Skip to content
Snippets Groups Projects

Compare revisions

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

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • normann/preprocessor
  • Dynare/preprocessor
  • FerhatMihoubi/preprocessor
  • MichelJuillard/preprocessor
  • sebastien/preprocessor
  • lnsongxf/preprocessor
  • albop/preprocessor
  • DoraK/preprocessor
  • amg/preprocessor
  • wmutschl/preprocessor
  • JohannesPfeifer/preprocessor
11 results
Select Git revision
  • 4.6
  • 5.x
  • aux_vars_fix
  • julia
  • master
  • pylib
  • rework_pac
  • uop
  • wasm
  • created_preprocessor_repo
  • julia-6.2.0
11 results
Show changes
Showing
with 14522 additions and 14039 deletions
/* /*
* Copyright (C) 2003-2018 Dynare Team * Copyright © 2003-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -14,24 +14,29 @@ ...@@ -14,24 +14,29 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <cstdlib> #include <algorithm>
#include <cassert> #include <cassert>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream> #include <iostream>
#include <regex> #include <iterator>
#include <ranges>
#include <boost/filesystem.hpp>
#include "DataTree.hh" #include "DataTree.hh"
bool DataTree::no_commutativity = false;
void void
DataTree::initConstants() DataTree::initConstants()
{ {
Zero = AddNonNegativeConstant("0"); Zero = AddNonNegativeConstant("0");
One = AddNonNegativeConstant("1"); One = AddNonNegativeConstant("1");
Two = AddNonNegativeConstant("2"); Two = AddNonNegativeConstant("2");
Three = AddNonNegativeConstant("3");
MinusOne = AddUMinus(One); MinusOne = AddUMinus(One);
...@@ -42,37 +47,37 @@ DataTree::initConstants() ...@@ -42,37 +47,37 @@ DataTree::initConstants()
Pi = AddNonNegativeConstant("3.141592653589793"); Pi = AddNonNegativeConstant("3.141592653589793");
} }
DataTree::DataTree(SymbolTable &symbol_table_arg, DataTree::DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, ExternalFunctionsTable& external_functions_table_arg,
bool is_dynamic_arg) : HeterogeneityTable& heterogeneity_table_arg, bool is_dynamic_arg) :
symbol_table {symbol_table_arg}, symbol_table {symbol_table_arg},
num_constants {num_constants_arg}, num_constants {num_constants_arg},
external_functions_table {external_functions_table_arg}, external_functions_table {external_functions_table_arg},
heterogeneity_table {heterogeneity_table_arg},
is_dynamic {is_dynamic_arg} is_dynamic {is_dynamic_arg}
{ {
initConstants(); initConstants();
} }
DataTree::~DataTree() = default;
DataTree::DataTree(const DataTree& d) : DataTree::DataTree(const DataTree& d) :
symbol_table {d.symbol_table}, symbol_table {d.symbol_table},
num_constants {d.num_constants}, num_constants {d.num_constants},
external_functions_table {d.external_functions_table}, external_functions_table {d.external_functions_table},
heterogeneity_table {d.heterogeneity_table},
is_dynamic {d.is_dynamic}, is_dynamic {d.is_dynamic},
local_variables_vector {d.local_variables_vector} local_variables_vector {d.local_variables_vector}
{ {
// Constants must be initialized first because they are used in some Add* methods // Constants must be initialized first because they are used in some Add* methods
initConstants(); initConstants();
// See commment in DataTree::operator=() for the rationale
for (int symb_id : d.local_variables_vector)
local_variables_table[symb_id] = d.local_variables_table.at(symb_id)->clone(*this);
for (const auto& it : d.node_list) for (const auto& it : d.node_list)
it->clone(*this); it->clone(*this);
assert(node_list.size() == d.node_list.size()); assert(node_list.size() == d.node_list.size());
for (const auto & it : d.local_variables_table)
local_variables_table[it.first] = it.second->clone(*this);
} }
DataTree& DataTree&
...@@ -81,6 +86,7 @@ DataTree::operator=(const DataTree &d) ...@@ -81,6 +86,7 @@ DataTree::operator=(const DataTree &d)
assert(&symbol_table == &d.symbol_table); assert(&symbol_table == &d.symbol_table);
assert(&num_constants == &d.num_constants); assert(&num_constants == &d.num_constants);
assert(&external_functions_table == &d.external_functions_table); assert(&external_functions_table == &d.external_functions_table);
assert(&heterogeneity_table == &d.heterogeneity_table);
assert(is_dynamic == d.is_dynamic); assert(is_dynamic == d.is_dynamic);
num_const_node_map.clear(); num_const_node_map.clear();
...@@ -91,6 +97,7 @@ DataTree::operator=(const DataTree &d) ...@@ -91,6 +97,7 @@ DataTree::operator=(const DataTree &d)
external_function_node_map.clear(); external_function_node_map.clear();
var_expectation_node_map.clear(); var_expectation_node_map.clear();
pac_expectation_node_map.clear(); pac_expectation_node_map.clear();
pac_target_nonstationary_node_map.clear();
first_deriv_external_function_node_map.clear(); first_deriv_external_function_node_map.clear();
second_deriv_external_function_node_map.clear(); second_deriv_external_function_node_map.clear();
...@@ -99,6 +106,14 @@ DataTree::operator=(const DataTree &d) ...@@ -99,6 +106,14 @@ DataTree::operator=(const DataTree &d)
// Constants must be initialized first because they are used in some Add* methods // Constants must be initialized first because they are used in some Add* methods
initConstants(); initConstants();
/* Model local variables must be next, because they can be evaluated in Add*
methods when the model equations are added. They need to be cloned in
order of appearance in the model block (hence with
local_variables_vector), because if there is a model_local_variable statement
the symbol IDs ordering may not be the right one (see dynare#1782) */
for (int symb_id : d.local_variables_vector)
local_variables_table[symb_id] = d.local_variables_table.at(symb_id)->clone(*this);
for (const auto& it : d.node_list) for (const auto& it : d.node_list)
it->clone(*this); it->clone(*this);
...@@ -106,25 +121,21 @@ DataTree::operator=(const DataTree &d) ...@@ -106,25 +121,21 @@ DataTree::operator=(const DataTree &d)
local_variables_vector = d.local_variables_vector; local_variables_vector = d.local_variables_vector;
for (const auto & it : d.local_variables_table)
local_variables_table[it.first] = it.second->clone(*this);
return *this; return *this;
} }
expr_t NumConstNode*
DataTree::AddNonNegativeConstant(const string& value) DataTree::AddNonNegativeConstant(const string& value)
{ {
int id = num_constants.AddNonNegativeConstant(value); int id = num_constants.AddNonNegativeConstant(value);
auto it = num_const_node_map.find(id); if (auto it = num_const_node_map.find(id); it != num_const_node_map.end())
if (it != num_const_node_map.end())
return it->second; return it->second;
auto sp = make_unique<NumConstNode>(*this, node_list.size(), id); auto sp = make_unique<NumConstNode>(*this, node_list.size(), id);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
num_const_node_map[id] = p; num_const_node_map.emplace(id, p);
return p; return p;
} }
...@@ -137,14 +148,13 @@ DataTree::AddVariable(int symb_id, int lag) ...@@ -137,14 +148,13 @@ DataTree::AddVariable(int symb_id, int lag)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
auto it = variable_node_map.find({ symb_id, lag }); if (auto it = variable_node_map.find({symb_id, lag}); it != variable_node_map.end())
if (it != variable_node_map.end())
return it->second; return it->second;
auto sp = make_unique<VariableNode>(*this, node_list.size(), symb_id, lag); auto sp = make_unique<VariableNode>(*this, node_list.size(), symb_id, lag);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
variable_node_map[{ symb_id, lag }] = p; variable_node_map.try_emplace({symb_id, lag}, p);
return p; return p;
} }
...@@ -154,7 +164,8 @@ DataTree::getVariable(int symb_id, int lag) const ...@@ -154,7 +164,8 @@ DataTree::getVariable(int symb_id, int lag) const
auto it = variable_node_map.find({symb_id, lag}); auto it = variable_node_map.find({symb_id, lag});
if (it == variable_node_map.end()) if (it == variable_node_map.end())
{ {
cerr << "DataTree::getVariable: unknown variable node for symb_id=" << symb_id << " and lag=" << lag << endl; cerr << "DataTree::getVariable: unknown variable node for symb_id=" << symb_id
<< " and lag=" << lag << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
return it->second; return it->second;
...@@ -163,8 +174,8 @@ DataTree::getVariable(int symb_id, int lag) const ...@@ -163,8 +174,8 @@ DataTree::getVariable(int symb_id, int lag) const
bool bool
DataTree::ParamUsedWithLeadLagInternal() const DataTree::ParamUsedWithLeadLagInternal() const
{ {
for (const auto & it : variable_node_map) for (const auto& [symb_lag, expr] : variable_node_map)
if (symbol_table.getType(it.first.first) == SymbolType::parameter && it.first.second != 0) if (symbol_table.getType(symb_lag.first) == SymbolType::parameter && symb_lag.second != 0)
return true; return true;
return false; return false;
} }
...@@ -172,30 +183,38 @@ DataTree::ParamUsedWithLeadLagInternal() const ...@@ -172,30 +183,38 @@ DataTree::ParamUsedWithLeadLagInternal() const
expr_t expr_t
DataTree::AddPlus(expr_t iArg1, expr_t iArg2) DataTree::AddPlus(expr_t iArg1, expr_t iArg2)
{ {
if (iArg1 != Zero && iArg2 != Zero) if (iArg2 == Zero)
{ return iArg1;
if (iArg1 == Zero)
return iArg2;
// Simplify x+(-y) in x-y // Simplify x+(-y) in x-y
auto *uarg2 = dynamic_cast<UnaryOpNode *>(iArg2); if (auto uarg2 = dynamic_cast<UnaryOpNode*>(iArg2);
if (uarg2 != nullptr && uarg2->get_op_code() == UnaryOpcode::uminus) uarg2 && uarg2->op_code == UnaryOpcode::uminus)
return AddMinus(iArg1, uarg2->get_arg()); return AddMinus(iArg1, uarg2->arg);
// Simplify (-x)+y in y-x
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);
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);
barg2 && barg2->op_code == BinaryOpcode::minus && barg2->arg2 == iArg1)
return barg2->arg1;
// To treat commutativity of "+" // To treat commutativity of "+"
// Nodes iArg1 and iArg2 are sorted by index // Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx) if (iArg1->idx > iArg2->idx && !no_commutativity) // NOLINT(clang-analyzer-core.NullDereference)
{ swap(iArg1, iArg2);
expr_t tmp = iArg1;
iArg1 = iArg2;
iArg2 = tmp;
}
return AddBinaryOp(iArg1, BinaryOpcode::plus, iArg2); return AddBinaryOp(iArg1, BinaryOpcode::plus, iArg2);
} }
else if (iArg1 != Zero)
return iArg1;
else if (iArg2 != Zero)
return iArg2;
else
return Zero;
}
expr_t expr_t
DataTree::AddMinus(expr_t iArg1, expr_t iArg2) DataTree::AddMinus(expr_t iArg1, expr_t iArg2)
...@@ -209,53 +228,71 @@ DataTree::AddMinus(expr_t iArg1, expr_t iArg2) ...@@ -209,53 +228,71 @@ DataTree::AddMinus(expr_t iArg1, expr_t iArg2)
if (iArg1 == iArg2) if (iArg1 == iArg2)
return Zero; return Zero;
// Simplify x-(-y) in x+y
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);
barg1 && barg1->op_code == BinaryOpcode::plus)
{
if (barg1->arg2 == iArg2)
return barg1->arg1;
if (barg1->arg1 == iArg2)
return barg1->arg2;
}
return AddBinaryOp(iArg1, BinaryOpcode::minus, iArg2); return AddBinaryOp(iArg1, BinaryOpcode::minus, iArg2);
} }
expr_t expr_t
DataTree::AddUMinus(expr_t iArg1) DataTree::AddUMinus(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
{ return Zero;
// Simplify -(-x) in x // Simplify -(-x) in x
auto *uarg = dynamic_cast<UnaryOpNode *>(iArg1); if (auto uarg = dynamic_cast<UnaryOpNode*>(iArg1); uarg && uarg->op_code == UnaryOpcode::uminus)
if (uarg != nullptr && uarg->get_op_code() == UnaryOpcode::uminus) return uarg->arg;
return uarg->get_arg();
return AddUnaryOp(UnaryOpcode::uminus, iArg1); return AddUnaryOp(UnaryOpcode::uminus, iArg1);
} }
else
return Zero;
}
expr_t expr_t
DataTree::AddTimes(expr_t iArg1, expr_t iArg2) DataTree::AddTimes(expr_t iArg1, expr_t iArg2)
{ {
if (iArg1 == Zero || iArg2 == Zero)
return Zero;
if (iArg1 == One)
return iArg2;
if (iArg2 == One)
return iArg1;
if (iArg1 == MinusOne) if (iArg1 == MinusOne)
return AddUMinus(iArg2); return AddUMinus(iArg2);
else if (iArg2 == MinusOne)
if (iArg2 == MinusOne)
return AddUMinus(iArg1); return AddUMinus(iArg1);
else if (iArg1 != Zero && iArg1 != One && iArg2 != Zero && iArg2 != One)
{ // Simplify (x/y)*y in x
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);
barg2 && barg2->op_code == BinaryOpcode::divide && barg2->arg2 == iArg1)
return barg2->arg1;
// To treat commutativity of "*" // To treat commutativity of "*"
// Nodes iArg1 and iArg2 are sorted by index // Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx) if (iArg1->idx > iArg2->idx && !no_commutativity) // NOLINT(clang-analyzer-core.NullDereference)
{ swap(iArg1, iArg2);
expr_t tmp = iArg1;
iArg1 = iArg2;
iArg2 = tmp;
}
return AddBinaryOp(iArg1, BinaryOpcode::times, iArg2); return AddBinaryOp(iArg1, BinaryOpcode::times, iArg2);
} }
else if (iArg1 != Zero && iArg1 != One && iArg2 == One)
return iArg1;
else if (iArg2 != Zero && iArg2 != One && iArg1 == One)
return iArg2;
else if (iArg2 == One && iArg1 == One)
return One;
else
return Zero;
}
expr_t expr_t
DataTree::AddDivide(expr_t iArg1, expr_t iArg2) noexcept(false) DataTree::AddDivide(expr_t iArg1, expr_t iArg2) noexcept(false)
...@@ -276,6 +313,21 @@ DataTree::AddDivide(expr_t iArg1, expr_t iArg2) noexcept(false) ...@@ -276,6 +313,21 @@ DataTree::AddDivide(expr_t iArg1, expr_t iArg2) noexcept(false)
if (iArg1 == iArg2) if (iArg1 == iArg2)
return One; return One;
// Simplify x/(1/y) in x*y
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);
barg1 && barg1->op_code == BinaryOpcode::times)
{
if (barg1->arg2 == iArg2)
return barg1->arg1;
if (barg1->arg1 == iArg2)
return barg1->arg2;
}
return AddBinaryOp(iArg1, BinaryOpcode::divide, iArg2); return AddBinaryOp(iArg1, BinaryOpcode::divide, iArg2);
} }
...@@ -318,16 +370,20 @@ DataTree::AddDifferent(expr_t iArg1, expr_t iArg2) ...@@ -318,16 +370,20 @@ DataTree::AddDifferent(expr_t iArg1, expr_t iArg2)
expr_t expr_t
DataTree::AddPower(expr_t iArg1, expr_t iArg2) DataTree::AddPower(expr_t iArg1, expr_t iArg2)
{ {
if (iArg1 != Zero && iArg2 != Zero && iArg1 != One && iArg2 != One) // This one comes first, because 0⁰=1
return AddBinaryOp(iArg1, BinaryOpcode::power, iArg2); if (iArg2 == Zero)
else if (iArg1 == One)
return One;
else if (iArg2 == One)
return iArg1;
else if (iArg2 == Zero)
return One; return One;
else
if (iArg1 == Zero)
return Zero; return Zero;
if (iArg1 == One)
return One;
if (iArg2 == One)
return iArg1;
return AddBinaryOp(iArg1, BinaryOpcode::power, iArg2);
} }
expr_t expr_t
...@@ -340,167 +396,197 @@ DataTree::AddPowerDeriv(expr_t iArg1, expr_t iArg2, int powerDerivOrder) ...@@ -340,167 +396,197 @@ DataTree::AddPowerDeriv(expr_t iArg1, expr_t iArg2, int powerDerivOrder)
expr_t expr_t
DataTree::AddDiff(expr_t iArg1) DataTree::AddDiff(expr_t iArg1)
{ {
if (iArg1->maxLead() > 0)
// Issue preprocessor#21: always expand diffs with leads
return AddMinus(iArg1, iArg1->decreaseLeadsLags(1));
return AddUnaryOp(UnaryOpcode::diff, iArg1); return AddUnaryOp(UnaryOpcode::diff, iArg1);
} }
expr_t 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, string(name), lags); return AddUnaryOp(UnaryOpcode::adl, iArg1, 0, 0, 0, name, lags);
} }
expr_t expr_t
DataTree::AddExp(expr_t iArg1) DataTree::AddExp(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::exp, iArg1);
else
return One; return One;
return AddUnaryOp(UnaryOpcode::exp, iArg1);
} }
expr_t expr_t
DataTree::AddLog(expr_t iArg1) DataTree::AddLog(expr_t iArg1)
{ {
if (iArg1 != Zero && iArg1 != One) if (iArg1 == One)
return AddUnaryOp(UnaryOpcode::log, iArg1);
else if (iArg1 == One)
return Zero; return Zero;
else
if (iArg1 == Zero)
{ {
cerr << "ERROR: log(0) not defined!" << endl; cerr << "ERROR: log(0) not defined!" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Simplify log(1/x) in −log(x)
if (auto barg1 = dynamic_cast<BinaryOpNode*>(iArg1);
barg1 && barg1->op_code == BinaryOpcode::divide && barg1->arg1 == One)
return AddUMinus(AddLog(barg1->arg2));
return AddUnaryOp(UnaryOpcode::log, iArg1);
} }
expr_t expr_t
DataTree::AddLog10(expr_t iArg1) DataTree::AddLog10(expr_t iArg1)
{ {
if (iArg1 != Zero && iArg1 != One) if (iArg1 == One)
return AddUnaryOp(UnaryOpcode::log10, iArg1);
else if (iArg1 == One)
return Zero; return Zero;
else
if (iArg1 == Zero)
{ {
cerr << "ERROR: log10(0) not defined!" << endl; cerr << "ERROR: log10(0) not defined!" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Simplify log₁₀(1/x) in −log₁₀(x)
if (auto barg1 = dynamic_cast<BinaryOpNode*>(iArg1);
barg1 && barg1->op_code == BinaryOpcode::divide && barg1->arg1 == One)
return AddUMinus(AddLog10(barg1->arg2));
return AddUnaryOp(UnaryOpcode::log10, iArg1);
} }
expr_t expr_t
DataTree::AddCos(expr_t iArg1) DataTree::AddCos(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::cos, iArg1);
else
return One; return One;
return AddUnaryOp(UnaryOpcode::cos, iArg1);
} }
expr_t expr_t
DataTree::AddSin(expr_t iArg1) DataTree::AddSin(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::sin, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::sin, iArg1);
} }
expr_t expr_t
DataTree::AddTan(expr_t iArg1) DataTree::AddTan(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::tan, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::tan, iArg1);
} }
expr_t expr_t
DataTree::AddAcos(expr_t iArg1) DataTree::AddAcos(expr_t iArg1)
{ {
if (iArg1 != One) if (iArg1 == One)
return AddUnaryOp(UnaryOpcode::acos, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::acos, iArg1);
} }
expr_t expr_t
DataTree::AddAsin(expr_t iArg1) DataTree::AddAsin(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::asin, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::asin, iArg1);
} }
expr_t expr_t
DataTree::AddAtan(expr_t iArg1) DataTree::AddAtan(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::atan, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::atan, iArg1);
} }
expr_t expr_t
DataTree::AddCosh(expr_t iArg1) DataTree::AddCosh(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::cosh, iArg1);
else
return One; return One;
return AddUnaryOp(UnaryOpcode::cosh, iArg1);
} }
expr_t expr_t
DataTree::AddSinh(expr_t iArg1) DataTree::AddSinh(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::sinh, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::sinh, iArg1);
} }
expr_t expr_t
DataTree::AddTanh(expr_t iArg1) DataTree::AddTanh(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::tanh, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::tanh, iArg1);
} }
expr_t expr_t
DataTree::AddAcosh(expr_t iArg1) DataTree::AddAcosh(expr_t iArg1)
{ {
if (iArg1 != One) if (iArg1 == One)
return AddUnaryOp(UnaryOpcode::acosh, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::acosh, iArg1);
} }
expr_t expr_t
DataTree::AddAsinh(expr_t iArg1) DataTree::AddAsinh(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::asinh, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::asinh, iArg1);
} }
expr_t expr_t
DataTree::AddAtanh(expr_t iArg1) DataTree::AddAtanh(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::atanh, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::atanh, iArg1);
} }
expr_t expr_t
DataTree::AddSqrt(expr_t iArg1) DataTree::AddSqrt(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return Zero;
if (iArg1 == One)
return One;
return AddUnaryOp(UnaryOpcode::sqrt, iArg1); return AddUnaryOp(UnaryOpcode::sqrt, iArg1);
else }
expr_t
DataTree::AddCbrt(expr_t iArg1)
{
if (iArg1 == Zero)
return Zero; return Zero;
if (iArg1 == One)
return One;
return AddUnaryOp(UnaryOpcode::cbrt, iArg1);
} }
expr_t expr_t
...@@ -508,9 +594,10 @@ DataTree::AddAbs(expr_t iArg1) ...@@ -508,9 +594,10 @@ DataTree::AddAbs(expr_t iArg1)
{ {
if (iArg1 == Zero) if (iArg1 == Zero)
return Zero; return Zero;
if (iArg1 == One) if (iArg1 == One)
return One; return One;
else
return AddUnaryOp(UnaryOpcode::abs, iArg1); return AddUnaryOp(UnaryOpcode::abs, iArg1);
} }
...@@ -519,19 +606,29 @@ DataTree::AddSign(expr_t iArg1) ...@@ -519,19 +606,29 @@ DataTree::AddSign(expr_t iArg1)
{ {
if (iArg1 == Zero) if (iArg1 == Zero)
return Zero; return Zero;
if (iArg1 == One) if (iArg1 == One)
return One; return One;
else
return AddUnaryOp(UnaryOpcode::sign, iArg1); return AddUnaryOp(UnaryOpcode::sign, iArg1);
} }
expr_t expr_t
DataTree::AddErf(expr_t iArg1) DataTree::AddErf(expr_t iArg1)
{ {
if (iArg1 != Zero) if (iArg1 == Zero)
return AddUnaryOp(UnaryOpcode::erf, iArg1);
else
return Zero; return Zero;
return AddUnaryOp(UnaryOpcode::erf, iArg1);
}
expr_t
DataTree::AddErfc(expr_t iArg1)
{
if (iArg1 == Zero)
return One;
return AddUnaryOp(UnaryOpcode::erfc, iArg1);
} }
expr_t expr_t
...@@ -573,7 +670,8 @@ DataTree::AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id) ...@@ -573,7 +670,8 @@ DataTree::AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id)
expr_t expr_t
DataTree::AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id) DataTree::AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id)
{ {
return AddUnaryOp(UnaryOpcode::steadyStateParam2ndDeriv, iArg1, 0, param1_symb_id, param2_symb_id); return AddUnaryOp(UnaryOpcode::steadyStateParam2ndDeriv, iArg1, 0, param1_symb_id,
param2_symb_id);
} }
expr_t expr_t
...@@ -585,35 +683,49 @@ DataTree::AddExpectation(int iArg1, expr_t iArg2) ...@@ -585,35 +683,49 @@ DataTree::AddExpectation(int iArg1, expr_t iArg2)
expr_t expr_t
DataTree::AddVarExpectation(const string& model_name) DataTree::AddVarExpectation(const string& model_name)
{ {
auto it = var_expectation_node_map.find(model_name); if (auto it = var_expectation_node_map.find(model_name); it != var_expectation_node_map.end())
if (it != var_expectation_node_map.end())
return it->second; return it->second;
auto sp = make_unique<VarExpectationNode>(*this, node_list.size(), model_name); auto sp = make_unique<VarExpectationNode>(*this, node_list.size(), model_name);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
var_expectation_node_map[model_name] = p; var_expectation_node_map.emplace(model_name, p);
return p; return p;
} }
expr_t expr_t
DataTree::AddPacExpectation(const string& model_name) DataTree::AddPacExpectation(const string& model_name)
{ {
auto it = pac_expectation_node_map.find(model_name); if (auto it = pac_expectation_node_map.find(model_name); it != pac_expectation_node_map.end())
if (it != pac_expectation_node_map.end())
return it->second; return it->second;
auto sp = make_unique<PacExpectationNode>(*this, node_list.size(), model_name); auto sp = make_unique<PacExpectationNode>(*this, node_list.size(), model_name);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
pac_expectation_node_map[model_name] = p; pac_expectation_node_map.emplace(model_name, p);
return p; return p;
} }
expr_t expr_t
DataTree::AddPacTargetNonstationary(const string& model_name)
{
if (auto it = pac_target_nonstationary_node_map.find(model_name);
it != pac_target_nonstationary_node_map.end())
return it->second;
auto sp = make_unique<PacTargetNonstationaryNode>(*this, node_list.size(), model_name);
auto p = sp.get();
node_list.push_back(move(sp));
pac_target_nonstationary_node_map.emplace(model_name, p);
return p;
}
BinaryOpNode*
DataTree::AddEqual(expr_t iArg1, expr_t iArg2) DataTree::AddEqual(expr_t iArg1, expr_t iArg2)
{ {
return AddBinaryOp(iArg1, BinaryOpcode::equal, 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));
} }
void void
...@@ -622,11 +734,10 @@ DataTree::AddLocalVariable(int symb_id, expr_t value) noexcept(false) ...@@ -622,11 +734,10 @@ DataTree::AddLocalVariable(int symb_id, expr_t value) noexcept(false)
assert(symbol_table.getType(symb_id) == SymbolType::modelLocalVariable); assert(symbol_table.getType(symb_id) == SymbolType::modelLocalVariable);
// Throw an exception if symbol already declared // Throw an exception if symbol already declared
auto it = local_variables_table.find(symb_id); if (local_variables_table.contains(symb_id))
if (it != local_variables_table.end()) throw LocalVariableException {symbol_table.getName(symb_id)};
throw LocalVariableException(symbol_table.getName(symb_id));
local_variables_table[symb_id] = value; local_variables_table.emplace(symb_id, value);
local_variables_vector.push_back(symb_id); local_variables_vector.push_back(symb_id);
} }
...@@ -635,157 +746,150 @@ DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments) ...@@ -635,157 +746,150 @@ DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments)
{ {
assert(symbol_table.getType(symb_id) == SymbolType::externalFunction); assert(symbol_table.getType(symb_id) == SymbolType::externalFunction);
auto it = external_function_node_map.find({ arguments, symb_id }); if (auto it = external_function_node_map.find({arguments, symb_id});
if (it != external_function_node_map.end()) it != external_function_node_map.end())
return it->second; return it->second;
auto sp = make_unique<ExternalFunctionNode>(*this, node_list.size(), symb_id, arguments); auto sp = make_unique<ExternalFunctionNode>(*this, node_list.size(), symb_id, arguments);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
external_function_node_map[{ arguments, symb_id }] = p; external_function_node_map.try_emplace({arguments, symb_id}, p);
return p; return p;
} }
expr_t expr_t
DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index) DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index)
{ {
assert(symbol_table.getType(top_level_symb_id) == SymbolType::externalFunction); assert(symbol_table.getType(top_level_symb_id) == SymbolType::externalFunction);
auto it if (auto it
= first_deriv_external_function_node_map.find({arguments, input_index, top_level_symb_id}); = first_deriv_external_function_node_map.find({arguments, input_index, top_level_symb_id});
if (it != first_deriv_external_function_node_map.end()) it != first_deriv_external_function_node_map.end())
return it->second; return it->second;
auto sp = make_unique<FirstDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index); auto sp = make_unique<FirstDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id,
arguments, input_index);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
first_deriv_external_function_node_map[{ arguments, input_index, top_level_symb_id }] = p; first_deriv_external_function_node_map.try_emplace({arguments, input_index, top_level_symb_id},
p);
return p; return p;
} }
expr_t expr_t
DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2) DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index1, int input_index2)
{ {
assert(symbol_table.getType(top_level_symb_id) == SymbolType::externalFunction); assert(symbol_table.getType(top_level_symb_id) == SymbolType::externalFunction);
auto it if (auto it = second_deriv_external_function_node_map.find(
= second_deriv_external_function_node_map.find({ arguments, input_index1, input_index2, {arguments, input_index1, input_index2, top_level_symb_id});
top_level_symb_id }); it != second_deriv_external_function_node_map.end())
if (it != second_deriv_external_function_node_map.end())
return it->second; return it->second;
auto sp = make_unique<SecondDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index1, input_index2); auto sp = make_unique<SecondDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id,
arguments, input_index1, input_index2);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
second_deriv_external_function_node_map[{ arguments, input_index1, input_index2, top_level_symb_id }] = p; second_deriv_external_function_node_map.try_emplace(
{arguments, input_index1, input_index2, top_level_symb_id}, p);
return p; return p;
} }
expr_t
DataTree::AddSum(expr_t arg)
{
return AddUnaryOp(UnaryOpcode::sum, arg);
}
bool bool
DataTree::isSymbolUsed(int symb_id) const DataTree::isSymbolUsed(int symb_id) const
{ {
for (const auto & it : variable_node_map) if (ranges::any_of(views::keys(variable_node_map),
if (it.first.first == symb_id) [=](const auto& symb_lag) { return symb_lag.first == symb_id; }))
return true; return true;
if (local_variables_table.find(symb_id) != local_variables_table.end()) if (local_variables_table.contains(symb_id))
return true; return true;
return false; return false;
} }
int int
DataTree::getDerivID(int symb_id, int lag) const noexcept(false) DataTree::getDerivID([[maybe_unused]] int symb_id, [[maybe_unused]] int lag) const noexcept(false)
{ {
throw UnknownDerivIDException(); throw UnknownDerivIDException();
} }
SymbolType SymbolType
DataTree::getTypeByDerivID(int deriv_id) const noexcept(false) DataTree::getTypeByDerivID([[maybe_unused]] int deriv_id) const noexcept(false)
{ {
throw UnknownDerivIDException(); throw UnknownDerivIDException();
} }
int int
DataTree::getLagByDerivID(int deriv_id) const noexcept(false) DataTree::getLagByDerivID([[maybe_unused]] int deriv_id) const noexcept(false)
{ {
throw UnknownDerivIDException(); throw UnknownDerivIDException();
} }
int int
DataTree::getSymbIDByDerivID(int deriv_id) const noexcept(false) DataTree::getSymbIDByDerivID([[maybe_unused]] int deriv_id) const noexcept(false)
{ {
throw UnknownDerivIDException(); throw UnknownDerivIDException();
} }
void
DataTree::addAllParamDerivId(set<int> &deriv_id_set)
{
}
int int
DataTree::getDynJacobianCol(int deriv_id) const noexcept(false) DataTree::getTypeSpecificIDByDerivID([[maybe_unused]] int deriv_id) const
{ {
throw UnknownDerivIDException(); throw UnknownDerivIDException();
} }
bool void
DataTree::isUnaryOpUsed(UnaryOpcode opcode) const DataTree::addAllParamDerivId([[maybe_unused]] set<int>& deriv_id_set)
{ {
for (const auto & it : unary_op_node_map)
if (get<1>(it.first) == opcode)
return true;
return false;
} }
bool bool
DataTree::isBinaryOpUsed(BinaryOpcode opcode) const DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
{ {
for (const auto & it : binary_op_node_map) return ranges::any_of(views::keys(unary_op_node_map),
if (get<2>(it.first) == opcode) [=](const auto& key) { return get<1>(key) == opcode; });
return true;
return false;
} }
bool bool
DataTree::isTrinaryOpUsed(TrinaryOpcode opcode) const DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const
{ {
for (const auto & it : trinary_op_node_map) set<int> var;
if (get<3>(it.first) == opcode) for (const auto& [key, value] : unary_op_node_map)
return true; if (get<1>(key) == opcode)
return false;
}
bool
DataTree::isExternalFunctionUsed(int symb_id) const
{ {
for (const auto & it : external_function_node_map) value->collectVariables(type, var);
if (it.first.second == symb_id) if (!var.empty())
return true; return true;
}
return false; return false;
} }
bool bool
DataTree::isFirstDerivExternalFunctionUsed(int symb_id) const DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
{ {
for (const auto & it : first_deriv_external_function_node_map) return ranges::any_of(views::keys(binary_op_node_map),
if (get<2>(it.first) == symb_id) [=](const auto& key) { return get<2>(key) == opcode; });
return true;
return false;
} }
bool bool
DataTree::isSecondDerivExternalFunctionUsed(int symb_id) const DataTree::isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const
{ {
for (const auto & it : second_deriv_external_function_node_map) set<int> var;
if (get<3>(it.first) == symb_id) for (const auto& [key, value] : binary_op_node_map)
if (get<2>(key) == opcode)
{
value->collectVariables(type, var);
if (!var.empty())
return true; return true;
}
return false; return false;
} }
...@@ -793,94 +897,94 @@ int ...@@ -793,94 +897,94 @@ int
DataTree::minLagForSymbol(int symb_id) const DataTree::minLagForSymbol(int symb_id) const
{ {
int r = 0; int r = 0;
for (const auto & it : variable_node_map) for (const auto& [symb_lag, expr] : variable_node_map)
if (it.first.first == symb_id && it.first.second < r) if (symb_lag.first == symb_id)
r = it.first.second; r = min(r, symb_lag.second);
return r; return r;
} }
void void
DataTree::writePowerDerivCHeader(ostream &output) const DataTree::writeCHelpersDefinition(ostream& output) const
{ {
if (isBinaryOpUsed(BinaryOpcode::powerDeriv)) if (isBinaryOpUsed(BinaryOpcode::powerDeriv))
output << "double getPowerDeriv(double, double, int);" << endl; output << "// The k-th derivative of x^p" << endl
} << "inline double" << endl
<< "getPowerDeriv(double x, double p, int k)" << endl
void
DataTree::writePowerDeriv(ostream &output) const
{
if (isBinaryOpUsed(BinaryOpcode::powerDeriv))
output << "/*" << endl
<< " * The k-th derivative of x^p" << endl
<< " */" << endl
<< "double getPowerDeriv(double x, double p, int k)" << endl
<< "{" << endl << "{" << endl
<< "#ifdef _MSC_VER" << endl << " if (fabs(x) < " << power_deriv_near_zero
<< "# define nearbyint(x) (fabs((x)-floor(x)) < fabs((x)-ceil(x)) ? floor(x) : ceil(x))" << endl << " && p >= 0 && k > p && fabs(p-nearbyint(p)) < " << power_deriv_near_zero << ')'
<< "#endif" << endl << endl
<< " if ( fabs(x) < " << near_zero << " && p > 0 && k > p && fabs(p-nearbyint(p)) < " << near_zero << " )" << endl
<< " return 0.0;" << endl << " return 0.0;" << endl
<< " else" << endl << " else" << endl
<< " {" << endl << " {" << endl
<< " int i = 0;" << endl
<< " double dxp = pow(x, p-k);" << endl << " double dxp = pow(x, p-k);" << endl
<< " for (; i<k; i++)" << endl << " for (int i = 0; i<k; i++)" << endl
<< " dxp *= p--;" << endl << " dxp *= p--;" << endl
<< " return dxp;" << endl << " return dxp;" << endl
<< " }" << endl << " }" << endl
<< "}" << endl; << "}" << endl;
if (isUnaryOpUsed(UnaryOpcode::sign))
output << "inline double" << endl
<< "sign(double x)" << endl
<< "{" << endl
<< " return (x > 0) ? 1 : ((x < 0) ? -1 : 0);" << endl
<< "}" << endl;
} }
void void
DataTree::writeNormcdfCHeader(ostream &output) const DataTree::writeCHelpersDeclaration(ostream& output) const
{ {
#if defined(_WIN32) || defined(__CYGWIN32__) if (isBinaryOpUsed(BinaryOpcode::powerDeriv))
if (isTrinaryOpUsed(TrinaryOpcode::normcdf)) output << "extern inline double getPowerDeriv(double x, double p, int k);" << endl;
output << "#ifdef _MSC_VER" << endl if (isUnaryOpUsed(UnaryOpcode::sign))
<< "double normcdf(double);" << endl output << "extern inline double sign(double x);" << endl;
<< "#endif" << endl;
#endif
} }
void vector<string>
DataTree::writeNormcdf(ostream &output) const DataTree::strsplit(string_view str, char delim)
{ {
#if defined(_WIN32) || defined(__CYGWIN32__) vector<string> result;
if (isTrinaryOpUsed(TrinaryOpcode::normcdf)) while (true)
output << endl {
<< "#ifdef _MSC_VER" << endl size_t idx {str.find(delim)};
<< "/*" << endl if (auto sub {str.substr(0, idx)}; !sub.empty())
<< " * Define normcdf for MSVC compiler" << endl result.emplace_back(sub);
<< " */" << endl if (idx == string_view::npos)
<< "double normcdf(double x)" << endl break;
<< "{" << endl str.remove_prefix(idx + 1);
<< "#if _MSC_VER >= 1700" << endl }
<< " return 0.5 * erfc(-x * M_SQRT1_2);" << endl return result;
<< "#else" << endl }
<< " // From http://www.johndcook.com/blog/cpp_phi" << endl
<< " double a1 = 0.254829592;" << endl filesystem::path
<< " double a2 = -0.284496736;" << endl DataTree::packageDir(const string_view& package)
<< " double a3 = 1.421413741;" << endl {
<< " double a4 = -1.453152027;" << endl filesystem::path d;
<< " double a5 = 1.061405429;" << endl for (const auto& it : strsplit(package, '.'))
<< " double p = 0.3275911;" << endl d /= "+" + it;
<< " int sign = (x < 0) ? -1 : 1;" << endl return d;
<< " x = fabs(x)/sqrt(2.0);" << endl
<< " // From the Handbook of Mathematical Functions by Abramowitz and Stegun, formula 7.1.26" << endl
<< " double t = 1.0/(1.0 + p*x);" << endl
<< " double y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);" << endl
<< " return 0.5*(1.0 + sign*y);" << endl
<< "#endif" << endl
<< "}" << endl
<< "#endif" << endl;
#endif
} }
string void
DataTree::packageDir(const string &package) DataTree::writeToFileIfModified(stringstream& new_contents, const filesystem::path& filename)
{ {
regex pat{"\\."}; ifstream old_file {filename, ios::in | ios::binary};
string dirname = "+" + regex_replace(package, pat, "/+"); if (old_file.is_open()
boost::filesystem::create_directories(dirname); && ranges::equal(istreambuf_iterator<char> {old_file}, istreambuf_iterator<char> {},
return dirname; istreambuf_iterator<char> {new_contents}, istreambuf_iterator<char> {}))
return;
old_file.close();
new_contents.seekg(0);
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);
}
ranges::copy(istreambuf_iterator<char> {new_contents}, istreambuf_iterator<char> {},
ostreambuf_iterator<char> {new_file});
new_file.close();
} }
/* /*
* Copyright (C) 2003-2018 Dynare Team * Copyright © 2003-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -14,27 +14,31 @@ ...@@ -14,27 +14,31 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _DATATREE_HH #ifndef DATA_TREE_HH
#define _DATATREE_HH #define DATA_TREE_HH
using namespace std; #include <cmath>
#include <filesystem>
#include <string> #include <iomanip>
#include <map> #include <map>
#include <vector> #include <memory>
#include <sstream> #include <sstream>
#include <iomanip> #include <string>
#include <cmath> #include <string_view>
#include <utility> #include <utility>
#include <vector>
#include "SymbolTable.hh"
#include "NumericalConstants.hh"
#include "ExternalFunctionsTable.hh"
#include "ExprNode.hh" #include "ExprNode.hh"
#include "ExternalFunctionsTable.hh"
#include "HeterogeneityTable.hh"
#include "NumericalConstants.hh"
#include "SubModel.hh" #include "SubModel.hh"
#include "SymbolTable.hh"
using namespace std;
class DataTree class DataTree
{ {
...@@ -45,7 +49,11 @@ public: ...@@ -45,7 +49,11 @@ public:
NumericalConstants& num_constants; NumericalConstants& num_constants;
//! A reference to the external functions table //! A reference to the external functions table
ExternalFunctionsTable& external_functions_table; ExternalFunctionsTable& external_functions_table;
// A reference to the heterogeneity table
HeterogeneityTable& heterogeneity_table;
//! Is it possible to use leads/lags on variable nodes? //! Is it possible to use leads/lags on variable nodes?
/* NB: This data member cannot be replaced by a virtual method, because this information is needed
in AddVariable(), which itself can be called from the copy constructor. */
const bool is_dynamic; const bool is_dynamic;
private: private:
...@@ -57,8 +65,10 @@ private: ...@@ -57,8 +65,10 @@ private:
using variable_node_map_t = map<pair<int, int>, VariableNode*>; using variable_node_map_t = map<pair<int, int>, VariableNode*>;
variable_node_map_t variable_node_map; variable_node_map_t variable_node_map;
//! (arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags) -> UnaryOpNode //! (arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags) ->
using unary_op_node_map_t = map<tuple<expr_t, UnaryOpcode, int, int, int, string, vector<int>>, UnaryOpNode *>; //! UnaryOpNode
using unary_op_node_map_t
= map<tuple<expr_t, UnaryOpcode, int, int, int, string, vector<int>>, UnaryOpNode*>;
unary_op_node_map_t unary_op_node_map; unary_op_node_map_t unary_op_node_map;
//! ( arg1, arg2, opCode, order of Power Derivative) -> BinaryOpNode //! ( arg1, arg2, opCode, order of Power Derivative) -> BinaryOpNode
...@@ -81,68 +91,73 @@ private: ...@@ -81,68 +91,73 @@ private:
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; pac_expectation_node_map_t pac_expectation_node_map;
// model_name -> 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 // (arguments, deriv_idx, symb_id) -> FirstDerivExternalFunctionNode
using first_deriv_external_function_node_map_t = map<tuple<vector<expr_t>, int, int>, FirstDerivExternalFunctionNode *>; using first_deriv_external_function_node_map_t
= map<tuple<vector<expr_t>, int, int>, FirstDerivExternalFunctionNode*>;
first_deriv_external_function_node_map_t first_deriv_external_function_node_map; first_deriv_external_function_node_map_t first_deriv_external_function_node_map;
// (arguments, deriv_idx1, deriv_idx2, symb_id) -> SecondDerivExternalFunctionNode // (arguments, deriv_idx1, deriv_idx2, symb_id) -> SecondDerivExternalFunctionNode
using second_deriv_external_function_node_map_t = map<tuple<vector<expr_t>, int, int, int>, SecondDerivExternalFunctionNode *>; using second_deriv_external_function_node_map_t
= map<tuple<vector<expr_t>, int, int, int>, SecondDerivExternalFunctionNode*>;
second_deriv_external_function_node_map_t second_deriv_external_function_node_map; second_deriv_external_function_node_map_t second_deriv_external_function_node_map;
// Flag to disable simplifications related to commutativity of addition and multiplication
static bool no_commutativity;
protected: protected:
//! Stores local variables value (maps symbol ID to corresponding node) //! Stores local variables value (maps symbol ID to corresponding node)
map<int, expr_t> local_variables_table; map<int, expr_t> local_variables_table;
//! Stores the order of appearance of local variables in the model block. Needed following change in #563 //! Stores the order of appearance of local variables in the model block. Needed following change
//! in #563
vector<int> local_variables_vector; vector<int> local_variables_vector;
//! Internal implementation of ParamUsedWithLeadLag() //! Internal implementation of ParamUsedWithLeadLag()
bool ParamUsedWithLeadLagInternal() const; [[nodiscard]] bool ParamUsedWithLeadLagInternal() const;
/*! Takes a MATLAB/Octave package name (possibly with several levels nested using dots), /* Writes the contents of “new_contents” to the file “filename”. However, if
and returns the name of the corresponding filesystem directory (which the file already exists and would not be modified by this operation, then do
is created by the function if it does not exist). nothing. */
In practice the package nesting is used for the planner_objective (stored static void writeToFileIfModified(stringstream& new_contents, const filesystem::path& filename);
inside +objective subdir). */
static string packageDir(const string &package);
private: private:
const static int constants_precision{16}; constexpr static int constants_precision {16};
//! The list of nodes //! The list of nodes
vector<unique_ptr<ExprNode>> node_list; vector<unique_ptr<ExprNode>> node_list;
inline expr_t AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set = 0, int param1_symb_id = 0, int param2_symb_id = 0, const string &adl_param_name = "", const vector<int> &adl_lags = vector<int>()); inline expr_t AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set = 0,
inline expr_t AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder = 0); int param1_symb_id = 0, int param2_symb_id = 0,
const string& adl_param_name = "",
const vector<int>& adl_lags = vector<int>());
inline expr_t AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2,
int powerDerivOrder = 0);
inline expr_t AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3); inline expr_t AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3);
//! Initializes the predefined constants, used only from the constructors //! Initializes the predefined constants, used only from the constructors
void initConstants(); void initConstants();
public: public:
DataTree(SymbolTable &symbol_table_arg, DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, ExternalFunctionsTable& external_functions_table_arg,
bool is_static_args = false); HeterogeneityTable& heterogeneity_table_arg, bool is_dynamic_arg = false);
virtual virtual ~DataTree() = default;
~DataTree();
DataTree(const DataTree& d); DataTree(const DataTree& d);
DataTree(DataTree &&) = delete;
DataTree& operator=(const DataTree& d); DataTree& operator=(const DataTree& d);
DataTree & operator=(DataTree &&) = delete;
//! Some predefined constants //! Some predefined constants
expr_t Zero, One, Two, MinusOne, NaN, Infinity, MinusInfinity, Pi; NumConstNode *Zero, *One, *Two, *Three, *NaN, *Infinity, *Pi;
expr_t MinusOne, MinusInfinity;
//! Raised when a local parameter is declared twice //! Raised when a local parameter is declared twice
class LocalVariableException struct LocalVariableException
{ {
public:
string name; string name;
explicit LocalVariableException(string name_arg) : name{move(name_arg)}
{
}
}; };
class DivisionByZeroException class DivisionByZeroException
...@@ -151,13 +166,13 @@ public: ...@@ -151,13 +166,13 @@ public:
inline expr_t AddPossiblyNegativeConstant(double val); inline expr_t AddPossiblyNegativeConstant(double val);
//! Adds a non-negative numerical constant (possibly Inf or NaN) //! Adds a non-negative numerical constant (possibly Inf or NaN)
expr_t AddNonNegativeConstant(const string &value); NumConstNode* AddNonNegativeConstant(const string& value);
//! Adds a variable //! Adds a variable
VariableNode* AddVariable(int symb_id, int lag = 0); VariableNode* AddVariable(int symb_id, int lag = 0);
//! Gets a variable //! Gets a variable
/*! Same as AddVariable, except that it fails if the variable node has not /*! Same as AddVariable, except that it fails if the variable node has not
already been created */ already been created */
VariableNode *getVariable(int symb_id, int lag = 0) const; [[nodiscard]] VariableNode* getVariable(int symb_id, int lag = 0) const;
//! Adds "arg1+arg2" to model tree //! Adds "arg1+arg2" to model tree
expr_t AddPlus(expr_t iArg1, expr_t iArg2); expr_t AddPlus(expr_t iArg1, expr_t iArg2);
//! Adds "arg1-arg2" to model tree //! Adds "arg1-arg2" to model tree
...@@ -222,12 +237,16 @@ public: ...@@ -222,12 +237,16 @@ public:
expr_t AddAtanh(expr_t iArg1); expr_t AddAtanh(expr_t iArg1);
//! Adds "sqrt(arg)" to model tree //! Adds "sqrt(arg)" to model tree
expr_t AddSqrt(expr_t iArg1); expr_t AddSqrt(expr_t iArg1);
//! Adds "cbrt(arg)" to model tree
expr_t AddCbrt(expr_t iArg1);
//! Adds "abs(arg)" to model tree //! Adds "abs(arg)" to model tree
expr_t AddAbs(expr_t iArg1); expr_t AddAbs(expr_t iArg1);
//! Adds "sign(arg)" to model tree //! Adds "sign(arg)" to model tree
expr_t AddSign(expr_t iArg1); expr_t AddSign(expr_t iArg1);
//! Adds "erf(arg)" to model tree //! Adds "erf(arg)" to model tree
expr_t AddErf(expr_t iArg1); expr_t AddErf(expr_t iArg1);
//! Adds "erfc(arg)" to model tree
expr_t AddErfc(expr_t iArg1);
//! Adds "max(arg1,arg2)" to model tree //! Adds "max(arg1,arg2)" to model tree
expr_t AddMax(expr_t iArg1, expr_t iArg2); expr_t AddMax(expr_t iArg1, expr_t iArg2);
//! Adds "min(arg1,arg2)" to model tree //! Adds "min(arg1,arg2)" to model tree
...@@ -243,94 +262,136 @@ public: ...@@ -243,94 +262,136 @@ public:
//! Add 2nd derivative of steady state w.r.t. parameter to model tree //! 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); expr_t AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id);
//! Adds "arg1=arg2" to model tree //! Adds "arg1=arg2" to model tree
expr_t AddEqual(expr_t iArg1, expr_t iArg2); BinaryOpNode* AddEqual(expr_t iArg1, expr_t iArg2);
//! Adds "var_expectation(model_name)" to model tree //! 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 //! 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);
//! Adds a model local variable with its value //! Adds a model local variable with its value
void AddLocalVariable(int symb_id, expr_t value) noexcept(false); void AddLocalVariable(int symb_id, expr_t value) noexcept(false);
//! Adds an external function node //! Adds an external function node
expr_t AddExternalFunction(int symb_id, const vector<expr_t>& arguments); expr_t AddExternalFunction(int symb_id, const vector<expr_t>& arguments);
//! Adds an external function node for the first derivative of an external function //! Adds an external function node for the first derivative of an external function
expr_t AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index); expr_t AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index);
//! Adds an external function node for the second derivative of an external function //! Adds an external function node for the second derivative of an external function
expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2); expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index1, int input_index2);
// Adds "SUM(arg)" to model tree
expr_t AddSum(expr_t arg);
//! Checks if a given symbol is used somewhere in the data tree //! Checks if a given symbol is used somewhere in the data tree
bool isSymbolUsed(int symb_id) const; [[nodiscard]] bool isSymbolUsed(int symb_id) const;
//! Checks if a given unary op is used somewhere in the data tree //! Checks if a given unary op is used somewhere in the data tree
bool isUnaryOpUsed(UnaryOpcode opcode) const; [[nodiscard]] bool isUnaryOpUsed(UnaryOpcode opcode) const;
//! Checks if a given unary op is used somewhere in the data tree on an endogenous variable
[[nodiscard]] bool isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const;
//! Checks if a given binary op is used somewhere in the data tree //! Checks if a given binary op is used somewhere in the data tree
bool isBinaryOpUsed(BinaryOpcode opcode) const; [[nodiscard]] bool isBinaryOpUsed(BinaryOpcode opcode) const;
//! Checks if a given trinary op is used somewhere in the data tree //! Checks if a given binary op is used somewhere in the data tree on an endogenous variable
bool isTrinaryOpUsed(TrinaryOpcode opcode) const; [[nodiscard]] bool isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const;
//! Checks if a given external function is used somewhere in the data tree //! Returns the minimum lag (as a negative number) of the given symbol in the whole data tree (and
bool isExternalFunctionUsed(int symb_id) const; //! not only in the equations !!)
//! Checks if a given first derivative external function is used somewhere in the data tree
bool isFirstDerivExternalFunctionUsed(int symb_id) const;
//! Checks if a given second derivative external function is used somewhere in the data tree
bool isSecondDerivExternalFunctionUsed(int symb_id) const;
//! Returns the minimum lag (as a negative number) of the given symbol in the whole data tree (and not only in the equations !!)
/*! Returns 0 if the symbol is not used */ /*! Returns 0 if the symbol is not used */
int minLagForSymbol(int symb_id) const; [[nodiscard]] int minLagForSymbol(int symb_id) const;
//! Write the C Header for getPowerDeriv when use_dll is used /* Writes definitions of C function helpers (getPowerDeriv(), sign()) as
void writePowerDerivCHeader(ostream &output) const; inline functions */
//! Write getPowerDeriv in C void writeCHelpersDefinition(ostream& output) const;
void writePowerDeriv(ostream &output) const; /* Writes declarations of C function helpers (getPowerDeriv(), sign()) as
//! Write the C Header for normcdf when use_dll is used extern inline (external definition). Those need to be included in exactly
void writeNormcdfCHeader(ostream &output) const; one translation unit. That external definition will be used or not,
//! Write normcdf in C depending on the optimization decision by the compiler.
void writeNormcdf(ostream &output) const; See https://en.cppreference.com/w/c/language/inline */
void writeCHelpersDeclaration(ostream& output) const;
//! Thrown when trying to access an unknown variable by deriv_id //! Thrown when trying to access an unknown variable by deriv_id
class UnknownDerivIDException class UnknownDerivIDException
{ {
}; };
//! Raised when a trend is declared twice //! Raised when a trend is declared twice
class TrendException struct TrendException
{ {
public:
string name; string name;
explicit TrendException(string name_arg) : name{move(name_arg)} };
// Returns the derivation ID, or throws an exception if the derivation ID does not exist
[[nodiscard]] virtual int getDerivID(int symb_id, int lag) const noexcept(false);
// Get the type corresponding to a derivation ID
[[nodiscard]] virtual SymbolType getTypeByDerivID(int deriv_id) const noexcept(false);
// Get the lag corresponding to a derivation ID
[[nodiscard]] virtual int getLagByDerivID(int deriv_id) const noexcept(false);
// Get the symbol ID corresponding to a derivation ID
[[nodiscard]] virtual int getSymbIDByDerivID(int deriv_id) const noexcept(false);
// Get the type-specific ID corresponding to a derivation ID
[[nodiscard]] virtual int getTypeSpecificIDByDerivID(int deriv_id) const;
// Get the symbol name corresponding to a derivation ID
[[nodiscard]] string
getNameByDerivID(int deriv_id) const
{ {
return symbol_table.getName(getSymbIDByDerivID(deriv_id));
} }
};
//! Returns the derivation ID, or throws an exception if the derivation ID does not exist /* Returns the column of the Jacobian associated to a derivation ID.
virtual int getDerivID(int symb_id, int lag) const noexcept(false); The “sparse” argument selects between the legacy representation and the
virtual SymbolType getTypeByDerivID(int deriv_id) const noexcept(false); sparse representation. */
virtual int getLagByDerivID(int deriv_id) const noexcept(false); [[nodiscard]] virtual int
virtual int getSymbIDByDerivID(int deriv_id) const noexcept(false); getJacobianCol([[maybe_unused]] int deriv_id, [[maybe_unused]] bool sparse) const
//! Returns the column of the dynamic Jacobian associated to a derivation ID {
virtual int getDynJacobianCol(int deriv_id) const noexcept(false); throw UnknownDerivIDException();
//! Adds to the set all the deriv IDs corresponding to parameters }
virtual void addAllParamDerivId(set<int> &deriv_id_set);
//! Returns bool indicating whether DataTree represents a Dynamic Model (returns true in DynamicModel.hh) /* Returns the number of columns of the Jacobian
virtual bool The “sparse” argument selects between the legacy representation and the
isDynamic() const sparse representation. */
[[nodiscard]] virtual int
getJacobianColsNbr([[maybe_unused]] bool sparse) const
{ {
return false; throw UnknownDerivIDException();
}; }
//! Adds to the set all the deriv IDs corresponding to parameters
virtual void addAllParamDerivId(set<int>& deriv_id_set);
class UnknownLocalVariableException struct UnknownLocalVariableException
{ {
public:
//! Symbol ID //! Symbol ID
int id; int id;
explicit UnknownLocalVariableException(int id_arg) : id(id_arg)
{
}
}; };
expr_t getLocalVariable(int symb_id) const [[nodiscard]] expr_t
getLocalVariable(int symb_id, int lead_lag) const
{ {
auto it = local_variables_table.find(symb_id); auto it = local_variables_table.find(symb_id);
if (it == local_variables_table.end()) if (it == local_variables_table.end())
throw UnknownLocalVariableException(symb_id); throw UnknownLocalVariableException {symb_id};
/* In the following, the case without lead/lag is optimized. It makes a difference on models
with many nested model-local variables, see e.g.
https://forum.dynare.org/t/pre-processing-takes-very-long/26865 */
if (lead_lag == 0)
return it->second; return it->second;
else
return it->second->decreaseLeadsLags(-lead_lag);
} }
static void
setNoCommutativity()
{
no_commutativity = true;
}
/* Equivalent of MATLAB/Octave’s strsplit, except that it ignores empty
substring components (MATLAB/Octave adds them to the output); in
particular, returns an empty vector given an empty string. */
static vector<string> strsplit(string_view str, char delim);
/*! Takes a MATLAB/Octave package name (possibly with several levels nested using dots),
and returns the path to the corresponding filesystem directory.
In practice the package nesting is used for the planner_objective (stored
inside +objective subdir). */
static filesystem::path packageDir(const string_view& package);
}; };
inline expr_t inline expr_t
...@@ -341,7 +402,7 @@ DataTree::AddPossiblyNegativeConstant(double v) ...@@ -341,7 +402,7 @@ DataTree::AddPossiblyNegativeConstant(double v)
if (isnan(v)) if (isnan(v))
return NaN; return NaN;
if (isinf(v)) if (isinf(v))
return (v < 0 ? MinusInfinity : Infinity); return v < 0 ? MinusInfinity : Infinity;
bool neg = false; bool neg = false;
if (v < 0) if (v < 0)
...@@ -361,21 +422,23 @@ DataTree::AddPossiblyNegativeConstant(double v) ...@@ -361,21 +422,23 @@ DataTree::AddPossiblyNegativeConstant(double v)
} }
inline expr_t inline expr_t
DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int param1_symb_id, int param2_symb_id, const string &adl_param_name, const vector<int> &adl_lags) DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int param1_symb_id,
int param2_symb_id, const string& adl_param_name, const vector<int>& adl_lags)
{ {
// If the node already exists in tree, share it // If the node already exists in tree, share it
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,
if (it != unary_op_node_map.end()) param2_symb_id, adl_param_name, adl_lags});
it != unary_op_node_map.end())
return it->second; return it->second;
// Try to reduce to a constant // Try to reduce to a constant
// Case where arg is a constant and op_code == UnaryOpcode::uminus (i.e. we're adding a negative constant) is skipped // Case where arg is a constant and op_code == UnaryOpcode::uminus (i.e. we're adding a negative
auto *carg = dynamic_cast<NumConstNode *>(arg); // constant) is skipped
if (op_code != UnaryOpcode::uminus || carg == nullptr) if (auto carg = dynamic_cast<NumConstNode*>(arg); op_code != UnaryOpcode::uminus || !carg)
{ {
try try
{ {
double argval = arg->eval(eval_context_t()); double argval = arg->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double val = UnaryOpNode::eval_opcode(op_code, argval); double val = UnaryOpNode::eval_opcode(op_code, argval);
return AddPossiblyNegativeConstant(val); return AddPossiblyNegativeConstant(val);
} }
...@@ -384,25 +447,28 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int ...@@ -384,25 +447,28 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int
} }
} }
auto sp = make_unique<UnaryOpNode>(*this, node_list.size(), op_code, arg, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags); auto sp = make_unique<UnaryOpNode>(*this, node_list.size(), op_code, arg, arg_exp_info_set,
param1_symb_id, param2_symb_id, adl_param_name, adl_lags);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
unary_op_node_map[{ arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags }] = p; unary_op_node_map.try_emplace(
{arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags},
p);
return p; return p;
} }
inline expr_t inline expr_t
DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder) DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder)
{ {
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});
if (it != binary_op_node_map.end()) it != binary_op_node_map.end())
return it->second; return it->second;
// Try to reduce to a constant // Try to reduce to a constant
try try
{ {
double argval1 = arg1->eval(eval_context_t()); double argval1 = arg1->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double argval2 = arg2->eval(eval_context_t()); double argval2 = arg2->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder); double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder);
return AddPossiblyNegativeConstant(val); return AddPossiblyNegativeConstant(val);
} }
...@@ -410,26 +476,27 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD ...@@ -410,26 +476,27 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD
{ {
} }
auto sp = make_unique<BinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, powerDerivOrder); auto sp
= make_unique<BinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, powerDerivOrder);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
binary_op_node_map[{ arg1, arg2, op_code, powerDerivOrder }] = p; binary_op_node_map.try_emplace({arg1, arg2, op_code, powerDerivOrder}, p);
return p; return p;
} }
inline expr_t inline expr_t
DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3) DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3)
{ {
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});
if (it != trinary_op_node_map.end()) it != trinary_op_node_map.end())
return it->second; return it->second;
// Try to reduce to a constant // Try to reduce to a constant
try try
{ {
double argval1 = arg1->eval(eval_context_t()); double argval1 = arg1->eval({});
double argval2 = arg2->eval(eval_context_t()); double argval2 = arg2->eval({});
double argval3 = arg3->eval(eval_context_t()); double argval3 = arg3->eval({});
double val = TrinaryOpNode::eval_opcode(argval1, op_code, argval2, argval3); double val = TrinaryOpNode::eval_opcode(argval1, op_code, argval2, argval3);
return AddPossiblyNegativeConstant(val); return AddPossiblyNegativeConstant(val);
} }
...@@ -440,7 +507,7 @@ DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t a ...@@ -440,7 +507,7 @@ DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t a
auto sp = make_unique<TrinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, arg3); auto sp = make_unique<TrinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, arg3);
auto p = sp.get(); auto p = sp.get();
node_list.push_back(move(sp)); node_list.push_back(move(sp));
trinary_op_node_map[{ arg1, arg2, arg3, op_code }] = p; trinary_op_node_map.try_emplace({arg1, arg2, arg3, op_code}, p);
return p; return p;
} }
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
/* /*
* Copyright (C) 2003-2018 Dynare Team * Copyright © 2003-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -14,28 +14,73 @@ ...@@ -14,28 +14,73 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _DYNAMICMODEL_HH #ifndef DYNAMIC_MODEL_HH
#define _DYNAMICMODEL_HH #define DYNAMIC_MODEL_HH
using namespace std;
#include <filesystem>
#include <fstream> #include <fstream>
#include <boost/crc.hpp>
#include "Bytecode.hh"
#include "StaticModel.hh" #include "StaticModel.hh"
using namespace std;
//! Stores a dynamic model //! Stores a dynamic model
class DynamicModel : public ModelTree class DynamicModel : public ModelTree
{ {
friend class StaticModel; // For reading static_mfs from converting constructor
public: public:
//! A reference to the trend component model table //! 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 //! 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};
/* For a given equation, tracks all the regimes and the declared alternatives with combinations of
bind and relax tags */
class OccbinRegimeTracker
{
private: private:
// The list of constraints used for this equation
vector<string> constraints;
/* The list of regimes present for this equation; each regime is a vector of boolean, of same
length as “constraints”; each boolean represents a constraint (in the order of
“constraints”): false for relax, true for bind */
set<vector<bool>> regimes_present;
public:
struct ConstraintInBothBindAndRelaxException
{
const string constraint;
};
struct RegimeAlreadyPresentException
{
const vector<string> constraints_bind, constraints_relax;
};
void addRegime(const vector<string>& constraints_bind,
const vector<string>& constraints_relax) noexcept(false);
struct MissingRegimeException
{
const vector<string> constraints_bind, constraints_relax;
};
void checkAllRegimesPresent() const noexcept(false);
private:
[[nodiscard]] pair<vector<string>, vector<string>>
convertBitVectorToRegimes(const vector<bool>& r) const;
};
private:
/* 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] //! Stores equations declared as [static]
...@@ -43,10 +88,13 @@ private: ...@@ -43,10 +88,13 @@ private:
vector<BinaryOpNode*> static_only_equations; vector<BinaryOpNode*> static_only_equations;
//! Stores line numbers of equations declared as [static] //! Stores line numbers of equations declared as [static]
vector<int> static_only_equations_lineno; vector<optional<int>> static_only_equations_lineno;
//! Stores the equation tags of equations declared as [static] //! Stores the equation tags of equations declared as [static]
vector<vector<pair<string, string>>> static_only_equations_equation_tags; EquationTags static_only_equations_equation_tags;
// Complementarity conditions of equations declared as [static]
vector<optional<tuple<int, expr_t, expr_t>>> static_only_complementarity_conditions;
using deriv_id_table_t = map<pair<int, int>, int>; using deriv_id_table_t = map<pair<int, int>, int>;
//! Maps a pair (symbol_id, lag) to a deriv ID //! Maps a pair (symbol_id, lag) to a deriv ID
...@@ -54,9 +102,12 @@ private: ...@@ -54,9 +102,12 @@ private:
//! Maps a deriv ID to a pair (symbol_id, lag) //! Maps a deriv ID to a pair (symbol_id, lag)
vector<pair<int, int>> inv_deriv_id_table; vector<pair<int, int>> inv_deriv_id_table;
//! Maps a deriv_id to the column index of the dynamic Jacobian /* Maps a deriv_id to the column index of the dynamic Jacobian, in the legacy
/*! Contains only endogenous, exogenous and exogenous deterministic */ representation.
Contains only endogenous, exogenous and exogenous deterministic */
map<int, int> dyn_jacobian_cols_table; map<int, int> dyn_jacobian_cols_table;
// Number of columns of the dynamic Jacobian (legacy representation)
int dyn_jacobian_ncols;
//! Maximum lag and lead over all types of variables (positive values) //! Maximum lag and lead over all types of variables (positive values)
/*! Set by computeDerivIDs() */ /*! Set by computeDerivIDs() */
...@@ -71,204 +122,216 @@ private: ...@@ -71,204 +122,216 @@ private:
/*! Set by computeDerivIDs() */ /*! 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 //! Maximum lag and lead over all types of variables (positive values) of original model
int max_lag_orig{0}, max_lead_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 //! 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 //! Maximum lag and lead over exogenous variables (positive values) of original model
int max_exo_lag_orig {0}, max_exo_lead_orig {0}; int max_exo_lag_orig {0}, max_exo_lead_orig {0};
//! Maximum lag and lead over deterministic exogenous variables (positive values) of original model //! Maximum lag and lead over deterministic exogenous variables (positive values) of original
//! model
int max_exo_det_lag_orig {0}, max_exo_det_lead_orig {0}; int max_exo_det_lag_orig {0}, max_exo_det_lead_orig {0};
//! Cross reference information // Cross reference information: eq → set of (symb_id, lag) for each symbol type
map<int, ExprNode::EquationInfo> xrefs; map<int, ExprNode::EquationInfo> xrefs;
map<pair<int, int>, set<int>> xref_param; // Reverse cross reference information: (symb_id, lag) → eqs
map<pair<int, int>, set<int>> xref_endo; map<pair<int, int>, set<int>> xref_param, xref_endo, xref_exo, xref_exo_det;
map<pair<int, int>, set<int>> xref_exo;
map<pair<int, int>, set<int>> xref_exo_det;
//! Nonzero equations in the Hessian //! Nonzero equations in the Hessian
map<int, string> nonzero_hessian_eqs; set<int> nonzero_hessian_eqs;
//! Number of columns of dynamic jacobian //! Creates mapping for variables and equations they are present in
/*! Set by computeDerivID()s and computeDynJacobianCols() */ map<int, set<int>> variableMapping;
int dynJacobianColsNbr{0};
//! Temporary terms for block decomposed models
vector< vector<temporary_terms_t>> v_temporary_terms;
vector<temporary_terms_inuse_t> v_temporary_terms_inuse; /* For each block, and for each variable type, maps (variable ID, lag) to
Jacobian column. The variable ID is the index within the block. */
vector<map<pair<int, int>, int>> blocks_jacob_cols_endo;
//! Store the derivatives or the chainrule derivatives:map<pair< equation, pair< variable, lead_lag >, expr_t> //! Used for var_expectation and var_model
using first_chain_rule_derivatives_t = map< pair< int, pair< int, int>>, expr_t>; map<string, set<int>> var_expectation_functions_to_write;
first_chain_rule_derivatives_t first_chain_rule_derivatives;
// Value of the “mfs” option of “model” block (or ”model_options” command)
int mfs {1};
//! Writes dynamic model file (Matlab version) /* 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};
// Writes dynamic model file (MATLAB/Octave version, legacy representation)
void writeDynamicMFile(const string& basename) const; void writeDynamicMFile(const string& basename) const;
//! Writes dynamic model file (Julia version) //! Writes the code of the block-decomposed model in virtual machine bytecode
void writeDynamicJuliaFile(const string &dynamic_basename) const; void writeDynamicBlockBytecode(const string& basename) const;
//! Writes dynamic model file (C version)
/*! \todo add third derivatives handling */
void writeDynamicCFile(const string &basename, const int order) const;
//! Writes dynamic model file when SparseDLL option is on
void writeSparseDynamicMFile(const string &basename) const;
//! Writes the dynamic model equations and its derivatives
/*! \todo add third derivatives handling in C output */
void writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia) const;
void writeDynamicModel(const string &basename, bool use_dll, bool julia) const;
void writeDynamicModel(const string &basename, ostream &DynamicOutput, bool use_dll, bool julia) const;
//! Writes the Block reordred structure of the model in M output
void writeModelEquationsOrdered_M(const string &basename) const;
//! Writes the code of the Block reordred structure of the model in virtual machine bytecode
void writeModelEquationsCode_Block(const string &basename, const map_idx_t &map_idx, const bool linear_decomposition) const;
//! Writes the code of the model in virtual machine bytecode //! Writes the code of the model in virtual machine bytecode
void writeModelEquationsCode(const string &basename, const map_idx_t &map_idx) const; void writeDynamicBytecode(const string& basename) const;
void writeSetAuxiliaryVariables(const string &basename, const bool julia) const;
void writeAuxVarRecursiveDefinitions(ostream &output, ExprNodeOutputType output_type) const;
//! Computes jacobian and prepares for equation normalization // Write the block structure of the model in the driver file
/*! Using values from initval/endval blocks and parameter initializations: void writeBlockDriverOutput(ostream& output) const;
- computes the jacobian for the model w.r. to contemporaneous variables
- removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff)
*/
//void evaluateJacobian(const eval_context_t &eval_context, jacob_map *j_m, bool dynamic);
//! return a map on the block jacobian // Used by determineBlockDerivativesType()
map<pair<pair<int, pair<int, int>>, pair<int, int>>, int> get_Derivatives(int block); enum class BlockDerivativeType
//! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables {
void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives); standard,
chainRule,
normalizedChainRule
};
string reform(string name) const; /* For each tuple (lag, eq, var) within the given block, determine the type
map_idx_t map_idx; of the derivative to be computed. Indices are within the block (i.e.
between 0 and blocks[blk].size-1). */
map<tuple<int, int, int>, BlockDerivativeType> determineBlockDerivativesType(int blk);
//! sorts the temporary terms in the blocks order void computeChainRuleJacobian() override;
void computeTemporaryTermsOrdered();
//! creates a mapping from the index of temporary terms to a natural index string reform(const string& name) const;
void computeTemporaryTermsMapping();
//! Write derivative code of an equation w.r. to a variable
void compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, int lag, const map_idx_t &map_idx) const;
//! Write chain rule derivative code of an equation w.r. to a variable
void compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int var, int lag, const map_idx_t &map_idx) const;
//! Get the type corresponding to a derivation ID
SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override; SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;
//! Get the lag corresponding to a derivation ID
int getLagByDerivID(int deriv_id) const noexcept(false) override; int getLagByDerivID(int deriv_id) const noexcept(false) override;
//! Get the symbol ID corresponding to a derivation ID
int getSymbIDByDerivID(int deriv_id) const noexcept(false) override; int getSymbIDByDerivID(int deriv_id) const noexcept(false) override;
int getTypeSpecificIDByDerivID(int deriv_id) const override;
//! Compute the column indices of the dynamic Jacobian //! Compute the column indices of the dynamic Jacobian
void computeDynJacobianCols(bool jacobianExo); void computeDynJacobianCols();
//! Computes derivatives of the Jacobian w.r. to trend vars and tests that they are equal to zero //! 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);
//! Collect only the first derivatives
map<pair<int, pair<int, int>>, expr_t> collect_first_order_derivatives_endogenous();
//! Allocates the derivation IDs for all dynamic variables of the model //! Allocates the derivation IDs for all dynamic variables of the model
/*! Also computes max_{endo,exo}_{lead_lag}, and initializes dynJacobianColsNbr to the number of dynamic endos */ /*! Also computes max_{endo,exo}_{lead_lag}, and initializes dynJacobianColsNbr to the number of
* dynamic endos */
void computeDerivIDs(); void computeDerivIDs();
//! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous /* Compute the Jacobian column indices in the block decomposition case
void collect_block_first_order_derivatives(); (stored in blocks_jacob_cols_*).
Also fills auxiliary structures related to “other” endogenous and
//! Collecte the informations about exogenous, deterministic exogenous and endogenous from the previous block for each block exogenous: blocks{,_derivatives}_{other_endo,exo_exo_det} */
void collectBlockVariables(); void computeBlockDynJacobianCols();
//! Factorized code for substitutions of leads/lags //! Factorized code for substitutions of leads/lags
/*! \param[in] type determines which type of variables is concerned /*! \param[in] type determines which type of variables is concerned
\param[in] deterministic_model whether we are in a deterministic model (only for exogenous leads/lags) \param[in] deterministic_model whether we are in a deterministic model (only for exogenous
\param[in] subset variables to which to apply the transformation (only for diff of forward vars) leads/lags) \param[in] subset variables to which to apply the transformation (only for diff of
forward vars)
*/ */
void substituteLeadLagInternal(AuxVarType type, bool deterministic_model, const vector<string> &subset); void substituteLeadLagInternal(AuxVarType type, bool deterministic_model,
const vector<string>& subset);
//! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
bool global_temporary_terms{true};
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
//! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size >>
block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
//! for all blocks derivatives description
blocks_derivatives_t blocks_derivatives;
//! The jacobian without the elements below the cutoff
dynamic_jacob_map_t dynamic_jacobian;
//! Vector indicating if the block is linear in endogenous variable (true) or not (false)
vector<bool> blocks_linear;
//! Map the derivatives for a block pair<lag, make_pair(make_pair(eq, var)), expr_t>
using derivative_t = map<pair< int, pair<int, int>>, expr_t>;
//! Vector of derivative for each blocks
vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det;
//!List for each block and for each lag-lead all the other endogenous variables and exogenous variables
using var_t = set<int>;
using lag_var_t = map<int, var_t>;
vector<lag_var_t> other_endo_block, exo_block, exo_det_block;
//!List for each block the exogenous variables
vector<pair<var_t, int>> block_var_exo;
map< int, map<int, int>> block_exo_index, block_det_exo_index, block_other_endo_index;
//! for each block described the number of static, forward, backward and mixed variables in the block
/*! pair< pair<static, forward>, pair<backward,mixed>> */
vector<pair< pair<int, int>, pair<int, int>>> block_col_type;
//! Help computeXrefs to compute the reverse references (i.e. param->eqs, endo->eqs, etc) //! Help computeXrefs to compute the reverse references (i.e. param->eqs, endo->eqs, etc)
void computeRevXref(map<pair<int, int>, set<int>> &xrefset, const set<pair<int, int>> &eiref, int eqn); void computeRevXref(map<pair<int, int>, set<int>>& xrefset, const set<pair<int, int>>& eiref,
int eqn);
//! Write reverse cross references //! Write reverse cross references
void writeRevXrefs(ostream &output, const map<pair<int, int>, set<int>> &xrefmap, const string &type) const; void writeRevXrefs(ostream& output, const map<pair<int, int>, set<int>>& xrefmap,
const string& type) const;
//! List for each variable its block number and its maximum lag and lead inside the block
vector<pair<int, pair<int, int>>> variable_block_lead_lag; /* Writes MATLAB/Octave wrapper function for computing residuals and
//! List for each equation its block number derivatives at the same time (legacy representation) */
vector<int> equation_block; void writeDynamicMWrapperFunction(const string& name, const string& ending) const;
/* Helper for writing MATLAB/Octave functions for residuals/derivatives and
//! Used for var_expectation and var_model their temporary terms (legacy representation) */
map<string, set<int>> var_expectation_functions_to_write; void writeDynamicMFileHelper(const string& basename, const string& name, const string& retvalname,
const string& name_tt, size_t ttlen, const string& previous_tt_name,
//! Used for pac_expectation operator const ostringstream& init_s, const ostringstream& end_s,
set<const PacExpectationNode *> pac_expectation_info; // PacExpectationNode pointers
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
vector<pair<int, int>> endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
void writeWrapperFunctions(const string &name, const string &ending) const;
void writeDynamicModelHelper(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; const ostringstream& s, const ostringstream& s_tt) const;
//! Create a legacy *_dynamic.m file for Matlab/Octave not yet using the temporary terms array interface /* Create the compatibility dynamic.m file for MATLAB/Octave not yet using
void writeDynamicMatlabCompatLayer(const string &basename) const; the temporary terms array interface (legacy representation) */
void writeDynamicMCompatFile(const string& basename) const;
void getEquationNumbersFromTags(vector<int> &eqnumber, set<string> &eqtags) const;
void findPacExpectationEquationNumbers(vector<int> &eqnumber) const;
//! Internal helper for the copy constructor and assignment operator //! Internal helper for the copy constructor and assignment operator
/*! Copies all the structures that contain ExprNode*, by the converting the /*! Copies all the structures that contain ExprNode*, by the converting the
pointers into their equivalent in the new tree */ 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.
The argument inc_exc_option_value should be of one of the following forms:
* filename.txt
* eq1
* ['eq 1', 'eq 2']
* [tagname='eq 1']
* [tagname=('eq 1', 'eq 2')]
If argument is a filename, the file should be formatted as:
eq 1
eq 2
OR
tagname=
X
Y
The boolean exclude_eqs should be true if we are in the exclude_eqs case,
false in the include_eqs case (this only affects error messages).
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);
/* Helper for the removeEquations() method.
listed_eqs_by_tag describes a list of equations to remove (identified by
one or more tags; if multiple tags are present for a single equation, they
are understood as a conjunction), exclude_eqs is a boolean indicating whether we’re
excluding or including, and excluded_vars_change_type is a boolean
indicating whether to compute variables to be excluded.
The all_equations* arguments will be modified by the routine by excluding
equations. They are either the main structures for storing equations in
ModelTree, or their counterpart for static-only equations. The
static_equations boolean indicates when we are in the latter case.
The listed_eqs_by_tag structure will be updated by removing the tags
matched with equations in the all_equations* argument*.
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,
vector<optional<tuple<int, expr_t, expr_t>>>& all_complementarity_conditions,
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
arbitrarily-written expressions. */
map<string, map<tuple<int, int, int>, expr_t>> computeAutoregressiveMatrices() const;
//! 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;
/* 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
types of auxiliary variables: endo lags and diff lags). It returns a
vector because in some cases there may be sereval corresponding deriv_ids
(for example, in the deriv_id table, AUX_DIFF_nn(-1) may appear as itself
(with a lag), and also as a contemporaneous diff lag auxvar). */
vector<int> getVARDerivIDs(int lhs_symb_id, int lead_lag) const;
int
getBlockJacobianEndoCol(int blk, int var, int lag) const override
{
return blocks_jacob_cols_endo[blk].at({var, lag});
}
// Used to check consistency of bind/relax tags; the keys are equation names
map<string, OccbinRegimeTracker> occbin_regime_trackers;
protected:
string
modelClassName() const override
{
return "dynamic model";
}
public: public:
DynamicModel(SymbolTable &symbol_table_arg, DynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg,
TrendComponentModelTable& trend_component_model_table_arg, TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg); VarModelTable& var_model_table_arg);
DynamicModel(const DynamicModel& m); DynamicModel(const DynamicModel& m);
DynamicModel(DynamicModel &&) = delete;
DynamicModel& operator=(const DynamicModel& m); DynamicModel& operator=(const DynamicModel& m);
DynamicModel & operator=(DynamicModel &&) = delete;
//! Compute cross references //! Compute cross references
void computeXrefs(); void computeXrefs();
...@@ -276,23 +339,25 @@ public: ...@@ -276,23 +339,25 @@ public:
//! Write cross references //! Write cross references
void writeXrefs(ostream& output) const; void writeXrefs(ostream& output) const;
//! Execute computations (variable sorting + derivation) //! Execute computations (variable sorting + derivation + block decomposition)
/*! /*!
\param jacobianExo whether derivatives w.r. to exo and exo_det should be in the Jacobian (derivatives w.r. to endo are always computed) \param derivsOrder order of derivatives w.r. to exo, exo_det and endo should be computed
\param hessian whether 2nd derivatives w.r. to exo, exo_det and endo should be computed (implies jacobianExo = true) (implies jacobianExo = true when order >= 2) \param paramsDerivsOrder order of derivatives w.r.
\param thirdDerivatives whether 3rd derivatives w.r. to endo/exo/exo_det should be computed (implies jacobianExo = true) to a pair (endo/exo/exo_det, parameter) to be computed (>0 implies jacobianExo = true) \param
\param paramsDerivsOrder order of derivatives w.r. to a pair (endo/exo/exo_det, parameter) to be computed (>0 implies jacobianExo = true) eval_context evaluation context for normalization \param no_tmp_terms if true, no temporary
\param eval_context evaluation context for normalization terms will be computed in the dynamic files
\param no_tmp_terms if true, no temporary terms will be computed in the dynamic files
*/ */
void computingPass(bool jacobianExo, bool hessian, bool thirdDerivatives, int paramsDerivsOrder, void computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t& eval_context,
const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool use_dll, bool bytecode, const bool nopreprocessoroutput, bool linear_decomposition); bool no_tmp_terms, bool block, bool use_dll);
//! Writes model initialization and lead/lag incidence matrix to output //! Writes information about the dynamic model to the driver file
void writeOutput(ostream &output, const string &basename, bool block, bool linear_decomposition, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const; void writeDriverOutput(ostream& output, bool compute_xrefs) const;
//! Write JSON AST //! Write JSON AST
void writeJsonAST(ostream& output) const; void writeJsonAST(ostream& output) const;
//! Write JSON variable mapping
void writeJsonVariableMapping(ostream& output) const;
//! Write JSON Output //! Write JSON Output
void writeJsonOutput(ostream& output) const; void writeJsonOutput(ostream& output) const;
...@@ -305,67 +370,70 @@ public: ...@@ -305,67 +370,70 @@ public:
//! Write JSON Output representation of dynamic model after computing pass //! 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 prams derivatives file //! Write JSON params derivatives
void writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const; void writeJsonParamsDerivatives(ostream& output, bool writeDetails) const;
//! Write cross reference output if the xref maps have been filed //! Write cross reference output if the xref maps have been filed
void writeJsonXrefs(ostream& output) const; void writeJsonXrefs(ostream& output) const;
void writeJsonXrefsHelper(ostream &output, const map<pair<int, int>, set<int>> &xrefs) const; void writeJsonXrefsHelper(ostream& output, const map<pair<int, int>, set<int>>& xrefmap) const;
//! Print equations that have non-zero second derivatives //! Print equations that have non-zero second derivatives
void printNonZeroHessianEquations(ostream& output) const; void printNonZeroHessianEquations(ostream& output) const;
//! Set the equations that have non-zero second derivatives //! Tells whether Hessian has been computed
void setNonZeroHessianEquations(map<int, string> &eqs); /*! This is needed to know whether no non-zero equation in Hessian means a
zero Hessian or Hessian not computed */
//! Fill Autoregressive Matrix for var_model/trend_component_model bool
void fillAutoregressiveMatrix(map<string, map<tuple<int, int, int>, expr_t>> &ARr, bool is_trend_component_model) const; isHessianComputed() const
{
return computed_derivs_order >= 2;
}
//! Fill Error Component Matrix for trend_component_model /* Check whether the model is linear, by verifying that the hessian is zero,
void fillErrorComponentMatrix(map<string, map<tuple<int, int, int>, expr_t>> &ECr, ExprNode::subst_table_t &diff_subst_table) const; and error out otherwise.
Must be called after computingPass().
FIXME: this check always passes if derivsOrder = 1, i.e. for a perfect
foresight model, because the Hessian is not computed in that case. */
void checkIsLinear() const;
//! Fill the Trend Component Model Table //! Fill the trend component model table with information available from the transformed model
void fillTrendComponentModelTable() const; void fillTrendComponentModelTable() const;
void fillTrendComponentModelTableFromOrigModel(StaticModel &static_model) const; //! Fill the trend component model table with information available from the original model
void fillTrendComponentmodelTableAREC(ExprNode::subst_table_t &diff_subst_table) const; void fillTrendComponentModelTableFromOrigModel() const;
/* Fill the trend component model table with information about AR/EC
//! Fill the Var Model Table 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;
//! Fill the VAR model table with information available from the transformed model
// NB: Does not fill the AR and A0 matrices
void fillVarModelTable() const; void fillVarModelTable() const;
void fillVarModelTableFromOrigModel(StaticModel &static_model) const; //! Fill the VAR model table with information available from the original model
void fillVarModelTableFromOrigModel() const;
//! Fill the AR and A0 matrices of the VAR model table
// Uses derivatives, hence must be called after computingPass()
void fillVarModelTableMatrices();
//! Update the rhs references in the var model and trend component tables //! Update the rhs references in the var model and trend component tables
//! after substitution of auxiliary variables and find the trend variables //! after substitution of auxiliary variables and find the trend variables
//! in the trend_component model //! in the trend_component model
void updateVarAndTrendModel() const; void updateVarAndTrendModel() const;
//! Add aux equations (and aux variables) for variables declared in var_model //! Writes dynamic model file (+ bytecode)
//! at max order if they don't already exist void writeDynamicFile(const string& basename, bool use_dll, const string& mexext,
void addEquationsForVar(); const filesystem::path& matlabroot, bool julia) const;
//! Get Pac equation parameter info
void walkPacParameters();
//! Add var_model info to pac_expectation nodes
void fillPacExpectationVarInfo(string &pac_model_name,
vector<int> &lhs,
int max_lag,
int pac_max_lag,
vector<bool> &nonstationary,
int growth_symb_id);
//! Substitutes pac_expectation operator
void substitutePacExpectation();
//! Adds informations for simulation in a binary file
void Write_Inf_To_Bin_File_Block(const string &basename,
const int &num, int &u_count_int, bool &file_open, bool is_two_boundaries, const bool linear_decomposition) const;
//! Writes dynamic model file
void writeDynamicFile(const string &basename, bool block, bool linear_decomposition, bool bytecode, bool use_dll, int order, bool julia) const;
//! Writes file containing parameters derivatives //! Writes file containing parameters derivatives
void writeParamsDerivativesFile(const string &basename, bool julia) const; template<bool julia>
void writeParamsDerivativesFile(const string& basename) const;
//! Creates mapping for variables and equations they are present in
void createVariableMapping();
//! Converts to nonlinear model (only the equations) //! Expands equation tags with default equation names (available "name" tag or LHS variable or
/*! It assumes that the nonlinear model given in argument has just been allocated */ //! equation ID)
void toNonlinearPart(DynamicModel &non_linear_equations_dynamic_model) const; void expandEqTags();
//! Find endogenous variables not used in model //! Find endogenous variables not used in model
set<int> findUnusedEndogenous(); set<int> findUnusedEndogenous();
...@@ -375,13 +443,36 @@ public: ...@@ -375,13 +443,36 @@ public:
//! Set the max leads/lags of the original model //! Set the max leads/lags of the original model
void setLeadsLagsOrig(); void setLeadsLagsOrig();
//! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous //! Implements the include_eqs/exclude_eqs options
void computeRamseyPolicyFOCs(const StaticModel &static_model, const bool nopreprocessoroutput); 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,
bool excluded_vars_change_type);
/* Replaces model equations with derivatives of Lagrangian w.r.t. endogenous.
The optimality FOCs (derivatives w.r.t. ordinary endogenous) will appear
first, followed by the constraints (derivatives w.r.t. multipliers).
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& planner_objective,
map<int, pair<expr_t, expr_t>> cloned_ramsey_constraints);
//! Clears all equations
void clearEquations();
//! Replaces the model equations in dynamic_model with those in this model //! 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] //! Adds an equation marked as [static]
void addStaticOnlyEquation(expr_t eq, int lineno, const vector<pair<string, string>> &eq_tags); void addStaticOnlyEquation(expr_t eq, const optional<int>& lineno,
optional<tuple<int, expr_t, expr_t>> complementarity_condition,
map<string, string> eq_tags);
//! Returns number of static only equations //! Returns number of static only equations
size_t staticOnlyEquationsNbr() const; size_t staticOnlyEquationsNbr() const;
...@@ -389,22 +480,66 @@ public: ...@@ -389,22 +480,66 @@ public:
//! Returns number of dynamic only equations //! Returns number of dynamic only equations
size_t dynamicOnlyEquationsNbr() const; size_t dynamicOnlyEquationsNbr() const;
// Adds an occbin equation (with “bind” and/or “relax” tag)
/* This function assumes that there is a “name” tag, and that the relevant
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, const optional<int>& lineno, map<string, string> eq_tags,
const vector<string>& constraints_bind,
const vector<string>& constraints_relax);
//! Writes LaTeX file with the equations of the dynamic model //! Writes LaTeX file with the equations of the dynamic model
void writeLatexFile(const string &basename, const 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) //! Writes LaTeX file with the equations of the dynamic model (for the original model)
void writeLatexOriginalFile(const string &basename, const bool write_equation_tags) const; void writeLatexOriginalFile(const string& basename, bool write_equation_tags) const;
int getDerivID(int symb_id, int lag) const noexcept(false) override; int getDerivID(int symb_id, int lag) const noexcept(false) override;
int getDynJacobianCol(int deriv_id) const noexcept(false) override;
void addAllParamDerivId(set<int> &deriv_id_set) override;
//! Returns true indicating that this is a dynamic model int
bool getJacobianCol(int deriv_id, bool sparse) const override
isDynamic() const override
{ {
return true; if (sparse)
}; {
SymbolType type {getTypeByDerivID(deriv_id)};
int tsid {getTypeSpecificIDByDerivID(deriv_id)};
int lag {getLagByDerivID(deriv_id)};
if (type == SymbolType::endogenous)
{
assert(lag >= -1 && lag <= 1);
return tsid + (lag + 1) * symbol_table.endo_nbr();
}
else if (type == SymbolType::exogenous)
{
assert(lag == 0);
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();
}
else
throw UnknownDerivIDException();
}
else
{
if (auto it = dyn_jacobian_cols_table.find(deriv_id); it == dyn_jacobian_cols_table.end())
throw UnknownDerivIDException();
else
return it->second;
}
}
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;
}
void addAllParamDerivId(set<int>& deriv_id_set) override;
//! Drive test of detrended equations //! Drive test of detrended equations
void runTrendTest(const eval_context_t& eval_context); void runTrendTest(const eval_context_t& eval_context);
...@@ -426,36 +561,134 @@ public: ...@@ -426,36 +561,134 @@ public:
//! Transforms the model by removing all UnaryOpcode::expectation //! Transforms the model by removing all UnaryOpcode::expectation
void substituteExpectation(bool partial_information_model); void substituteExpectation(bool partial_information_model);
//! Transforms the model by decreasing the lead/lag of predetermined variables in model equations by one //! Transforms the model by decreasing the lead/lag of predetermined variables in model equations
//! by one
void transformPredeterminedVariables(); void transformPredeterminedVariables();
// Performs the transformations associated to variables declared with “var(log)”
void substituteLogTransform();
/* Performs the transformations associated to aggregation operators in heterogeneous models, such
as SUM(…) */
void substituteAggregationOperators();
// Check that no variable was declared with “var(log)” in the given equations
void checkNoWithLogTransform(const set<int>& eqnumbers);
//! Transforms the model by removing trends specified by the user //! Transforms the model by removing trends specified by the user
void detrendEquations(); void detrendEquations();
const nonstationary_symbols_map_t&
getNonstationarySymbolsMap() const
{
return nonstationary_symbols_map;
}
const map<int, expr_t>&
getTrendSymbolsMap() const
{
return trend_symbols_map;
}
//! Substitutes adl operator //! Substitutes adl operator
void substituteAdl(); void substituteAdl();
//! Creates aux vars for all unary operators //! Substitutes out all model-local variables
void substituteUnaryOps(StaticModel &static_model); void substituteModelLocalVariables();
//! Creates aux vars for certain unary operators: originally implemented for support of VARs /* Creates aux vars for all unary operators in all equations. Also makes the
void substituteUnaryOps(StaticModel &static_model, set<string> &eq_tags); 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);
//! Creates aux vars for certain unary operators: originally implemented for support of VARs /* Creates aux vars for all unary operators in specified equations. Also makes the
void substituteUnaryOps(StaticModel &static_model, vector<int> &eqnumbers); 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);
//! Substitutes diff operator //! Substitutes diff operator
void substituteDiff(StaticModel &static_model, ExprNode::subst_table_t &diff_subst_table); pair<lag_equivalence_table_t, ExprNode::subst_table_t>
substituteDiff(VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table);
//! Substitute VarExpectation operators //! Substitute VarExpectation operators
void substituteVarExpectation(const map<string, expr_t>& subst_table); void substituteVarExpectation(const map<string, expr_t>& subst_table);
//! Return max lag of pac equation void analyzePacEquationStructure(const string& name, map<string, string>& pac_eq_name,
int getPacMaxLag(const string &pac_model_name) const; PacModelTable::equation_info_t& pac_equation_info);
// Exception thrown by getPacTargetSymbId()
struct PacTargetNotIdentifiedException
{
const string model_name, message;
};
//! Return target of the pac equation
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.
In the process, add the variable and the equation defining Z₁.
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);
/* For a PAC MCE model with an associated pac_target_info, fill pac_expectation_substitution with
the expression that will be substituted for the pac_expectation operator. In the process, add
the variables and the equations defining Z₁ and Z₀ for each component. The new auxiliary
parameters are added to pac_mce_alpha_symb_ids. The routine also creates the auxiliary
variables for the components, and adds the corresponding equations.
*/
void computePacModelConsistentExpectationSubstitutionWithComponents(
const string& name, int discount_symb_id, int pac_eq_max_lag,
ExprNode::subst_table_t& diff_subst_table, map<string, vector<int>>& pac_aux_param_symb_ids,
vector<PacModelTable::target_component_t>& pac_target_components,
map<string, expr_t>& pac_expectation_substitution);
/* For a PAC backward model, fill pac_expectation_substitution with the
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);
/* Same as above, but for PAC models which have an associated
pac_target_info.
Contrary to the above routine, this one will create the growth correction
parameters as needed.
Those parameter IDs, as well as the IDs for the h parameters, are stored
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);
//! 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);
//! Substitutes the pac_target_nonstationary operator of a given pac_model
void substitutePacTargetNonstationary(const string& pac_model_name, expr_t substexpr);
//! Table to undiff LHS variables for pac vector z //! Table to undiff LHS variables for pac vector z
vector<int> getUndiffLHSForPac(const string& aux_model_name, vector<int> getUndiffLHSForPac(const string& aux_model_name,
ExprNode::subst_table_t &diff_subst_table) const; const ExprNode::subst_table_t& diff_subst_table) const;
//! Transforms the model by replacing trend variables with a 1 //! Transforms the model by replacing trend variables with a 1
void removeTrendVariableFromEquations(); void removeTrendVariableFromEquations();
...@@ -468,200 +701,265 @@ public: ...@@ -468,200 +701,265 @@ public:
//! Fills eval context with values of model local variables and auxiliary variables //! 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;
auto getStaticOnlyEquationsInfo() const { return make_tuple(static_only_equations, static_only_equations_lineno, static_only_equations_equation_tags); }; /*! Checks that all pac_expectation operators have been substituted, error
out otherwise */
void checkNoRemainingPacExpectation() const;
//! Return the number of blocks /*! Checks that all pac_target_nonstationary operators have been substituted, error
unsigned int out otherwise */
getNbBlocks() const override void checkNoRemainingPacTargetNonstationary() const;
{
return (block_type_firstequation_size_mfs.size()); auto
}; getStaticOnlyEquationsInfo() const
//! Determine the simulation type of each block
BlockSimulationType
getBlockSimulationType(int block_number) const override
{
return (block_type_firstequation_size_mfs[block_number].first.first);
};
//! Return the first equation number of a block
unsigned int
getBlockFirstEquation(int block_number) const override
{
return (block_type_firstequation_size_mfs[block_number].first.second);
};
//! Return the size of the block block_number
unsigned int
getBlockSize(int block_number) const override
{
return (block_type_firstequation_size_mfs[block_number].second.first);
};
//! Return the number of exogenous variable in the block block_number
unsigned int
getBlockExoSize(int block_number) const override
{
return (block_var_exo[block_number].first.size());
};
//! Return the number of colums in the jacobian matrix for exogenous variable in the block block_number
unsigned int
getBlockExoColSize(int block_number) const override
{
return (block_var_exo[block_number].second);
};
//! Return the number of feedback variable of the block block_number
unsigned int
getBlockMfs(int block_number) const override
{
return (block_type_firstequation_size_mfs[block_number].second.second);
};
//! Return the maximum lag in a block
unsigned int
getBlockMaxLag(int block_number) const override
{
return (block_lag_lead[block_number].first);
};
//! Return the maximum lead in a block
unsigned int
getBlockMaxLead(int block_number) const override
{
return (block_lag_lead[block_number].second);
};
//! Return the type of equation (equation_number) belonging to the block block_number
EquationType
getBlockEquationType(int block_number, int equation_number) const override
{
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first);
};
//! Return true if the equation has been normalized
bool
isBlockEquationRenormalized(int block_number, int equation_number) const override
{
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first == E_EVALUATE_S);
};
//! Return the expr_t of the equation equation_number belonging to the block block_number
expr_t
getBlockEquationExpr(int block_number, int equation_number) const override
{
return (equations[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]]);
};
//! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
expr_t
getBlockEquationRenormalizedExpr(int block_number, int equation_number) const override
{
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].second);
};
//! Return the original number of equation equation_number belonging to the block block_number
int
getBlockEquationID(int block_number, int equation_number) const override
{
return (equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]);
};
//! Return the original number of variable variable_number belonging to the block block_number
int
getBlockVariableID(int block_number, int variable_number) const override
{
return (variable_reordered[block_type_firstequation_size_mfs[block_number].first.second+variable_number]);
};
//! Return the original number of the exogenous variable varexo_number belonging to the block block_number
int
getBlockVariableExoID(int block_number, int variable_number) const override
{
auto it = exo_block[block_number].find(variable_number);
return (it->first);
};
//! Return the position of equation_number in the block number belonging to the block block_number
int
getBlockInitialEquationID(int block_number, int equation_number) const override
{
return ((int) inv_equation_reordered[equation_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
};
//! Return the position of variable_number in the block number belonging to the block block_number
int
getBlockInitialVariableID(int block_number, int variable_number) const override
{
return ((int) inv_variable_reordered[variable_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
};
//! Return the block number containing the endogenous variable variable_number
int
getBlockVariableID(int variable_number) const
{
return (variable_block_lead_lag[variable_number].first);
};
//! Return the position of the exogenous variable_number in the block number belonging to the block block_number
int
getBlockInitialExogenousID(int block_number, int variable_number) const override
{
auto it = block_exo_index.find(block_number);
if (it != block_exo_index.end())
{ {
auto it1 = it->second.find(variable_number); return tuple {static_only_equations, static_only_equations_lineno,
if (it1 != it->second.end()) static_only_complementarity_conditions, static_only_equations_equation_tags};
return it1->second;
else
return -1;
} }
else
return (-1); //! Returns true if a parameter was used in the model block with a lead or lag
}; bool ParamUsedWithLeadLag() const;
//! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
bool isChecksumMatching(const string& basename) const;
//! 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;
// Returns the set of equations (as numbers) which have a pac_expectation operator
set<int> findPacExpectationEquationNumbers() const;
int int
getBlockInitialDetExogenousID(int block_number, int variable_number) const override getMFS() const override
{
auto it = block_det_exo_index.find(block_number);
if (it != block_det_exo_index.end())
{ {
auto it1 = it->second.find(variable_number); return mfs;
if (it1 != it->second.end())
return it1->second;
else
return -1;
} }
else
return (-1); void
}; setMFS(int mfs_arg)
//! Return the position of the other endogenous variable_number in the block number belonging to the block block_number
int
getBlockInitialOtherEndogenousID(int block_number, int variable_number) const override
{
auto it = block_other_endo_index.find(block_number);
if (it != block_other_endo_index.end())
{ {
auto it1 = it->second.find(variable_number); mfs = mfs_arg;
if (it1 != it->second.end())
return it1->second;
else
return -1;
} }
else
return (-1);
};
bool isModelLocalVariableUsed() const;
//! Returns true if a parameter was used in the model block with a lead or lag void
bool ParamUsedWithLeadLag() const; setStaticMFS(int static_mfs_arg)
{
static_mfs = static_mfs_arg;
}
bool isChecksumMatching(const string &basename, bool block) const; // Checks that all alternatives are declared for all Occbin regimes in all equations
void checkOccbinRegimes() const;
}; };
//! Classes to re-order derivatives for various sparse storage formats template<bool julia>
class derivative void
DynamicModel::writeParamsDerivativesFile(const string& basename) const
{ {
public: if (!params_derivatives.size())
long unsigned int linear_address; return;
long unsigned int col_nbr;
unsigned int row_nbr; constexpr ExprNodeOutputType output_type {julia ? ExprNodeOutputType::juliaDynamicModel
expr_t value; : ExprNodeOutputType::matlabDynamicModel};
derivative(long unsigned int arg1, long unsigned int arg2, int arg3, expr_t arg4) :
linear_address(arg1), col_nbr(arg2), row_nbr(arg3), value(arg4) auto [tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output,
{ g3p_output] {writeParamsDerivativesFileHelper<output_type>()};
};
};
class derivative_less_than if constexpr (!julia)
{ {
public: filesystem::path filename {packageDir(basename) / "dynamic_params_derivs.m"};
bool ofstream paramsDerivsFile {filename, ios::out | ios::binary};
operator()(const derivative &d1, const derivative &d2) const if (!paramsDerivsFile.is_open())
{ {
return d1.linear_address < d2.linear_address; 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.close();
}
else
{
stringstream output;
output << "# NB: this file was automatically generated by Dynare" << endl
<< "# from " << basename << ".mod" << endl
<< "#" << endl
<< "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() << ", "
<< 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
<< "return (rp, gp, rpp, gpp, hp, g3p)" << endl
<< "end" << endl;
writeToFileIfModified(output, filesystem::path {basename} / "model" / "julia"
/ "DynamicParamsDerivs.jl");
}
}
#endif #endif
Source diff could not be displayed: it is too large. Options to address this: view the blob.
/* -*- C++ -*- */ /* -*- C++ -*- */
/* /*
* Copyright (C) 2003-2018 Dynare Team * Copyright © 2003-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -15,16 +15,15 @@ ...@@ -15,16 +15,15 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
%{ %{
using namespace std;
#include <cstring>
#include "ParsingDriver.hh" #include "ParsingDriver.hh"
using namespace std;
// Announce to Flex the prototype we want for lexing function // Announce to Flex the prototype we want for lexing function
#define YY_DECL \ #define YY_DECL \
Dynare::parser::token_type \ Dynare::parser::token_type \
...@@ -41,11 +40,10 @@ using token = Dynare::parser::token; ...@@ -41,11 +40,10 @@ using token = Dynare::parser::token;
#define yyterminate() return Dynare::parser::token_type(0); #define yyterminate() return Dynare::parser::token_type(0);
int comment_caller, line_caller; int comment_caller, line_caller;
/* Particular value : when sigma_e command is found
this flag is set to 1, when command finished it is set to 0
*/
int sigma_e = 0;
string eofbuff; string eofbuff;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
%} %}
%option c++ %option c++
...@@ -61,7 +59,6 @@ string eofbuff; ...@@ -61,7 +59,6 @@ string eofbuff;
%x VERBATIM_BLOCK %x VERBATIM_BLOCK
%x NATIVE %x NATIVE
%x NATIVE_COMMENT %x NATIVE_COMMENT
%x DATES_STATEMENT
%x LINE1 %x LINE1
%x LINE2 %x LINE2
%x LINE3 %x LINE3
...@@ -71,7 +68,9 @@ string eofbuff; ...@@ -71,7 +68,9 @@ string eofbuff;
#define YY_USER_ACTION location_increment(yylloc, yytext); #define YY_USER_ACTION location_increment(yylloc, yytext);
%} %}
DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2])) NAME [a-z_][a-z0-9_]*
FLOAT_NUMBER ((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+[ed][-+]?[0-9]+)
DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|[sh][12])
%% %%
/* Code put at the beginning of yylex() */ /* Code put at the beginning of yylex() */
...@@ -83,7 +82,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -83,7 +82,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
/* Rules for matching $line directives */ /* Rules for matching $line directives */
<*>^@#line\ \" { line_caller = YYSTATE; BEGIN(LINE1); } <*>^@#line\ \" { line_caller = YYSTATE; BEGIN(LINE1); }
<LINE1>[^\"]* { <LINE1>[^\"]* {
filename = string(yytext); filename = yytext;
BEGIN(LINE2); BEGIN(LINE2);
} }
<LINE2>\" BEGIN(LINE3); <LINE2>\" BEGIN(LINE3);
...@@ -93,13 +92,12 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -93,13 +92,12 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
} }
/* spaces, tabs and carriage returns are ignored */ /* spaces, tabs and carriage returns are ignored */
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,DATES_STATEMENT,LINE1,LINE2,LINE3>[ \t\r\f]+ { yylloc->step(); } <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,LINE1,LINE2,LINE3>[[:space:]]+ { yylloc->step(); }
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,DATES_STATEMENT,LINE1,LINE2,LINE3>[\n]+ { yylloc->step(); }
/* Comments */ /* Comments */
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>%.* <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>%.*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>\/{2}.* <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>"//".*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>"/*" {comment_caller = YY_START; BEGIN COMMENT;} <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>"/*" {comment_caller = YY_START; BEGIN COMMENT;}
<COMMENT>"*/" {BEGIN comment_caller;} <COMMENT>"*/" {BEGIN comment_caller;}
<COMMENT>. <COMMENT>.
...@@ -113,10 +111,9 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -113,10 +111,9 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<INITIAL>predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;} <INITIAL>predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;}
<INITIAL>parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;} <INITIAL>parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;}
<INITIAL>model_local_variable {BEGIN DYNARE_STATEMENT; return token::MODEL_LOCAL_VARIABLE;} <INITIAL>model_local_variable {BEGIN DYNARE_STATEMENT; return token::MODEL_LOCAL_VARIABLE;}
<INITIAL>periods {BEGIN DYNARE_STATEMENT; return token::PERIODS;} <INITIAL>heterogeneity_dimension {BEGIN DYNARE_STATEMENT; return token::HETEROGENEITY_DIMENSION;}
<INITIAL>model_info {BEGIN DYNARE_STATEMENT; return token::MODEL_INFO;} <INITIAL>model_info {BEGIN DYNARE_STATEMENT; return token::MODEL_INFO;}
<INITIAL>estimation {BEGIN DYNARE_STATEMENT; return token::ESTIMATION;} <INITIAL>estimation {BEGIN DYNARE_STATEMENT; return token::ESTIMATION;}
<INITIAL>var_estimation {BEGIN DYNARE_STATEMENT; return token::VAR_ESTIMATION;}
<INITIAL>set_time {BEGIN DYNARE_STATEMENT; return token::SET_TIME;} <INITIAL>set_time {BEGIN DYNARE_STATEMENT; return token::SET_TIME;}
<INITIAL>data {BEGIN DYNARE_STATEMENT; return token::DATA;} <INITIAL>data {BEGIN DYNARE_STATEMENT; return token::DATA;}
<INITIAL>varobs {BEGIN DYNARE_STATEMENT; return token::VAROBS;} <INITIAL>varobs {BEGIN DYNARE_STATEMENT; return token::VAROBS;}
...@@ -145,16 +142,22 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -145,16 +142,22 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<INITIAL>var_expectation_model {BEGIN DYNARE_STATEMENT; return token::VAR_EXPECTATION_MODEL;} <INITIAL>var_expectation_model {BEGIN DYNARE_STATEMENT; return token::VAR_EXPECTATION_MODEL;}
<INITIAL>pac_model {BEGIN DYNARE_STATEMENT; return token::PAC_MODEL;} <INITIAL>pac_model {BEGIN DYNARE_STATEMENT; return token::PAC_MODEL;}
<INITIAL>dsample {BEGIN DYNARE_STATEMENT; return token::DSAMPLE;} <INITIAL>dsample {BEGIN DYNARE_STATEMENT; return token::DSAMPLE;}
<INITIAL>Sigma_e {BEGIN DYNARE_STATEMENT; sigma_e = 1; return token::SIGMA_E;}
<INITIAL>planner_objective {BEGIN DYNARE_STATEMENT; return token::PLANNER_OBJECTIVE;} <INITIAL>planner_objective {BEGIN DYNARE_STATEMENT; return token::PLANNER_OBJECTIVE;}
<INITIAL>ramsey_model {BEGIN DYNARE_STATEMENT; return token::RAMSEY_MODEL;} <INITIAL>ramsey_model {BEGIN DYNARE_STATEMENT; return token::RAMSEY_MODEL;}
<INITIAL>ramsey_policy {BEGIN DYNARE_STATEMENT; return token::RAMSEY_POLICY;} <INITIAL>ramsey_policy {BEGIN DYNARE_STATEMENT; return token::RAMSEY_POLICY;}
<INITIAL>evaluate_planner_objective {BEGIN DYNARE_STATEMENT; return token::EVALUATE_PLANNER_OBJECTIVE;}
<INITIAL>occbin_setup {BEGIN DYNARE_STATEMENT; return token::OCCBIN_SETUP;}
<INITIAL>occbin_solver {BEGIN DYNARE_STATEMENT; return token::OCCBIN_SOLVER;}
<INITIAL>occbin_write_regimes {BEGIN DYNARE_STATEMENT; return token::OCCBIN_WRITE_REGIMES;}
<INITIAL>occbin_graph {BEGIN DYNARE_STATEMENT; return token::OCCBIN_GRAPH;}
<INITIAL>discretionary_policy {BEGIN DYNARE_STATEMENT; return token::DISCRETIONARY_POLICY;} <INITIAL>discretionary_policy {BEGIN DYNARE_STATEMENT; return token::DISCRETIONARY_POLICY;}
<INITIAL>identification {BEGIN DYNARE_STATEMENT; return token::IDENTIFICATION;} <INITIAL>identification {BEGIN DYNARE_STATEMENT; return token::IDENTIFICATION;}
<INITIAL>bvar_density {BEGIN DYNARE_STATEMENT; return token::BVAR_DENSITY; } <INITIAL>bvar_density {BEGIN DYNARE_STATEMENT; return token::BVAR_DENSITY; }
<INITIAL>bvar_forecast {BEGIN DYNARE_STATEMENT; return token::BVAR_FORECAST; } <INITIAL>bvar_forecast {BEGIN DYNARE_STATEMENT; return token::BVAR_FORECAST; }
<INITIAL>dynare_sensitivity {BEGIN DYNARE_STATEMENT; return token::DYNARE_SENSITIVITY;} <INITIAL>bvar_irf {BEGIN DYNARE_STATEMENT; return token::BVAR_IRF; }
<INITIAL>sensitivity {BEGIN DYNARE_STATEMENT; return token::SENSITIVITY;}
<INITIAL>dynare_sensitivity {BEGIN DYNARE_STATEMENT; return token::DYNARE_SENSITIVITY;} // Deprecated
<INITIAL>initval_file {BEGIN DYNARE_STATEMENT; return token::INITVAL_FILE;} <INITIAL>initval_file {BEGIN DYNARE_STATEMENT; return token::INITVAL_FILE;}
<INITIAL>histval_file {BEGIN DYNARE_STATEMENT; return token::HISTVAL_FILE;} <INITIAL>histval_file {BEGIN DYNARE_STATEMENT; return token::HISTVAL_FILE;}
<INITIAL>forecast {BEGIN DYNARE_STATEMENT; return token::FORECAST;} <INITIAL>forecast {BEGIN DYNARE_STATEMENT; return token::FORECAST;}
...@@ -162,6 +165,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -162,6 +165,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<INITIAL>realtime_shock_decomposition {BEGIN DYNARE_STATEMENT; return token::REALTIME_SHOCK_DECOMPOSITION;} <INITIAL>realtime_shock_decomposition {BEGIN DYNARE_STATEMENT; return token::REALTIME_SHOCK_DECOMPOSITION;}
<INITIAL>plot_shock_decomposition {BEGIN DYNARE_STATEMENT; return token::PLOT_SHOCK_DECOMPOSITION;} <INITIAL>plot_shock_decomposition {BEGIN DYNARE_STATEMENT; return token::PLOT_SHOCK_DECOMPOSITION;}
<INITIAL>initial_condition_decomposition {BEGIN DYNARE_STATEMENT; return token::INITIAL_CONDITION_DECOMPOSITION;} <INITIAL>initial_condition_decomposition {BEGIN DYNARE_STATEMENT; return token::INITIAL_CONDITION_DECOMPOSITION;}
<INITIAL>squeeze_shock_decomposition {BEGIN DYNARE_STATEMENT; return token::SQUEEZE_SHOCK_DECOMPOSITION;}
<INITIAL>sbvar {BEGIN DYNARE_STATEMENT; return token::SBVAR;} <INITIAL>sbvar {BEGIN DYNARE_STATEMENT; return token::SBVAR;}
<INITIAL>ms_estimation {BEGIN DYNARE_STATEMENT; return token::MS_ESTIMATION;} <INITIAL>ms_estimation {BEGIN DYNARE_STATEMENT; return token::MS_ESTIMATION;}
<INITIAL>ms_simulation {BEGIN DYNARE_STATEMENT; return token::MS_SIMULATION;} <INITIAL>ms_simulation {BEGIN DYNARE_STATEMENT; return token::MS_SIMULATION;}
...@@ -172,8 +176,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -172,8 +176,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<INITIAL>ms_variance_decomposition {BEGIN DYNARE_STATEMENT; return token::MS_VARIANCE_DECOMPOSITION;} <INITIAL>ms_variance_decomposition {BEGIN DYNARE_STATEMENT; return token::MS_VARIANCE_DECOMPOSITION;}
<INITIAL>conditional_forecast {BEGIN DYNARE_STATEMENT; return token::CONDITIONAL_FORECAST;} <INITIAL>conditional_forecast {BEGIN DYNARE_STATEMENT; return token::CONDITIONAL_FORECAST;}
<INITIAL>plot_conditional_forecast {BEGIN DYNARE_STATEMENT; return token::PLOT_CONDITIONAL_FORECAST;} <INITIAL>plot_conditional_forecast {BEGIN DYNARE_STATEMENT; return token::PLOT_CONDITIONAL_FORECAST;}
<INITIAL>gmm_estimation {BEGIN DYNARE_STATEMENT; return token::GMM_ESTIMATION;} <INITIAL>method_of_moments {BEGIN DYNARE_STATEMENT; return token::METHOD_OF_MOMENTS;}
<INITIAL>smm_estimation {BEGIN DYNARE_STATEMENT; return token::SMM_ESTIMATION;}
<INITIAL>markov_switching {BEGIN DYNARE_STATEMENT; return token::MARKOV_SWITCHING;} <INITIAL>markov_switching {BEGIN DYNARE_STATEMENT; return token::MARKOV_SWITCHING;}
<INITIAL>svar {BEGIN DYNARE_STATEMENT; return token::SVAR;} <INITIAL>svar {BEGIN DYNARE_STATEMENT; return token::SVAR;}
...@@ -186,13 +189,15 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -186,13 +189,15 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<INITIAL>smoother2histval {BEGIN DYNARE_STATEMENT; return token::SMOOTHER2HISTVAL;} <INITIAL>smoother2histval {BEGIN DYNARE_STATEMENT; return token::SMOOTHER2HISTVAL;}
<INITIAL>perfect_foresight_setup {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SETUP;} <INITIAL>perfect_foresight_setup {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SETUP;}
<INITIAL>perfect_foresight_solver {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SOLVER;} <INITIAL>perfect_foresight_solver {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SOLVER;}
<INITIAL>det_cond_forecast {BEGIN DYNARE_STATEMENT; return token::DET_COND_FORECAST;} <INITIAL>perfect_foresight_with_expectation_errors_setup {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SETUP;}
<INITIAL>perfect_foresight_with_expectation_errors_solver {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SOLVER;}
<INITIAL>compilation_setup {BEGIN DYNARE_STATEMENT; return token::COMPILATION_SETUP;}
<INITIAL>model_remove {BEGIN DYNARE_STATEMENT; return token::MODEL_REMOVE;}
<INITIAL>model_options {BEGIN DYNARE_STATEMENT; return token::MODEL_OPTIONS;}
<INITIAL>var_remove {BEGIN DYNARE_STATEMENT; return token::VAR_REMOVE;}
<INITIAL>resid {BEGIN DYNARE_STATEMENT; return token::RESID;}
<DYNARE_STATEMENT>; { <DYNARE_STATEMENT>; {BEGIN INITIAL; return Dynare::parser::token_type (yytext[0]);}
if (!sigma_e)
BEGIN INITIAL;
return Dynare::parser::token_type (yytext[0]);
}
/* Begin of a Dynare block */ /* Begin of a Dynare block */
...@@ -201,8 +206,11 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -201,8 +206,11 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<INITIAL>initval {BEGIN DYNARE_BLOCK; return token::INITVAL;} <INITIAL>initval {BEGIN DYNARE_BLOCK; return token::INITVAL;}
<INITIAL>endval {BEGIN DYNARE_BLOCK; return token::ENDVAL;} <INITIAL>endval {BEGIN DYNARE_BLOCK; return token::ENDVAL;}
<INITIAL>histval {BEGIN DYNARE_BLOCK; return token::HISTVAL;} <INITIAL>histval {BEGIN DYNARE_BLOCK; return token::HISTVAL;}
<INITIAL>filter_initial_state {BEGIN DYNARE_BLOCK; return token::FILTER_INITIAL_STATE;}
<INITIAL>shocks {BEGIN DYNARE_BLOCK; return token::SHOCKS;} <INITIAL>shocks {BEGIN DYNARE_BLOCK; return token::SHOCKS;}
<INITIAL>heteroskedastic_shocks {BEGIN DYNARE_BLOCK; return token::HETEROSKEDASTIC_SHOCKS;}
<INITIAL>shock_groups {BEGIN DYNARE_BLOCK; return token::SHOCK_GROUPS;} <INITIAL>shock_groups {BEGIN DYNARE_BLOCK; return token::SHOCK_GROUPS;}
<INITIAL>init2shocks {BEGIN DYNARE_BLOCK; return token::INIT2SHOCKS;}
<INITIAL>mshocks {BEGIN DYNARE_BLOCK; return token::MSHOCKS;} <INITIAL>mshocks {BEGIN DYNARE_BLOCK; return token::MSHOCKS;}
<INITIAL>estimated_params {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS;} <INITIAL>estimated_params {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS;}
<INITIAL>epilogue {BEGIN DYNARE_BLOCK; return token::EPILOGUE;} <INITIAL>epilogue {BEGIN DYNARE_BLOCK; return token::EPILOGUE;}
...@@ -210,8 +218,10 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -210,8 +218,10 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<INITIAL>priors {BEGIN DYNARE_BLOCK;return token::ESTIMATED_PARAMS;} <INITIAL>priors {BEGIN DYNARE_BLOCK;return token::ESTIMATED_PARAMS;}
<INITIAL>estimated_params_init {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_INIT;} <INITIAL>estimated_params_init {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_INIT;}
<INITIAL>estimated_params_bounds {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_BOUNDS;} <INITIAL>estimated_params_bounds {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_BOUNDS;}
<INITIAL>estimated_params_remove {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_REMOVE;}
<INITIAL>osr_params_bounds {BEGIN DYNARE_BLOCK; return token::OSR_PARAMS_BOUNDS;} <INITIAL>osr_params_bounds {BEGIN DYNARE_BLOCK; return token::OSR_PARAMS_BOUNDS;}
<INITIAL>observation_trends {BEGIN DYNARE_BLOCK; return token::OBSERVATION_TRENDS;} <INITIAL>observation_trends {BEGIN DYNARE_BLOCK; return token::OBSERVATION_TRENDS;}
<INITIAL>deterministic_trends {BEGIN DYNARE_BLOCK; return token::DETERMINISTIC_TRENDS;}
<INITIAL>optim_weights {BEGIN DYNARE_BLOCK; return token::OPTIM_WEIGHTS;} <INITIAL>optim_weights {BEGIN DYNARE_BLOCK; return token::OPTIM_WEIGHTS;}
<INITIAL>homotopy_setup {BEGIN DYNARE_BLOCK; return token::HOMOTOPY_SETUP;} <INITIAL>homotopy_setup {BEGIN DYNARE_BLOCK; return token::HOMOTOPY_SETUP;}
<INITIAL>conditional_forecast_paths {BEGIN DYNARE_BLOCK; return token::CONDITIONAL_FORECAST_PATHS;} <INITIAL>conditional_forecast_paths {BEGIN DYNARE_BLOCK; return token::CONDITIONAL_FORECAST_PATHS;}
...@@ -219,8 +229,14 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -219,8 +229,14 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<INITIAL>moment_calibration {BEGIN DYNARE_BLOCK; return token::MOMENT_CALIBRATION;} <INITIAL>moment_calibration {BEGIN DYNARE_BLOCK; return token::MOMENT_CALIBRATION;}
<INITIAL>irf_calibration {BEGIN DYNARE_BLOCK; return token::IRF_CALIBRATION;} <INITIAL>irf_calibration {BEGIN DYNARE_BLOCK; return token::IRF_CALIBRATION;}
<INITIAL>ramsey_constraints {BEGIN DYNARE_BLOCK; return token::RAMSEY_CONSTRAINTS;} <INITIAL>ramsey_constraints {BEGIN DYNARE_BLOCK; return token::RAMSEY_CONSTRAINTS;}
<INITIAL>restrictions {BEGIN DYNARE_BLOCK; return token::RESTRICTIONS;}
<INITIAL>generate_irfs {BEGIN DYNARE_BLOCK; return token::GENERATE_IRFS;} <INITIAL>generate_irfs {BEGIN DYNARE_BLOCK; return token::GENERATE_IRFS;}
<INITIAL>matched_moments {BEGIN DYNARE_BLOCK; return token::MATCHED_MOMENTS;}
<INITIAL>occbin_constraints {BEGIN DYNARE_BLOCK; return token::OCCBIN_CONSTRAINTS;}
<INITIAL>model_replace {BEGIN DYNARE_BLOCK; return token::MODEL_REPLACE;}
<INITIAL>pac_target_info {BEGIN DYNARE_BLOCK; return token::PAC_TARGET_INFO;}
<INITIAL>matched_irfs {BEGIN DYNARE_BLOCK; return token::MATCHED_IRFS;}
<INITIAL>matched_irfs_weights {BEGIN DYNARE_BLOCK; return token::MATCHED_IRFS_WEIGHTS;}
<INITIAL>perfect_foresight_controlled_paths {BEGIN DYNARE_BLOCK; return token::PERFECT_FORESIGHT_CONTROLLED_PATHS;}
/* For the semicolon after an "end" keyword */ /* For the semicolon after an "end" keyword */
<INITIAL>; {return Dynare::parser::token_type (yytext[0]);} <INITIAL>; {return Dynare::parser::token_type (yytext[0]);}
...@@ -231,7 +247,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -231,7 +247,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>subsamples {return token::SUBSAMPLES;} <DYNARE_STATEMENT>subsamples {return token::SUBSAMPLES;}
<DYNARE_STATEMENT>options {return token::OPTIONS;} <DYNARE_STATEMENT>options {return token::OPTIONS;}
<DYNARE_STATEMENT>prior { <DYNARE_STATEMENT>prior {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::PRIOR; return token::PRIOR;
} }
<INITIAL>std {BEGIN DYNARE_STATEMENT; return token::STD;} <INITIAL>std {BEGIN DYNARE_STATEMENT; return token::STD;}
...@@ -241,31 +257,12 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -241,31 +257,12 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<INITIAL>prior_function {BEGIN DYNARE_STATEMENT; return token::PRIOR_FUNCTION;} <INITIAL>prior_function {BEGIN DYNARE_STATEMENT; return token::PRIOR_FUNCTION;}
<INITIAL>posterior_function {BEGIN DYNARE_STATEMENT; return token::POSTERIOR_FUNCTION;} <INITIAL>posterior_function {BEGIN DYNARE_STATEMENT; return token::POSTERIOR_FUNCTION;}
/* Inside of a Dynare statement */ <DYNARE_STATEMENT,DYNARE_BLOCK>{DATE} {
<DYNARE_STATEMENT>{DATE} { yylval->emplace<string>(yytext);
char *yycopy = strdup(yytext); return token::DATE;
char *uput = yycopy + yyleng;
unput(')');
unput('\'');
while (uput > yycopy)
unput(*--uput);
unput('\'');
unput('(');
unput('s');
unput('e');
unput('t');
unput('a');
unput('d');
free( yycopy );
} }
<DYNARE_STATEMENT>${DATE} { yylloc->step();
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6) /* Inside a Dynare statement */
yyout << yytext + 1;
#else
*yyout << yytext + 1;
#endif
}
<DYNARE_STATEMENT>dates {dates_parens_nb=0; BEGIN DATES_STATEMENT; yylval->build<string>("dates");}
<DYNARE_STATEMENT>file {return token::FILE;} <DYNARE_STATEMENT>file {return token::FILE;}
<DYNARE_STATEMENT>datafile {return token::DATAFILE;} <DYNARE_STATEMENT>datafile {return token::DATAFILE;}
<DYNARE_STATEMENT>dirname {return token::DIRNAME;} <DYNARE_STATEMENT>dirname {return token::DIRNAME;}
...@@ -275,7 +272,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -275,7 +272,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>mean {return token::MEAN;} <DYNARE_STATEMENT>mean {return token::MEAN;}
<DYNARE_STATEMENT>stdev {return token::STDEV;} <DYNARE_STATEMENT>stdev {return token::STDEV;}
<DYNARE_STATEMENT>truncate {return token::TRUNCATE;} <DYNARE_STATEMENT>truncate {return token::TRUNCATE;}
<DYNARE_STATEMENT>domain {return token::DOMAINN;} <DYNARE_STATEMENT>domain {return token::DOMAINN;} // Use altered token name to avoid identifier collision on Windows and macOS
<DYNARE_STATEMENT>variance {return token::VARIANCE;} <DYNARE_STATEMENT>variance {return token::VARIANCE;}
<DYNARE_STATEMENT>mode {return token::MODE;} <DYNARE_STATEMENT>mode {return token::MODE;}
<DYNARE_STATEMENT>interval {return token::INTERVAL;} <DYNARE_STATEMENT>interval {return token::INTERVAL;}
...@@ -286,22 +283,22 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -286,22 +283,22 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>jscale {return token::JSCALE;} <DYNARE_STATEMENT>jscale {return token::JSCALE;}
<DYNARE_STATEMENT>prefilter {return token::PREFILTER;} <DYNARE_STATEMENT>prefilter {return token::PREFILTER;}
<DYNARE_STATEMENT>presample {return token::PRESAMPLE;} <DYNARE_STATEMENT>presample {return token::PRESAMPLE;}
<DYNARE_STATEMENT>lik_algo {return token::LIK_ALGO;}
<DYNARE_STATEMENT>lik_init {return token::LIK_INIT;} <DYNARE_STATEMENT>lik_init {return token::LIK_INIT;}
<DYNARE_STATEMENT>taper_steps {return token::TAPER_STEPS;} <DYNARE_STATEMENT>taper_steps {return token::TAPER_STEPS;}
<DYNARE_STATEMENT>geweke_interval {return token::GEWEKE_INTERVAL;} <DYNARE_STATEMENT>geweke_interval {return token::GEWEKE_INTERVAL;}
<DYNARE_STATEMENT>raftery_lewis_qrs {return token::RAFTERY_LEWIS_QRS;} <DYNARE_STATEMENT>raftery_lewis_qrs {return token::RAFTERY_LEWIS_QRS;}
<DYNARE_STATEMENT>raftery_lewis_diagnostics {return token::RAFTERY_LEWIS_DIAGNOSTICS;} <DYNARE_STATEMENT>raftery_lewis_diagnostics {return token::RAFTERY_LEWIS_DIAGNOSTICS;}
<DYNARE_STATEMENT>brooks_gelman_plotrows {return token::BROOKS_GELMAN_PLOTROWS;}
<DYNARE_STATEMENT>graph {return token::GRAPH;} <DYNARE_STATEMENT>graph {return token::GRAPH;}
<DYNARE_STATEMENT>nograph {return token::NOGRAPH;} <DYNARE_STATEMENT>nograph {return token::NOGRAPH;}
<DYNARE_STATEMENT>posterior_graph {return token::POSTERIOR_GRAPH;} <DYNARE_STATEMENT>posterior_graph {return token::POSTERIOR_GRAPH;}
<DYNARE_STATEMENT>posterior_nograph {return token::POSTERIOR_NOGRAPH;} <DYNARE_STATEMENT>posterior_nograph {return token::POSTERIOR_NOGRAPH;}
<DYNARE_STATEMENT>nodisplay {return token::NODISPLAY;} <DYNARE_STATEMENT>nodisplay {return token::NODISPLAY;}
<DYNARE_STATEMENT>graph_format {return token::GRAPH_FORMAT;} <DYNARE_STATEMENT>graph_format {return token::GRAPH_FORMAT;}
<DYNARE_STATEMENT>eps {yylval->build<string>(yytext); return token::EPS;} <DYNARE_STATEMENT>eps {yylval->emplace<string>(yytext); return token::EPS;}
<DYNARE_STATEMENT>pdf {yylval->build<string>(yytext); return token::PDF;} <DYNARE_STATEMENT>pdf {yylval->emplace<string>(yytext); return token::PDF;}
<DYNARE_STATEMENT>fig {yylval->build<string>(yytext); return token::FIG;} <DYNARE_STATEMENT>fig {yylval->emplace<string>(yytext); return token::FIG;}
<DYNARE_STATEMENT>none {yylval->build<string>(yytext); return token::NONE;} <DYNARE_STATEMENT>none {yylval->emplace<string>(yytext); return token::NONE;}
<DYNARE_STATEMENT>print {return token::PRINT;} <DYNARE_STATEMENT>print {return token::PRINT;}
<DYNARE_STATEMENT>noprint {return token::NOPRINT;} <DYNARE_STATEMENT>noprint {return token::NOPRINT;}
<DYNARE_STATEMENT>conf_sig {return token::CONF_SIG;} <DYNARE_STATEMENT>conf_sig {return token::CONF_SIG;}
...@@ -310,7 +307,9 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -310,7 +307,9 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>mh_drop {return token::MH_DROP;} <DYNARE_STATEMENT>mh_drop {return token::MH_DROP;}
<DYNARE_STATEMENT>mh_jscale {return token::MH_JSCALE;} <DYNARE_STATEMENT>mh_jscale {return token::MH_JSCALE;}
<DYNARE_STATEMENT>mh_init_scale {return token::MH_INIT_SCALE;} <DYNARE_STATEMENT>mh_init_scale {return token::MH_INIT_SCALE;}
<DYNARE_STATEMENT>mh_init_scale_factor {return token::MH_INIT_SCALE_FACTOR;}
<DYNARE_STATEMENT>mh_tune_jscale {return token::MH_TUNE_JSCALE;} <DYNARE_STATEMENT>mh_tune_jscale {return token::MH_TUNE_JSCALE;}
<DYNARE_STATEMENT>mh_tune_guess {return token::MH_TUNE_GUESS;}
<DYNARE_STATEMENT>mode_file {return token::MODE_FILE;} <DYNARE_STATEMENT>mode_file {return token::MODE_FILE;}
<DYNARE_STATEMENT>mode_compute {return token::MODE_COMPUTE;} <DYNARE_STATEMENT>mode_compute {return token::MODE_COMPUTE;}
<DYNARE_STATEMENT>mode_check {return token::MODE_CHECK;} <DYNARE_STATEMENT>mode_check {return token::MODE_CHECK;}
...@@ -318,7 +317,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -318,7 +317,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>mode_check_symmetric_plots {return token::MODE_CHECK_SYMMETRIC_PLOTS;} <DYNARE_STATEMENT>mode_check_symmetric_plots {return token::MODE_CHECK_SYMMETRIC_PLOTS;}
<DYNARE_STATEMENT>mode_check_number_of_points {return token::MODE_CHECK_NUMBER_OF_POINTS;} <DYNARE_STATEMENT>mode_check_number_of_points {return token::MODE_CHECK_NUMBER_OF_POINTS;}
<DYNARE_STATEMENT>prior_trunc {return token::PRIOR_TRUNC;} <DYNARE_STATEMENT>prior_trunc {return token::PRIOR_TRUNC;}
<DYNARE_STATEMENT>mh_mode {return token::MH_MODE;} <DYNARE_STATEMENT>mh_posterior_mode_estimation {return token::MH_POSTERIOR_MODE_ESTIMATION;}
<DYNARE_STATEMENT>mh_nblocks {return token::MH_NBLOCKS;} <DYNARE_STATEMENT>mh_nblocks {return token::MH_NBLOCKS;}
<DYNARE_STATEMENT>load_mh_file {return token::LOAD_MH_FILE;} <DYNARE_STATEMENT>load_mh_file {return token::LOAD_MH_FILE;}
<DYNARE_STATEMENT>load_results_after_load_mh {return token::LOAD_RESULTS_AFTER_LOAD_MH;} <DYNARE_STATEMENT>load_results_after_load_mh {return token::LOAD_RESULTS_AFTER_LOAD_MH;}
...@@ -329,7 +328,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -329,7 +328,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>kalman_algo {return token::KALMAN_ALGO;} <DYNARE_STATEMENT>kalman_algo {return token::KALMAN_ALGO;}
<DYNARE_STATEMENT>fast_kalman_filter {return token::FAST_KALMAN_FILTER;} <DYNARE_STATEMENT>fast_kalman_filter {return token::FAST_KALMAN_FILTER;}
<DYNARE_STATEMENT>kalman_tol {return token::KALMAN_TOL;} <DYNARE_STATEMENT>kalman_tol {return token::KALMAN_TOL;}
<DYNARE_STATEMENT>undiff {return token::UNDIFF;} <DYNARE_STATEMENT>schur_vec_tol {return token::SCHUR_VEC_TOL;}
<DYNARE_STATEMENT>diffuse_kalman_tol {return token::DIFFUSE_KALMAN_TOL;} <DYNARE_STATEMENT>diffuse_kalman_tol {return token::DIFFUSE_KALMAN_TOL;}
<DYNARE_STATEMENT>forecast {return token::FORECAST;} <DYNARE_STATEMENT>forecast {return token::FORECAST;}
<DYNARE_STATEMENT>smoother {return token::SMOOTHER;} <DYNARE_STATEMENT>smoother {return token::SMOOTHER;}
...@@ -344,13 +343,15 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -344,13 +343,15 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT,DYNARE_BLOCK>relative_irf {return token::RELATIVE_IRF;} <DYNARE_STATEMENT,DYNARE_BLOCK>relative_irf {return token::RELATIVE_IRF;}
<DYNARE_STATEMENT>tex {return token::TEX;} <DYNARE_STATEMENT>tex {return token::TEX;}
<DYNARE_STATEMENT>nomoments {return token::NOMOMENTS;} <DYNARE_STATEMENT>nomoments {return token::NOMOMENTS;}
<DYNARE_STATEMENT>nomodelsummary {return token::NOMODELSUMMARY;}
<DYNARE_STATEMENT>std {return token::STD;} <DYNARE_STATEMENT>std {return token::STD;}
<DYNARE_STATEMENT>corr {return token::CORR;} <DYNARE_STATEMENT>corr {return token::CORR;}
<DYNARE_STATEMENT>nocorr {return token::NOCORR;} <DYNARE_STATEMENT>nocorr {return token::NOCORR;}
<DYNARE_STATEMENT>optim {return token::OPTIM;} <DYNARE_STATEMENT>optim {return token::OPTIM;}
<DYNARE_STATEMENT>periods {return token::PERIODS;} <DYNARE_STATEMENT>periods {return token::PERIODS;}
<DYNARE_BLOCK>from_initval_to_endval {return token::FROM_INITVAL_TO_ENDVAL;}
<DYNARE_STATEMENT>endval_steady {return token::ENDVAL_STEADY;}
<DYNARE_STATEMENT,DYNARE_BLOCK>model_name {return token::MODEL_NAME;} <DYNARE_STATEMENT,DYNARE_BLOCK>model_name {return token::MODEL_NAME;}
<DYNARE_STATEMENT>var_model_name {return token::VAR_MODEL_NAME;}
<DYNARE_STATEMENT>auxiliary_model_name {return token::AUXILIARY_MODEL_NAME;} <DYNARE_STATEMENT>auxiliary_model_name {return token::AUXILIARY_MODEL_NAME;}
<DYNARE_STATEMENT>endogenous_terminal_period {return token::ENDOGENOUS_TERMINAL_PERIOD;} <DYNARE_STATEMENT>endogenous_terminal_period {return token::ENDOGENOUS_TERMINAL_PERIOD;}
<DYNARE_STATEMENT>sub_draws {return token::SUB_DRAWS;} <DYNARE_STATEMENT>sub_draws {return token::SUB_DRAWS;}
...@@ -362,6 +363,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -362,6 +363,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>constant {return token::CONSTANT;} <DYNARE_STATEMENT>constant {return token::CONSTANT;}
<DYNARE_STATEMENT>noconstant {return token::NOCONSTANT;} <DYNARE_STATEMENT>noconstant {return token::NOCONSTANT;}
<DYNARE_STATEMENT>filename {return token::FILENAME;} <DYNARE_STATEMENT>filename {return token::FILENAME;}
<DYNARE_STATEMENT>conditional_likelihood {return token::CONDITIONAL_LIKELIHOOD;}
<DYNARE_STATEMENT>diffuse_filter {return token::DIFFUSE_FILTER;} <DYNARE_STATEMENT>diffuse_filter {return token::DIFFUSE_FILTER;}
<DYNARE_STATEMENT>plot_priors {return token::PLOT_PRIORS;} <DYNARE_STATEMENT>plot_priors {return token::PLOT_PRIORS;}
<DYNARE_STATEMENT>aim_solver {return token::AIM_SOLVER;} <DYNARE_STATEMENT>aim_solver {return token::AIM_SOLVER;}
...@@ -385,10 +387,8 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -385,10 +387,8 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>restriction_fname {return token::RESTRICTION_FNAME;} <DYNARE_STATEMENT>restriction_fname {return token::RESTRICTION_FNAME;}
<DYNARE_STATEMENT>nlags {return token::NLAGS;} <DYNARE_STATEMENT>nlags {return token::NLAGS;}
<DYNARE_STATEMENT>restrictions {return token::RESTRICTIONS;} <DYNARE_STATEMENT>restrictions {return token::RESTRICTIONS;}
<DYNARE_BLOCK>crossequations {return token::CROSSEQUATIONS;}
<DYNARE_BLOCK>covariance {return token::COVARIANCE;}
<DYNARE_BLOCK>adl {return token::ADL;} <DYNARE_BLOCK>adl {return token::ADL;}
<DYNARE_BLOCK>diff {return token::DIFF;} <DYNARE_STATEMENT,DYNARE_BLOCK>diff {return token::DIFF;}
<DYNARE_STATEMENT>cross_restrictions {return token::CROSS_RESTRICTIONS;} <DYNARE_STATEMENT>cross_restrictions {return token::CROSS_RESTRICTIONS;}
<DYNARE_STATEMENT>contemp_reduced_form {return token::CONTEMP_REDUCED_FORM;} <DYNARE_STATEMENT>contemp_reduced_form {return token::CONTEMP_REDUCED_FORM;}
<DYNARE_STATEMENT>real_pseudo_forecast {return token::REAL_PSEUDO_FORECAST;} <DYNARE_STATEMENT>real_pseudo_forecast {return token::REAL_PSEUDO_FORECAST;}
...@@ -406,7 +406,9 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -406,7 +406,9 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>logarithmic_reduction {return token::LOGARITHMIC_REDUCTION;} <DYNARE_STATEMENT>logarithmic_reduction {return token::LOGARITHMIC_REDUCTION;}
<DYNARE_STATEMENT>use_univariate_filters_if_singularity_is_detected {return token::USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED;} <DYNARE_STATEMENT>use_univariate_filters_if_singularity_is_detected {return token::USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED;}
<DYNARE_STATEMENT>hybrid {return token::HYBRID;} <DYNARE_STATEMENT>hybrid {return token::HYBRID;}
<DYNARE_STATEMENT>use_first_order_solution {return token::USE_FIRST_ORDER_SOLUTION;}
<DYNARE_STATEMENT>default {return token::DEFAULT;} <DYNARE_STATEMENT>default {return token::DEFAULT;}
<DYNARE_STATEMENT>init2shocks {return token::INIT2SHOCKS;}
<DYNARE_STATEMENT>number_of_particles {return token::NUMBER_OF_PARTICLES;} <DYNARE_STATEMENT>number_of_particles {return token::NUMBER_OF_PARTICLES;}
<DYNARE_STATEMENT>resampling {return token::RESAMPLING;} <DYNARE_STATEMENT>resampling {return token::RESAMPLING;}
...@@ -417,6 +419,11 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -417,6 +419,11 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>kitagawa {return token::KITAGAWA;} <DYNARE_STATEMENT>kitagawa {return token::KITAGAWA;}
<DYNARE_STATEMENT>smooth {return token::SMOOTH;} <DYNARE_STATEMENT>smooth {return token::SMOOTH;}
<DYNARE_STATEMENT>stratified {return token::STRATIFIED;} <DYNARE_STATEMENT>stratified {return token::STRATIFIED;}
<DYNARE_STATEMENT>residual {
yylval->emplace<string>(yytext);
return token::RESIDUAL;
}
<DYNARE_STATEMENT>multinomial {return token::MULTINOMIAL;}
<DYNARE_STATEMENT>cpf_weights {return token::CPF_WEIGHTS;} <DYNARE_STATEMENT>cpf_weights {return token::CPF_WEIGHTS;}
<DYNARE_STATEMENT>amisanotristani {return token::AMISANOTRISTANI;} <DYNARE_STATEMENT>amisanotristani {return token::AMISANOTRISTANI;}
<DYNARE_STATEMENT>murrayjonesparslow {return token::MURRAYJONESPARSLOW;} <DYNARE_STATEMENT>murrayjonesparslow {return token::MURRAYJONESPARSLOW;}
...@@ -431,45 +438,47 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -431,45 +438,47 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>no_posterior_kernel_density {return token::NO_POSTERIOR_KERNEL_DENSITY;} <DYNARE_STATEMENT>no_posterior_kernel_density {return token::NO_POSTERIOR_KERNEL_DENSITY;}
<DYNARE_STATEMENT>rescale_prediction_error_covariance {return token::RESCALE_PREDICTION_ERROR_COVARIANCE;} <DYNARE_STATEMENT>rescale_prediction_error_covariance {return token::RESCALE_PREDICTION_ERROR_COVARIANCE;}
<DYNARE_STATEMENT>use_penalized_objective_for_hessian {return token::USE_PENALIZED_OBJECTIVE_FOR_HESSIAN;} <DYNARE_STATEMENT>use_penalized_objective_for_hessian {return token::USE_PENALIZED_OBJECTIVE_FOR_HESSIAN;}
<DYNARE_STATEMENT>expression {return token::EXPRESSION;}
<DYNARE_STATEMENT>first_simulation_period {return token::FIRST_SIMULATION_PERIOD;}
<DYNARE_STATEMENT>last_simulation_period {return token::LAST_SIMULATION_PERIOD;}
<DYNARE_STATEMENT>no_init_estimation_check_first_obs {return token::NO_INIT_ESTIMATION_CHECK_FIRST_OBS;}
<DYNARE_STATEMENT>fsolve_options {return token::FSOLVE_OPTIONS;}
<DYNARE_STATEMENT>alpha { <DYNARE_STATEMENT>alpha {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::ALPHA; return token::ALPHA;
} }
<DYNARE_STATEMENT>beta { <DYNARE_STATEMENT>beta {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::BETA; return token::BETA;
} }
<DYNARE_STATEMENT>gamma { <DYNARE_STATEMENT>gamma {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::GAMMA; return token::GAMMA;
} }
<DYNARE_STATEMENT>inv_gamma { <DYNARE_STATEMENT>inv_gamma {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::INV_GAMMA; return token::INV_GAMMA;
} }
<DYNARE_STATEMENT>inv_gamma1 { <DYNARE_STATEMENT>inv_gamma1 {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::INV_GAMMA1; return token::INV_GAMMA1;
} }
<DYNARE_STATEMENT>inv_gamma2 { <DYNARE_STATEMENT>inv_gamma2 {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::INV_GAMMA2; return token::INV_GAMMA2;
} }
<DYNARE_STATEMENT>dirichlet { <DYNARE_STATEMENT>dirichlet {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::DIRICHLET; return token::DIRICHLET;
} }
<DYNARE_STATEMENT>weibull { <DYNARE_STATEMENT>weibull {return token::WEIBULL;}
yylval->build<string>(yytext);
return token::WEIBULL;
}
<DYNARE_STATEMENT>normal { <DYNARE_STATEMENT>normal {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NORMAL; return token::NORMAL;
} }
<DYNARE_STATEMENT>uniform { <DYNARE_STATEMENT>uniform {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::UNIFORM; return token::UNIFORM;
} }
<DYNARE_STATEMENT>gsig2_lmdm {return token::GSIG2_LMDM;} <DYNARE_STATEMENT>gsig2_lmdm {return token::GSIG2_LMDM;}
...@@ -480,13 +489,13 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -480,13 +489,13 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>ncsk {return token::NCSK;} <DYNARE_STATEMENT>ncsk {return token::NCSK;}
<DYNARE_STATEMENT>nstd {return token::NSTD;} <DYNARE_STATEMENT>nstd {return token::NSTD;}
<DYNARE_STATEMENT>ninv { <DYNARE_STATEMENT>ninv {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NINV; return token::NINV;
} }
<DYNARE_STATEMENT>indxparr {return token::INDXPARR;} <DYNARE_STATEMENT>indxparr {return token::INDXPARR;}
<DYNARE_STATEMENT>indxovr {return token::INDXOVR;} <DYNARE_STATEMENT>indxovr {return token::INDXOVR;}
<DYNARE_STATEMENT>aband { <DYNARE_STATEMENT>aband {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::ABAND; return token::ABAND;
} }
<DYNARE_STATEMENT>write_equation_tags {return token::WRITE_EQUATION_TAGS;} <DYNARE_STATEMENT>write_equation_tags {return token::WRITE_EQUATION_TAGS;}
...@@ -503,18 +512,18 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -503,18 +512,18 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>indxgdls {return token::INDXGDLS;} <DYNARE_STATEMENT>indxgdls {return token::INDXGDLS;}
<DYNARE_STATEMENT>eq_ms {return token::EQ_MS;} <DYNARE_STATEMENT>eq_ms {return token::EQ_MS;}
<DYNARE_STATEMENT>cms { <DYNARE_STATEMENT>cms {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::CMS; return token::CMS;
} }
<DYNARE_STATEMENT>ncms { <DYNARE_STATEMENT>ncms {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NCMS; return token::NCMS;
} }
<DYNARE_STATEMENT>eq_cms {return token::EQ_CMS;} <DYNARE_STATEMENT>eq_cms {return token::EQ_CMS;}
<DYNARE_STATEMENT>tlindx {return token::TLINDX;} <DYNARE_STATEMENT>tlindx {return token::TLINDX;}
<DYNARE_STATEMENT>tlnumber {return token::TLNUMBER;} <DYNARE_STATEMENT>tlnumber {return token::TLNUMBER;}
<DYNARE_STATEMENT>cnum { <DYNARE_STATEMENT>cnum {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::CNUM; return token::CNUM;
} }
<DYNARE_STATEMENT>nodecomposition {return token::NODECOMPOSITION;}; <DYNARE_STATEMENT>nodecomposition {return token::NODECOMPOSITION;};
...@@ -552,6 +561,33 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -552,6 +561,33 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>max_block_iterations {return token::MAX_BLOCK_ITERATIONS;} <DYNARE_STATEMENT>max_block_iterations {return token::MAX_BLOCK_ITERATIONS;}
<DYNARE_STATEMENT>max_repeated_optimization_runs {return token::MAX_REPEATED_OPTIMIZATION_RUNS;} <DYNARE_STATEMENT>max_repeated_optimization_runs {return token::MAX_REPEATED_OPTIMIZATION_RUNS;}
<DYNARE_STATEMENT>maxit {return token::MAXIT;} <DYNARE_STATEMENT>maxit {return token::MAXIT;}
<DYNARE_STATEMENT>simul_maxit {return token::SIMUL_MAXIT;}
<DYNARE_STATEMENT>likelihood_maxit {return token::LIKELIHOOD_MAXIT;}
<DYNARE_STATEMENT>smoother_maxit {return token::SMOOTHER_MAXIT;}
<DYNARE_STATEMENT>simul_periods {return token::SIMUL_PERIODS;}
<DYNARE_STATEMENT>likelihood_periods {return token::LIKELIHOOD_PERIODS;}
<DYNARE_STATEMENT>smoother_periods {return token::SMOOTHER_PERIODS;}
<DYNARE_STATEMENT>simul_curb_retrench {return token::SIMUL_CURB_RETRENCH;}
<DYNARE_STATEMENT>likelihood_curb_retrench {return token::LIKELIHOOD_CURB_RETRENCH;}
<DYNARE_STATEMENT>smoother_curb_retrench {return token::SMOOTHER_CURB_RETRENCH;}
<DYNARE_STATEMENT>simul_check_ahead_periods {return token::SIMUL_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>simul_max_check_ahead_periods {return token::SIMUL_MAX_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>simul_reset_check_ahead_periods {return token::SIMUL_RESET_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>likelihood_check_ahead_periods {return token::LIKELIHOOD_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>likelihood_max_check_ahead_periods {return token::LIKELIHOOD_MAX_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>smoother_check_ahead_periods {return token::SMOOTHER_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>smoother_max_check_ahead_periods {return token::SMOOTHER_MAX_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>simul_debug {return token::SIMUL_DEBUG;}
<DYNARE_STATEMENT>smoother_debug {return token::SMOOTHER_DEBUG;}
<DYNARE_STATEMENT>simul_periodic_solution {return token::SIMUL_PERIODIC_SOLUTION;}
<DYNARE_STATEMENT>likelihood_periodic_solution {return token::LIKELIHOOD_PERIODIC_SOLUTION;}
<DYNARE_STATEMENT>smoother_periodic_solution {return token::SMOOTHER_PERIODIC_SOLUTION;}
<DYNARE_STATEMENT>likelihood_inversion_filter {return token::LIKELIHOOD_INVERSION_FILTER;}
<DYNARE_STATEMENT>likelihood_piecewise_kalman_filter {return token::LIKELIHOOD_PIECEWISE_KALMAN_FILTER;}
<DYNARE_STATEMENT>likelihood_max_kalman_iterations {return token::LIKELIHOOD_MAX_KALMAN_ITERATIONS;}
<DYNARE_STATEMENT>smoother_inversion_filter {return token::SMOOTHER_INVERSION_FILTER;}
<DYNARE_STATEMENT>smoother_piecewise_kalman_filter {return token::SMOOTHER_PIECEWISE_KALMAN_FILTER;}
<DYNARE_STATEMENT>filter_use_relaxation {return token::FILTER_USE_RELEXATION;}
<DYNARE_STATEMENT>function_convergence_criterion {return token::FUNCTION_CONVERGENCE_CRITERION;} <DYNARE_STATEMENT>function_convergence_criterion {return token::FUNCTION_CONVERGENCE_CRITERION;}
<DYNARE_STATEMENT>parameter_convergence_criterion {return token::PARAMETER_CONVERGENCE_CRITERION;} <DYNARE_STATEMENT>parameter_convergence_criterion {return token::PARAMETER_CONVERGENCE_CRITERION;}
<DYNARE_STATEMENT>number_of_large_perturbations {return token::NUMBER_OF_LARGE_PERTURBATIONS;} <DYNARE_STATEMENT>number_of_large_perturbations {return token::NUMBER_OF_LARGE_PERTURBATIONS;}
...@@ -563,19 +599,15 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -563,19 +599,15 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>tolf {return token::TOLF;} <DYNARE_STATEMENT>tolf {return token::TOLF;}
<DYNARE_STATEMENT>tolx {return token::TOLX;} <DYNARE_STATEMENT>tolx {return token::TOLX;}
<DYNARE_STATEMENT>opt_algo {return token::OPT_ALGO;} <DYNARE_STATEMENT>opt_algo {return token::OPT_ALGO;}
<DYNARE_STATEMENT>add_flags {return token::ADD_FLAGS;}
<DYNARE_STATEMENT>substitute_flags {return token::SUBSTITUTE_FLAGS;}
<DYNARE_STATEMENT>add_libs {return token::ADD_LIBS;}
<DYNARE_STATEMENT>substitute_libs {return token::SUBSTITUTE_LIBS;}
<DYNARE_STATEMENT>compiler {return token::COMPILER;}
<DYNARE_STATEMENT>instruments {return token::INSTRUMENTS;} <DYNARE_STATEMENT>instruments {return token::INSTRUMENTS;}
<DYNARE_STATEMENT>hessian { <DYNARE_STATEMENT>hessian {return token::HESSIAN;}
yylval->build<string>(yytext); <DYNARE_STATEMENT>prior_variance {return token::PRIOR_VARIANCE;}
return token::HESSIAN; <DYNARE_STATEMENT>identity_matrix {return token::IDENTITY_MATRIX;}
}
<DYNARE_STATEMENT>prior_variance {
yylval->build<string>(yytext);
return token::PRIOR_VARIANCE;
}
<DYNARE_STATEMENT>identity_matrix {
yylval->build<string>(yytext);
return token::IDENTITY_MATRIX;
}
<DYNARE_STATEMENT>mcmc_jumping_covariance {return token::MCMC_JUMPING_COVARIANCE;} <DYNARE_STATEMENT>mcmc_jumping_covariance {return token::MCMC_JUMPING_COVARIANCE;}
/* These four (var, varexo, varexo_det, parameters) are for change_type */ /* These four (var, varexo, varexo_det, parameters) are for change_type */
...@@ -597,14 +629,28 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -597,14 +629,28 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>homotopy_mode {return token::HOMOTOPY_MODE; } <DYNARE_STATEMENT>homotopy_mode {return token::HOMOTOPY_MODE; }
<DYNARE_STATEMENT>homotopy_steps {return token::HOMOTOPY_STEPS; } <DYNARE_STATEMENT>homotopy_steps {return token::HOMOTOPY_STEPS; }
<DYNARE_STATEMENT>homotopy_force_continue {return token::HOMOTOPY_FORCE_CONTINUE;} <DYNARE_STATEMENT>homotopy_force_continue {return token::HOMOTOPY_FORCE_CONTINUE;}
<DYNARE_STATEMENT>homotopy_max_completion_share {return token::HOMOTOPY_MAX_COMPLETION_SHARE;}
<DYNARE_STATEMENT>homotopy_min_step_size {return token::HOMOTOPY_MIN_STEP_SIZE;}
<DYNARE_STATEMENT>homotopy_initial_step_size {return token::HOMOTOPY_INITIAL_STEP_SIZE;}
<DYNARE_STATEMENT>homotopy_step_size_increase_success_count {return token::HOMOTOPY_STEP_SIZE_INCREASE_SUCCESS_COUNT;}
<DYNARE_STATEMENT>homotopy_linearization_fallback {return token::HOMOTOPY_LINEARIZATION_FALLBACK;}
<DYNARE_STATEMENT>homotopy_marginal_linearization_fallback {return token::HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK;}
<DYNARE_STATEMENT>homotopy_exclude_varexo {return token::HOMOTOPY_EXCLUDE_VAREXO;}
<DYNARE_STATEMENT>nocheck {return token::NOCHECK; } <DYNARE_STATEMENT>nocheck {return token::NOCHECK; }
<DYNARE_STATEMENT>steady_solve_algo {return token::STEADY_SOLVE_ALGO;}
<DYNARE_STATEMENT>steady_maxit {return token::STEADY_MAXIT;}
<DYNARE_STATEMENT>steady_tolf {return token::STEADY_TOLF;}
<DYNARE_STATEMENT>steady_tolx {return token::STEADY_TOLX;}
<DYNARE_STATEMENT>steady_markowitz {return token::STEADY_MARKOWITZ;}
<DYNARE_STATEMENT>controlled_varexo {return token::CONTROLLED_VAREXO; } <DYNARE_STATEMENT>controlled_varexo {return token::CONTROLLED_VAREXO; }
<DYNARE_STATEMENT>parameter_set {return token::PARAMETER_SET; } <DYNARE_STATEMENT>parameter_set {return token::PARAMETER_SET; }
<DYNARE_STATEMENT>init_state {return token::INIT_STATE; } <DYNARE_STATEMENT>init_state {return token::INIT_STATE; }
<DYNARE_STATEMENT>fast_realtime {return token::FAST_REALTIME; } <DYNARE_STATEMENT>fast_realtime {return token::FAST_REALTIME; }
<DYNARE_STATEMENT>save_realtime {return token::SAVE_REALTIME;} <DYNARE_STATEMENT>save_realtime {return token::SAVE_REALTIME;}
<DYNARE_STATEMENT>detail_plot {return token::DETAIL_PLOT;} <DYNARE_STATEMENT>detail_plot {return token::DETAIL_PLOT;}
<DYNARE_STATEMENT>flip {return token::FLIP;}
<DYNARE_STATEMENT>interactive {return token::INTERACTIVE;} <DYNARE_STATEMENT>interactive {return token::INTERACTIVE;}
<DYNARE_STATEMENT>screen_shocks {return token::SCREEN_SHOCKS;} <DYNARE_STATEMENT>screen_shocks {return token::SCREEN_SHOCKS;}
<DYNARE_STATEMENT>steadystate {return token::STEADYSTATE;} <DYNARE_STATEMENT>steadystate {return token::STEADYSTATE;}
...@@ -612,6 +658,8 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -612,6 +658,8 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>qoq {return token::QOQ; } <DYNARE_STATEMENT>qoq {return token::QOQ; }
<DYNARE_STATEMENT>yoy {return token::YOY; } <DYNARE_STATEMENT>yoy {return token::YOY; }
<DYNARE_STATEMENT>aoa {return token::AOA; } <DYNARE_STATEMENT>aoa {return token::AOA; }
<DYNARE_STATEMENT>unconditional {return token::UNCONDITIONAL; }
<DYNARE_STATEMENT>conditional {return token::CONDITIONAL; }
<DYNARE_STATEMENT>fig_name {return token::FIG_NAME;} <DYNARE_STATEMENT>fig_name {return token::FIG_NAME;}
<DYNARE_STATEMENT>write_xls {return token::WRITE_XLS;} <DYNARE_STATEMENT>write_xls {return token::WRITE_XLS;}
<DYNARE_STATEMENT>realtime {return token::REALTIME;} <DYNARE_STATEMENT>realtime {return token::REALTIME;}
...@@ -624,8 +672,10 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -624,8 +672,10 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>mle_mode {return token::MLE_MODE; } <DYNARE_STATEMENT>mle_mode {return token::MLE_MODE; }
<DYNARE_STATEMENT>k_order_solver {return token::K_ORDER_SOLVER; } <DYNARE_STATEMENT>k_order_solver {return token::K_ORDER_SOLVER; }
<DYNARE_STATEMENT>filter_covariance {return token::FILTER_COVARIANCE; } <DYNARE_STATEMENT>filter_covariance {return token::FILTER_COVARIANCE; }
<DYNARE_STATEMENT>updated_covariance {return token::UPDATED_COVARIANCE; }
<DYNARE_STATEMENT>filter_decomposition {return token::FILTER_DECOMPOSITION; } <DYNARE_STATEMENT>filter_decomposition {return token::FILTER_DECOMPOSITION; }
<DYNARE_STATEMENT>smoothed_state_uncertainty {return token::SMOOTHED_STATE_UNCERTAINTY; } <DYNARE_STATEMENT>smoothed_state_uncertainty {return token::SMOOTHED_STATE_UNCERTAINTY; }
<DYNARE_STATEMENT>smoother_redux {return token::SMOOTHER_REDUX; }
<DYNARE_STATEMENT>selected_variables_only {return token::SELECTED_VARIABLES_ONLY; } <DYNARE_STATEMENT>selected_variables_only {return token::SELECTED_VARIABLES_ONLY; }
<DYNARE_STATEMENT>pruning {return token::PRUNING; } <DYNARE_STATEMENT>pruning {return token::PRUNING; }
<DYNARE_STATEMENT>save_draws {return token::SAVE_DRAWS; } <DYNARE_STATEMENT>save_draws {return token::SAVE_DRAWS; }
...@@ -634,7 +684,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -634,7 +684,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>epilogue {return token::EPILOGUE;} <DYNARE_STATEMENT>epilogue {return token::EPILOGUE;}
<DYNARE_STATEMENT>growth_factor {return token::GROWTH_FACTOR;} <DYNARE_STATEMENT>growth_factor {return token::GROWTH_FACTOR;}
<DYNARE_STATEMENT>log_growth_factor {return token::LOG_GROWTH_FACTOR;} <DYNARE_STATEMENT>log_growth_factor {return token::LOG_GROWTH_FACTOR;}
<DYNARE_STATEMENT>growth {return token::GROWTH;} <DYNARE_STATEMENT,DYNARE_BLOCK>growth {return token::GROWTH;}
<DYNARE_STATEMENT>cova_compute {return token::COVA_COMPUTE;} <DYNARE_STATEMENT>cova_compute {return token::COVA_COMPUTE;}
<DYNARE_STATEMENT>discretionary_tol {return token::DISCRETIONARY_TOL;} <DYNARE_STATEMENT>discretionary_tol {return token::DISCRETIONARY_TOL;}
<DYNARE_STATEMENT>analytic_derivation {return token::ANALYTIC_DERIVATION;} <DYNARE_STATEMENT>analytic_derivation {return token::ANALYTIC_DERIVATION;}
...@@ -642,6 +692,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -642,6 +692,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>solver_periods {return token::SOLVER_PERIODS;} <DYNARE_STATEMENT>solver_periods {return token::SOLVER_PERIODS;}
<DYNARE_STATEMENT>endogenous_prior {return token::ENDOGENOUS_PRIOR;} <DYNARE_STATEMENT>endogenous_prior {return token::ENDOGENOUS_PRIOR;}
<DYNARE_STATEMENT>consider_all_endogenous {return token::CONSIDER_ALL_ENDOGENOUS;} <DYNARE_STATEMENT>consider_all_endogenous {return token::CONSIDER_ALL_ENDOGENOUS;}
<DYNARE_STATEMENT>consider_all_endogenous_and_auxiliary {return token::CONSIDER_ALL_ENDOGENOUS_AND_AUXILIARY;}
<DYNARE_STATEMENT>consider_only_observed {return token::CONSIDER_ONLY_OBSERVED;} <DYNARE_STATEMENT>consider_only_observed {return token::CONSIDER_ONLY_OBSERVED;}
<DYNARE_STATEMENT>infile {return token::INFILE;} <DYNARE_STATEMENT>infile {return token::INFILE;}
<DYNARE_STATEMENT>invars {return token::INVARS;} <DYNARE_STATEMENT>invars {return token::INVARS;}
...@@ -654,25 +705,28 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -654,25 +705,28 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>posterior_sampler_options {return token::POSTERIOR_SAMPLER_OPTIONS;} <DYNARE_STATEMENT>posterior_sampler_options {return token::POSTERIOR_SAMPLER_OPTIONS;}
<DYNARE_STATEMENT>silent_optimizer {return token::SILENT_OPTIMIZER;} <DYNARE_STATEMENT>silent_optimizer {return token::SILENT_OPTIMIZER;}
<DYNARE_STATEMENT>lmmcp {return token::LMMCP;} <DYNARE_STATEMENT>lmmcp {return token::LMMCP;}
<DYNARE_STATEMENT>occbin {return token::OCCBIN;} <DYNARE_STATEMENT>additional_optimizer_steps {return token::ADDITIONAL_OPTIMIZER_STEPS;}
<DYNARE_STATEMENT>centered_moments {return token::CENTERED_MOMENTS; }
<DYNARE_STATEMENT>autolag {return token::AUTOLAG; }
<DYNARE_STATEMENT>recursive_order_estimation {return token::RECURSIVE_ORDER_ESTIMATION; }
<DYNARE_STATEMENT>bartlett_kernel_lag {return token::BARTLETT_KERNEL_LAG; } <DYNARE_STATEMENT>bartlett_kernel_lag {return token::BARTLETT_KERNEL_LAG; }
<DYNARE_STATEMENT>optimal { <DYNARE_STATEMENT>gmm {return token::GMM;}
yylval->build<string>(yytext); <DYNARE_STATEMENT>smm {return token::SMM;}
return token::OPTIMAL; <DYNARE_STATEMENT>irf_matching {return token::IRF_MATCHING;}
} <DYNARE_STATEMENT>stoch_simul {return token::STOCH_SIMUL;}
<DYNARE_STATEMENT>diagonal {
yylval->build<string>(yytext);
return token::DIAGONAL;
}
<DYNARE_STATEMENT>weighting_matrix {return token::WEIGHTING_MATRIX; } <DYNARE_STATEMENT>weighting_matrix {return token::WEIGHTING_MATRIX; }
<DYNARE_STATEMENT>weighting_matrix_scaling_factor {return token::WEIGHTING_MATRIX_SCALING_FACTOR; }
<DYNARE_STATEMENT>analytic_standard_errors {return token::ANALYTIC_STANDARD_ERRORS; }
<DYNARE_STATEMENT>analytic_jacobian {return token::ANALYTIC_JACOBIAN; }
<DYNARE_STATEMENT>mom_method {return token::MOM_METHOD; }
<DYNARE_STATEMENT>simulation_method {return token::SIMULATION_METHOD; }
<DYNARE_STATEMENT>penalized_estimator {return token::PENALIZED_ESTIMATOR; } <DYNARE_STATEMENT>penalized_estimator {return token::PENALIZED_ESTIMATOR; }
<DYNARE_STATEMENT>verbose {return token::VERBOSE; } <DYNARE_STATEMENT>verbose {return token::VERBOSE; }
<DYNARE_STATEMENT>simulation_multiple {return token::SIMULATION_MULTIPLE; } <DYNARE_STATEMENT>simulation_multiple {return token::SIMULATION_MULTIPLE; }
<DYNARE_STATEMENT>burnin {return token::BURNIN; }
<DYNARE_STATEMENT>seed {return token::SEED; } <DYNARE_STATEMENT>seed {return token::SEED; }
<DYNARE_STATEMENT>se_tolx {return token::SE_TOLX;}
<DYNARE_STATEMENT>bounded_shock_support {return token::BOUNDED_SHOCK_SUPPORT; } <DYNARE_STATEMENT>bounded_shock_support {return token::BOUNDED_SHOCK_SUPPORT; }
<DYNARE_STATEMENT>irf_matching_file {return token::IRF_MATCHING_FILE;}
<DYNARE_STATEMENT>add_tiny_number_to_cholesky {return token::ADD_TINY_NUMBER_TO_CHOLESKY; }
<DYNARE_STATEMENT>analytical_girf {return token::ANALYTICAL_GIRF; } <DYNARE_STATEMENT>analytical_girf {return token::ANALYTICAL_GIRF; }
<DYNARE_STATEMENT>irf_in_percent {return token::IRF_IN_PERCENT; } <DYNARE_STATEMENT>irf_in_percent {return token::IRF_IN_PERCENT; }
<DYNARE_STATEMENT>emas_girf {return token::EMAS_GIRF; } <DYNARE_STATEMENT>emas_girf {return token::EMAS_GIRF; }
...@@ -680,21 +734,64 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -680,21 +734,64 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>emas_tolf {return token::EMAS_TOLF; } <DYNARE_STATEMENT>emas_tolf {return token::EMAS_TOLF; }
<DYNARE_STATEMENT>emas_max_iter {return token::EMAS_MAX_ITER; } <DYNARE_STATEMENT>emas_max_iter {return token::EMAS_MAX_ITER; }
<DYNARE_STATEMENT>variable {return token::VARIABLE;} <DYNARE_STATEMENT>variable {return token::VARIABLE;}
<DYNARE_STATEMENT>no_identification_strength {return token::NO_IDENTIFICATION_STRENGTH;}
<DYNARE_STATEMENT>[\$][^$]*[\$] { <DYNARE_STATEMENT>no_identification_reducedform {return token::NO_IDENTIFICATION_REDUCEDFORM;}
strtok(yytext+1, "$"); <DYNARE_STATEMENT>no_identification_moments {return token::NO_IDENTIFICATION_MOMENTS;}
yylval->build<string>(yytext + 1); <DYNARE_STATEMENT>no_identification_minimal {return token::NO_IDENTIFICATION_MINIMAL;}
<DYNARE_STATEMENT>no_identification_spectrum {return token::NO_IDENTIFICATION_SPECTRUM;}
<DYNARE_STATEMENT>normalize_jacobians {return token::NORMALIZE_JACOBIANS;}
<DYNARE_STATEMENT>grid_nbr {return token::GRID_NBR;}
<DYNARE_STATEMENT>tol_rank {return token::TOL_RANK;}
<DYNARE_STATEMENT>tol_deriv {return token::TOL_DERIV;}
<DYNARE_STATEMENT>tol_sv {return token::TOL_SV;}
<DYNARE_STATEMENT>checks_via_subsets {return token::CHECKS_VIA_SUBSETS;}
<DYNARE_STATEMENT>max_dim_subsets_groups {return token::MAX_DIM_SUBSETS_GROUPS;}
<DYNARE_STATEMENT>max_nrows {return token::MAX_NROWS;}
<DYNARE_STATEMENT>with_epilogue {return token::WITH_EPILOGUE;}
<DYNARE_STATEMENT>heteroskedastic_filter {return token::HETEROSKEDASTIC_FILTER;}
<DYNARE_STATEMENT>non_zero {return token::NON_ZERO;}
<DYNARE_STATEMENT>preconditioner {return token::PRECONDITIONER;}
<DYNARE_STATEMENT>umfiter {return token::UMFITER;}
<DYNARE_STATEMENT>iterstack {return token::ITERSTACK;}
<DYNARE_STATEMENT>ilu {return token::ILU;}
<DYNARE_STATEMENT>iter_tol {return token::ITER_TOL;}
<DYNARE_STATEMENT>iter_maxit {return token::ITER_MAXIT;}
<DYNARE_STATEMENT>gmres_restart {return token::GMRES_RESTART;}
<DYNARE_STATEMENT>iterstack_maxlu {return token::ITERSTACK_MAXLU;}
<DYNARE_STATEMENT>iterstack_nperiods {return token::ITERSTACK_NPERIODS;}
<DYNARE_STATEMENT>iterstack_nlu {return token::ITERSTACK_NLU;}
<DYNARE_STATEMENT>iterstack_relu {return token::ITERSTACK_RELU;}
<DYNARE_STATEMENT>check_jacobian_singularity {return token::CHECK_JACOBIAN_SINGULARITY;}
<DYNARE_STATEMENT>\$[^$]*\$ {
yylval->emplace<string>(yytext + 1).pop_back();
return token::TEX_NAME; return token::TEX_NAME;
} }
/* Inside a Dynare block */ /* Inside a Dynare block */
<DYNARE_BLOCK>var {return token::VAR;} <DYNARE_BLOCK>var {return token::VAR;}
<DYNARE_BLOCK>varexo {return token::VAREXO;}
<DYNARE_BLOCK>stderr {return token::STDERR;} <DYNARE_BLOCK>stderr {return token::STDERR;}
<DYNARE_BLOCK>values {return token::VALUES;} <DYNARE_BLOCK>values {return token::VALUES;}
<DYNARE_BLOCK>corr {return token::CORR;} <DYNARE_BLOCK>corr {return token::CORR;}
<DYNARE_BLOCK>periods {return token::PERIODS;} <DYNARE_BLOCK>periods {return token::PERIODS;}
<DYNARE_BLOCK>cutoff {return token::CUTOFF;} <DYNARE_BLOCK>scales {return token::SCALES;}
<DYNARE_BLOCK>mfs {return token::MFS;} <DYNARE_BLOCK>add {
yylval->emplace<string>(yytext);
return token::ADD;
}
<DYNARE_BLOCK>multiply {
yylval->emplace<string>(yytext);
return token::MULTIPLY;
}
<DYNARE_STATEMENT,DYNARE_BLOCK>cutoff {return token::CUTOFF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>mfs {
yylval->emplace<string>(yytext);
return token::MFS;
}
<DYNARE_STATEMENT,DYNARE_BLOCK>static_mfs {return token::STATIC_MFS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>balanced_growth_test_tol {return token::BALANCED_GROWTH_TEST_TOL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>heterogeneity {return token::HETEROGENEITY;}
<DYNARE_BLOCK>gamma_pdf {return token::GAMMA_PDF;} <DYNARE_BLOCK>gamma_pdf {return token::GAMMA_PDF;}
<DYNARE_BLOCK>beta_pdf {return token::BETA_PDF;} <DYNARE_BLOCK>beta_pdf {return token::BETA_PDF;}
<DYNARE_BLOCK>normal_pdf {return token::NORMAL_PDF;} <DYNARE_BLOCK>normal_pdf {return token::NORMAL_PDF;}
...@@ -704,11 +801,52 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -704,11 +801,52 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_BLOCK>uniform_pdf {return token::UNIFORM_PDF;} <DYNARE_BLOCK>uniform_pdf {return token::UNIFORM_PDF;}
<DYNARE_BLOCK>weibull_pdf {return token::WEIBULL_PDF;} <DYNARE_BLOCK>weibull_pdf {return token::WEIBULL_PDF;}
<DYNARE_BLOCK>dsge_prior_weight {return token::DSGE_PRIOR_WEIGHT;} <DYNARE_BLOCK>dsge_prior_weight {return token::DSGE_PRIOR_WEIGHT;}
<DYNARE_BLOCK>surprise {return token::SURPRISE;}
<DYNARE_BLOCK>bind {
yylval->emplace<string>(yytext);
return token::BIND;
}
<DYNARE_BLOCK>relax {
yylval->emplace<string>(yytext);
return token::RELAX;
}
<DYNARE_BLOCK>error_bind {
yylval->emplace<string>(yytext);
return token::ERROR_BIND;
}
<DYNARE_BLOCK>error_relax {
yylval->emplace<string>(yytext);
return token::ERROR_RELAX;
}
<DYNARE_BLOCK>relative_to_initval {return token::RELATIVE_TO_INITVAL;}
<DYNARE_BLOCK>; {return Dynare::parser::token_type (yytext[0]);} <DYNARE_BLOCK>; {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_BLOCK># {return Dynare::parser::token_type (yytext[0]);} <DYNARE_BLOCK># {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_BLOCK>restriction {return token::RESTRICTION;} <DYNARE_BLOCK>restriction {return token::RESTRICTION;}
<DYNARE_BLOCK>component {return token::COMPONENT;}
<DYNARE_BLOCK>target {return token::TARGET;}
<DYNARE_BLOCK,DYNARE_STATEMENT>auxname {return token::AUXNAME;}
<DYNARE_BLOCK>auxname_target_nonstationary {return token::AUXNAME_TARGET_NONSTATIONARY;}
<DYNARE_BLOCK,DYNARE_STATEMENT>kind {
yylval->emplace<string>(yytext);
return token::KIND;
}
<DYNARE_BLOCK,DYNARE_STATEMENT>ll {
yylval->emplace<string>(yytext);
return token::LL;
}
<DYNARE_BLOCK,DYNARE_STATEMENT>dl {
yylval->emplace<string>(yytext);
return token::DL;
}
<DYNARE_BLOCK,DYNARE_STATEMENT>dd {
yylval->emplace<string>(yytext);
return token::DD;
}
<DYNARE_BLOCK>weights {return token::WEIGHTS;}
<DYNARE_BLOCK>exogenize {return token::EXOGENIZE;}
<DYNARE_BLOCK>endogenize {return token::ENDOGENIZE;}
/* Inside Dynare statement */ /* Inside Dynare statement */
<DYNARE_STATEMENT>solve_algo {return token::SOLVE_ALGO;} <DYNARE_STATEMENT>solve_algo {return token::SOLVE_ALGO;}
...@@ -718,16 +856,16 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -718,16 +856,16 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>robust_lin_solve {return token::ROBUST_LIN_SOLVE;} <DYNARE_STATEMENT>robust_lin_solve {return token::ROBUST_LIN_SOLVE;}
<DYNARE_STATEMENT>drop {return token::DROP;} <DYNARE_STATEMENT>drop {return token::DROP;}
<DYNARE_STATEMENT>order {return token::ORDER;} <DYNARE_STATEMENT>order {return token::ORDER;}
<DYNARE_STATEMENT>sylvester {return token::SYLVESTER;}
<DYNARE_STATEMENT>lyapunov {return token::LYAPUNOV;} <DYNARE_STATEMENT>lyapunov {return token::LYAPUNOV;}
<DYNARE_STATEMENT>dr { <DYNARE_STATEMENT>dr {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::DR; return token::DR;
} }
<DYNARE_STATEMENT>sylvester_fixed_point_tol {return token::SYLVESTER_FIXED_POINT_TOL;} <DYNARE_STATEMENT>lyapunov_complex_threshold {return token::LYAPUNOV_COMPLEX_THRESHOLD;}
<DYNARE_STATEMENT>lyapunov_fixed_point_tol {return token::LYAPUNOV_FIXED_POINT_TOL;} <DYNARE_STATEMENT>lyapunov_fixed_point_tol {return token::LYAPUNOV_FIXED_POINT_TOL;}
<DYNARE_STATEMENT>lyapunov_doubling_tol {return token::LYAPUNOV_DOUBLING_TOL;} <DYNARE_STATEMENT>lyapunov_doubling_tol {return token::LYAPUNOV_DOUBLING_TOL;}
<DYNARE_STATEMENT>dr_cycle_reduction_tol {return token::DR_CYCLE_REDUCTION_TOL;} <DYNARE_STATEMENT>dr_cycle_reduction_tol {return token::DR_CYCLE_REDUCTION_TOL;}
<DYNARE_STATEMENT>dr_cycle_reduction_maxiter {return token::DR_CYCLE_REDUCTION_MAXITER;}
<DYNARE_STATEMENT>dr_logarithmic_reduction_tol {return token::DR_LOGARITHMIC_REDUCTION_TOL;} <DYNARE_STATEMENT>dr_logarithmic_reduction_tol {return token::DR_LOGARITHMIC_REDUCTION_TOL;}
<DYNARE_STATEMENT>dr_logarithmic_reduction_maxiter {return token::DR_LOGARITHMIC_REDUCTION_MAXITER;} <DYNARE_STATEMENT>dr_logarithmic_reduction_maxiter {return token::DR_LOGARITHMIC_REDUCTION_MAXITER;}
<DYNARE_STATEMENT>replic {return token::REPLIC;} <DYNARE_STATEMENT>replic {return token::REPLIC;}
...@@ -739,6 +877,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -739,6 +877,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>one_sided_hp_filter {return token::ONE_SIDED_HP_FILTER;} <DYNARE_STATEMENT>one_sided_hp_filter {return token::ONE_SIDED_HP_FILTER;}
<DYNARE_STATEMENT>bandpass_filter {return token::BANDPASS_FILTER;} <DYNARE_STATEMENT>bandpass_filter {return token::BANDPASS_FILTER;}
<DYNARE_STATEMENT>hp_ngrid {return token::HP_NGRID;} <DYNARE_STATEMENT>hp_ngrid {return token::HP_NGRID;}
<DYNARE_STATEMENT>filtered_theoretical_moments_grid {return token::FILTERED_THEORETICAL_MOMENTS_GRID;}
<DYNARE_STATEMENT>simul_seed {return token::SIMUL_SEED;} <DYNARE_STATEMENT>simul_seed {return token::SIMUL_SEED;}
<DYNARE_STATEMENT>qz_criterium {return token::QZ_CRITERIUM;} <DYNARE_STATEMENT>qz_criterium {return token::QZ_CRITERIUM;}
<DYNARE_STATEMENT>qz_zero_threshold {return token::QZ_ZERO_THRESHOLD;} <DYNARE_STATEMENT>qz_zero_threshold {return token::QZ_ZERO_THRESHOLD;}
...@@ -748,10 +887,20 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -748,10 +887,20 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>xls_range {return token::XLS_RANGE;} <DYNARE_STATEMENT>xls_range {return token::XLS_RANGE;}
<DYNARE_STATEMENT>series {return token::SERIES;} <DYNARE_STATEMENT>series {return token::SERIES;}
<DYNARE_STATEMENT>mh_recover {return token::MH_RECOVER;} <DYNARE_STATEMENT>mh_recover {return token::MH_RECOVER;}
<DYNARE_STATEMENT>mh_initialize_from_previous_mcmc {return token::MH_INITIALIZE_FROM_PREVIOUS_MCMC;}
<DYNARE_STATEMENT>mh_initialize_from_previous_mcmc_directory {return token::MH_INITIALIZE_FROM_PREVIOUS_MCMC_DIRECTORY;}
<DYNARE_STATEMENT>mh_initialize_from_previous_mcmc_record {return token::MH_INITIALIZE_FROM_PREVIOUS_MCMC_RECORD;}
<DYNARE_STATEMENT>mh_initialize_from_previous_mcmc_prior {return token::MH_INITIALIZE_FROM_PREVIOUS_MCMC_PRIOR;}
<DYNARE_STATEMENT>planner_discount {return token::PLANNER_DISCOUNT;} <DYNARE_STATEMENT>planner_discount {return token::PLANNER_DISCOUNT;}
<DYNARE_STATEMENT>planner_discount_latex_name {return token::PLANNER_DISCOUNT_LATEX_NAME;}
<DYNARE_STATEMENT>calibration {return token::CALIBRATION;} <DYNARE_STATEMENT>calibration {return token::CALIBRATION;}
<DYNARE_STATEMENT>irf_plot_threshold {return token::IRF_PLOT_THRESHOLD;} <DYNARE_STATEMENT>irf_plot_threshold {return token::IRF_PLOT_THRESHOLD;}
<DYNARE_STATEMENT>no_homotopy {return token::NO_HOMOTOPY;} <DYNARE_STATEMENT>no_homotopy {return token::NO_HOMOTOPY;}
<DYNARE_STATEMENT>particle_filter_options {return token::PARTICLE_FILTER_OPTIONS;}
<DYNARE_STATEMENT>constant_simulation_length {return token::CONSTANT_SIMULATION_LENGTH;}
<DYNARE_STATEMENT>block_static { return token::BLOCK_STATIC; }
<DYNARE_STATEMENT>block_dynamic { return token::BLOCK_DYNAMIC; }
<DYNARE_STATEMENT>incidence { return token::INCIDENCE; }
<DYNARE_BLOCK>stderr_multiples {return token::STDERR_MULTIPLES;} <DYNARE_BLOCK>stderr_multiples {return token::STDERR_MULTIPLES;}
<DYNARE_BLOCK>diagonal_only {return token::DIAGONAL_ONLY;} <DYNARE_BLOCK>diagonal_only {return token::DIAGONAL_ONLY;}
...@@ -760,6 +909,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -760,6 +909,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_BLOCK>lag {return token::LAG;} <DYNARE_BLOCK>lag {return token::LAG;}
<DYNARE_BLOCK>coeff {return token::COEFF;} <DYNARE_BLOCK>coeff {return token::COEFF;}
<DYNARE_BLOCK>overwrite {return token::OVERWRITE;} <DYNARE_BLOCK>overwrite {return token::OVERWRITE;}
<DYNARE_BLOCK>learnt_in {return token::LEARNT_IN;}
<DYNARE_STATEMENT,DYNARE_BLOCK>upper_cholesky {return token::UPPER_CHOLESKY;} <DYNARE_STATEMENT,DYNARE_BLOCK>upper_cholesky {return token::UPPER_CHOLESKY;}
<DYNARE_STATEMENT,DYNARE_BLOCK>lower_cholesky {return token::LOWER_CHOLESKY;} <DYNARE_STATEMENT,DYNARE_BLOCK>lower_cholesky {return token::LOWER_CHOLESKY;}
<DYNARE_STATEMENT>chain {return token::CHAIN;} <DYNARE_STATEMENT>chain {return token::CHAIN;}
...@@ -769,43 +919,50 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -769,43 +919,50 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>coefficients {return token::COEFFICIENTS;} <DYNARE_STATEMENT>coefficients {return token::COEFFICIENTS;}
<DYNARE_STATEMENT>variances {return token::VARIANCES;} <DYNARE_STATEMENT>variances {return token::VARIANCES;}
<DYNARE_STATEMENT>equations {return token::EQUATIONS;} <DYNARE_STATEMENT>equations {return token::EQUATIONS;}
<DYNARE_STATEMENT>time_shift {return token::TIME_SHIFT;}
<DYNARE_STATEMENT>structural {return token::STRUCTURAL;}
<DYNARE_STATEMENT>true {
yylval->emplace<string>(yytext);
return token::TRUE;
}
<DYNARE_STATEMENT>false {
yylval->emplace<string>(yytext);
return token::FALSE;
}
<DYNARE_STATEMENT>[\.] {return Dynare::parser::token_type (yytext[0]);} <DYNARE_STATEMENT,DYNARE_BLOCK>\. {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT>[\\] {return Dynare::parser::token_type (yytext[0]);} <DYNARE_STATEMENT>\\ {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT>[\'] {return Dynare::parser::token_type (yytext[0]);} <DYNARE_STATEMENT>\' {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_BLOCK>use_dll {return token::USE_DLL;} <DYNARE_STATEMENT,DYNARE_BLOCK>use_dll {return token::USE_DLL;}
<DYNARE_BLOCK>block {return token::BLOCK;} <DYNARE_STATEMENT,DYNARE_BLOCK>block {return token::BLOCK;}
<DYNARE_BLOCK>bytecode {return token::BYTECODE;} <DYNARE_STATEMENT,DYNARE_BLOCK>bytecode {return token::BYTECODE;}
<DYNARE_BLOCK>linear_decomposition {return token::LINEAR_DECOMPOSITION;}
<DYNARE_BLOCK>all_values_required {return token::ALL_VALUES_REQUIRED;} <DYNARE_BLOCK>all_values_required {return token::ALL_VALUES_REQUIRED;}
<DYNARE_BLOCK>no_static {return token::NO_STATIC;} <DYNARE_STATEMENT,DYNARE_BLOCK>no_static {return token::NO_STATIC;}
<DYNARE_BLOCK>differentiate_forward_vars {return token::DIFFERENTIATE_FORWARD_VARS;} <DYNARE_STATEMENT,DYNARE_BLOCK>differentiate_forward_vars {return token::DIFFERENTIATE_FORWARD_VARS;}
<DYNARE_BLOCK>parallel_local_files {return token::PARALLEL_LOCAL_FILES;} <DYNARE_STATEMENT,DYNARE_BLOCK>parallel_local_files {return token::PARALLEL_LOCAL_FILES;}
<DYNARE_STATEMENT,DYNARE_BLOCK>linear {return token::LINEAR;} <DYNARE_STATEMENT,DYNARE_BLOCK>linear {return token::LINEAR;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[,] {return token::COMMA;} <DYNARE_STATEMENT,DYNARE_BLOCK>, {return token::COMMA;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[:] {return Dynare::parser::token_type (yytext[0]);} <DYNARE_STATEMENT,DYNARE_BLOCK>: {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT,DYNARE_BLOCK>[\(\)] {return Dynare::parser::token_type (yytext[0]);} <DYNARE_STATEMENT,DYNARE_BLOCK>[\(\)] {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT,DYNARE_BLOCK>[\[] {return Dynare::parser::token_type (yytext[0]);} <DYNARE_STATEMENT,DYNARE_BLOCK>\[ {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT,DYNARE_BLOCK>[\]] { <DYNARE_STATEMENT,DYNARE_BLOCK>\] {return Dynare::parser::token_type (yytext[0]);}
if (sigma_e) <DYNARE_STATEMENT,DYNARE_BLOCK>\+ {return token::PLUS;}
sigma_e = 0; <DYNARE_STATEMENT,DYNARE_BLOCK>- {return token::MINUS;}
return Dynare::parser::token_type (yytext[0]); <DYNARE_STATEMENT,DYNARE_BLOCK>\* {return token::TIMES;}
} <DYNARE_STATEMENT,DYNARE_BLOCK>\/ {return token::DIVIDE;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[+] {return token::PLUS;} <DYNARE_STATEMENT,DYNARE_BLOCK>= {return token::EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[-] {return token::MINUS;} <DYNARE_STATEMENT,DYNARE_BLOCK>< {return token::LESS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[*] {return token::TIMES;} <DYNARE_STATEMENT,DYNARE_BLOCK>> {return token::GREATER;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[/] {return token::DIVIDE;} <DYNARE_STATEMENT,DYNARE_BLOCK>>= {return token::GREATER_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[=] {return token::EQUAL;} <DYNARE_STATEMENT,DYNARE_BLOCK><= {return token::LESS_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[<] {return token::LESS;} <DYNARE_STATEMENT,DYNARE_BLOCK>== {return token::EQUAL_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[>] {return token::GREATER;} <DYNARE_STATEMENT,DYNARE_BLOCK>!= {return token::EXCLAMATION_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>">=" {return token::GREATER_EQUAL;} <DYNARE_BLOCK>\+= {return token::PLUS_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>"<=" {return token::LESS_EQUAL;} <DYNARE_BLOCK>\*= {return token::TIMES_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>"==" {return token::EQUAL_EQUAL;} <DYNARE_STATEMENT,DYNARE_BLOCK>\^ {return token::POWER;}
<DYNARE_STATEMENT,DYNARE_BLOCK>"!=" {return token::EXCLAMATION_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[\^] {return token::POWER;}
<DYNARE_STATEMENT,DYNARE_BLOCK>exp {return token::EXP;} <DYNARE_STATEMENT,DYNARE_BLOCK>exp {return token::EXP;}
<DYNARE_STATEMENT,DYNARE_BLOCK>log {return token::LOG;} <DYNARE_STATEMENT,DYNARE_BLOCK>log {return token::LOG;}
<DYNARE_STATEMENT,DYNARE_BLOCK>log10 {return token::LOG10;} <DYNARE_STATEMENT,DYNARE_BLOCK>log10 {return token::LOG10;}
...@@ -816,7 +973,14 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -816,7 +973,14 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT,DYNARE_BLOCK>asin {return token::ASIN;} <DYNARE_STATEMENT,DYNARE_BLOCK>asin {return token::ASIN;}
<DYNARE_STATEMENT,DYNARE_BLOCK>acos {return token::ACOS;} <DYNARE_STATEMENT,DYNARE_BLOCK>acos {return token::ACOS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>atan {return token::ATAN;} <DYNARE_STATEMENT,DYNARE_BLOCK>atan {return token::ATAN;}
<DYNARE_STATEMENT,DYNARE_BLOCK>sinh {return token::SINH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>cosh {return token::COSH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>tanh {return token::TANH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>asinh {return token::ASINH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>acosh {return token::ACOSH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>atanh {return token::ATANH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>sqrt {return token::SQRT;} <DYNARE_STATEMENT,DYNARE_BLOCK>sqrt {return token::SQRT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>cbrt {return token::CBRT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>max {return token::MAX;} <DYNARE_STATEMENT,DYNARE_BLOCK>max {return token::MAX;}
<DYNARE_STATEMENT,DYNARE_BLOCK>min {return token::MIN;} <DYNARE_STATEMENT,DYNARE_BLOCK>min {return token::MIN;}
<DYNARE_STATEMENT,DYNARE_BLOCK>abs {return token::ABS;} <DYNARE_STATEMENT,DYNARE_BLOCK>abs {return token::ABS;}
...@@ -824,16 +988,21 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -824,16 +988,21 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT,DYNARE_BLOCK>normcdf {return token::NORMCDF;} <DYNARE_STATEMENT,DYNARE_BLOCK>normcdf {return token::NORMCDF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>normpdf {return token::NORMPDF;} <DYNARE_STATEMENT,DYNARE_BLOCK>normpdf {return token::NORMPDF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>erf {return token::ERF;} <DYNARE_STATEMENT,DYNARE_BLOCK>erf {return token::ERF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>erfc {return token::ERFC;}
<DYNARE_STATEMENT,DYNARE_BLOCK>steady_state {return token::STEADY_STATE;} <DYNARE_STATEMENT,DYNARE_BLOCK>steady_state {return token::STEADY_STATE;}
<DYNARE_STATEMENT,DYNARE_BLOCK>expectation {return token::EXPECTATION;} <DYNARE_STATEMENT,DYNARE_BLOCK>expectation {return token::EXPECTATION;}
<DYNARE_BLOCK>var_expectation {return token::VAR_EXPECTATION;} <DYNARE_BLOCK>var_expectation {return token::VAR_EXPECTATION;}
<DYNARE_BLOCK>pac_expectation {return token::PAC_EXPECTATION;} <DYNARE_BLOCK>pac_expectation {return token::PAC_EXPECTATION;}
<DYNARE_BLOCK>pac_target_nonstationary {return token::PAC_TARGET_NONSTATIONARY;}
<DYNARE_BLOCK>sum {return token::SUM;}
<DYNARE_STATEMENT>discount {return token::DISCOUNT;} <DYNARE_STATEMENT>discount {return token::DISCOUNT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>varobs {return token::VAROBS;} <DYNARE_STATEMENT,DYNARE_BLOCK>varobs {return token::VAROBS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>varexobs {return token::VAREXOBS;} <DYNARE_STATEMENT,DYNARE_BLOCK>varexobs {return token::VAREXOBS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>nan {return token::NAN_CONSTANT;} <DYNARE_STATEMENT,DYNARE_BLOCK>nan {return token::NAN_CONSTANT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>inf {return token::INF_CONSTANT;} <DYNARE_STATEMENT,DYNARE_BLOCK>inf {return token::INF_CONSTANT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>constants {return token::CONSTANTS;} <DYNARE_STATEMENT,DYNARE_BLOCK>constants {return token::CONSTANTS;}
<DYNARE_BLOCK>⟂ {return token::PERPENDICULAR;}
<DYNARE_BLOCK>_\|_ {return token::PERPENDICULAR;}
/* options for GSA module by Marco Ratto */ /* options for GSA module by Marco Ratto */
<DYNARE_STATEMENT>identification {return token::IDENTIFICATION;} <DYNARE_STATEMENT>identification {return token::IDENTIFICATION;}
...@@ -881,38 +1050,27 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -881,38 +1050,27 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<DYNARE_STATEMENT>use_shock_groups {return token::USE_SHOCK_GROUPS;} <DYNARE_STATEMENT>use_shock_groups {return token::USE_SHOCK_GROUPS;}
<DYNARE_STATEMENT>colormap {return token::COLORMAP;} <DYNARE_STATEMENT>colormap {return token::COLORMAP;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[A-Za-z_][A-Za-z0-9_]* { <DYNARE_STATEMENT,DYNARE_BLOCK>{NAME} {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NAME; return token::NAME;
} }
<DYNARE_STATEMENT,DYNARE_BLOCK>((([0-9]*\.[0-9]+)|([0-9]+\.))([edED][-+]?[0-9]+)?)|([0-9]+[edED][-+]?[0-9]+) { <DYNARE_STATEMENT,DYNARE_BLOCK>{FLOAT_NUMBER} {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::FLOAT_NUMBER; return token::FLOAT_NUMBER;
} }
<DYNARE_STATEMENT,DYNARE_BLOCK>[0-9]+ { <DYNARE_STATEMENT,DYNARE_BLOCK>[0-9]+ {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::INT_NUMBER; return token::INT_NUMBER;
} }
<DATES_STATEMENT>\( { yylval->as<string>().append(yytext); dates_parens_nb++; } <DYNARE_BLOCK>\|e { return token::PIPE_E; }
<DATES_STATEMENT>\) { <DYNARE_BLOCK>\|x { return token::PIPE_X; }
yylval->as<string>().append(yytext); <DYNARE_BLOCK>\|p { return token::PIPE_P; }
if (--dates_parens_nb == 0)
{
BEGIN DYNARE_STATEMENT;
return token::DATES;
}
}
<DATES_STATEMENT>. { yylval->as<string>().append(yytext); }
<DYNARE_BLOCK>\|[eE] { return token::PIPE_E; }
<DYNARE_BLOCK>\|[xX] { return token::PIPE_X; }
<DYNARE_BLOCK>\|[pP] { return token::PIPE_P; }
<DYNARE_STATEMENT,DYNARE_BLOCK>\'[^\']+\' { <DYNARE_STATEMENT,DYNARE_BLOCK>\'[^\']*\' {
yylval->build<string>(yytext + 1).pop_back(); yylval->emplace<string>(yytext + 1).pop_back();
return token::QUOTED_STRING; return token::QUOTED_STRING;
} }
...@@ -944,11 +1102,11 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -944,11 +1102,11 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
element in initval (in which case Dynare recognizes the matrix name as an external element in initval (in which case Dynare recognizes the matrix name as an external
function symbol), and may want to modify the matrix later with Matlab statements. function symbol), and may want to modify the matrix later with Matlab statements.
*/ */
<INITIAL>[A-Za-z_][A-Za-z0-9_]* { <INITIAL>{NAME} {
if (driver.symbol_exists_and_is_not_modfile_local_or_external_function(yytext)) if (driver.symbol_exists_and_is_not_modfile_local_or_external_function(yytext))
{ {
BEGIN DYNARE_STATEMENT; BEGIN DYNARE_STATEMENT;
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NAME; return token::NAME;
} }
else else
...@@ -959,11 +1117,18 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -959,11 +1117,18 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
} }
} }
/* For joint prior statement, match [symbol, symbol, ...] /*
For joint prior statement, match [symbol, symbol, ...]
If no match, begin native and push everything back on stack If no match, begin native and push everything back on stack
We produce SYMBOL_VEC in Flex (instead of matching `'[' symbol_list ']'`
in Bison because the pattern also matches potential native statements
(e.g. function returns from a MATLAB/Octave function). Hence, we need to
be able to back out of the statement if we realize it's a native statement
and move to the NATIVE context
*/ */
<INITIAL>\[([[:space:]]*[A-Za-z_][A-Za-z0-9_]*[[:space:]]*,{1}[[:space:]]*)*([[:space:]]*[A-Za-z_][A-Za-z0-9_]*[[:space:]]*){1}\] { <INITIAL>\[([[:space:]]*{NAME}[[:space:]]*,{1}[[:space:]]*)*([[:space:]]*{NAME}[[:space:]]*){1}\] {
string yytextcpy = string(yytext); string yytextcpy{yytext};
yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), '['), yytextcpy.end()); yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), '['), yytextcpy.end());
yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), ']'), yytextcpy.end()); yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), ']'), yytextcpy.end());
yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), ' '), yytextcpy.end()); yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), ' '), yytextcpy.end());
...@@ -986,7 +1151,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -986,7 +1151,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
if (dynare_statement) if (dynare_statement)
{ {
BEGIN DYNARE_STATEMENT; BEGIN DYNARE_STATEMENT;
yylval->build<vector<string>>(val); yylval->emplace<vector<string>>(val);
return token::SYMBOL_VEC; return token::SYMBOL_VEC;
} }
} }
...@@ -1001,8 +1166,8 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -1001,8 +1166,8 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
\'[^\'\n]*\' | \'[^\'\n]*\' |
\"[^\"\n]*\" | \"[^\"\n]*\" |
\.{1,2} | \.{1,2} |
"*" | \* |
"/" { yymore(); eofbuff = string(yytext); } \/ { yymore(); eofbuff = yytext; }
\.{3,}[[:space:]]*\n { driver.add_native_remove_charset(yytext, "\n"); } \.{3,}[[:space:]]*\n { driver.add_native_remove_charset(yytext, "\n"); }
\n { \n {
if (strlen(yytext) > 1) if (strlen(yytext) > 1)
...@@ -1013,8 +1178,8 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -1013,8 +1178,8 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
driver.add_native(eofbuff); driver.add_native(eofbuff);
yyterminate(); yyterminate();
} }
\.{3,}[[:space:]]*"%".*\n | \.{3,}[[:space:]]*%.*\n |
"%"[^\n]* { driver.add_native_remove_charset(yytext, "%"); } %[^\n]* { driver.add_native_remove_charset(yytext, "%"); }
\.{3,}[[:space:]]*"//".*\n | \.{3,}[[:space:]]*"//".*\n |
"//"[^\n]* { driver.add_native_remove_charset(yytext, "//"); } "//"[^\n]* { driver.add_native_remove_charset(yytext, "//"); }
\.{3,}[[:space:]]*"/*" { \.{3,}[[:space:]]*"/*" {
...@@ -1031,11 +1196,13 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 ...@@ -1031,11 +1196,13 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
<NATIVE_COMMENT>"*/"[[:space:]]*\n { BEGIN NATIVE; } <NATIVE_COMMENT>"*/"[[:space:]]*\n { BEGIN NATIVE; }
<NATIVE_COMMENT>. <NATIVE_COMMENT>.
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,DATES_STATEMENT,LINE1,LINE2,LINE3,NATIVE_COMMENT><<EOF>> { yyterminate(); } <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,LINE1,LINE2,LINE3,NATIVE_COMMENT><<EOF>> { yyterminate(); }
<*>. { driver.error(*yylloc, "character unrecognized by lexer"); } <*>. { driver.error(*yylloc, "character unrecognized by lexer"); }
%% %%
#pragma GCC diagnostic pop
DynareFlex::DynareFlex(istream* in, ostream* out) DynareFlex::DynareFlex(istream* in, ostream* out)
: DynareFlexLexer{in, out} : DynareFlexLexer{in, out}
{ {
......
/* /*
* Copyright (C) 2003-2018 Dynare Team * Copyright © 2003-2023 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -14,59 +14,89 @@ ...@@ -14,59 +14,89 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iostream> #include <iostream>
#include <regex>
#include <sstream> #include <sstream>
#include <fstream> #include <string>
#include <thread>
#include <vector>
#include <cstdlib> #include <cstdlib>
#include <cstring>
#ifndef PACKAGE_VERSION
# define PACKAGE_VERSION 4.
#endif
#include <unistd.h> #include <unistd.h>
#include "ParsingDriver.hh"
#include "Configuration.hh"
#include "ExtendedPreprocessorTypes.hh" #include "ExtendedPreprocessorTypes.hh"
#include "ConfigFile.hh" #include "ModFile.hh"
#include "ParsingDriver.hh"
/* Prototype for second part of main function /* Prototype for the function that handles the macro-expansion of the .mod file
Splitting main() in two parts was necessary because ParsingDriver.h and MacroDriver.h can't be Splitting this out was necessary because ParsingDriver.hh and macro/Driver.hh can't be
included simultaneously (because of Bison limitations). included simultaneously (because of Bison limitations).
Function can be found in: MacroExpandModFile.cc
*/ */
void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear_global, stringstream macroExpandModFile(const filesystem::path& filename, const istream& modfile,
bool no_tmp_terms, bool no_log, bool no_warn, bool warn_uninit, bool console, bool debug, bool save_macro, filesystem::path save_macro_file,
bool nograph, bool nointeractive, bool parallel, ConfigFile &config_file, bool line_macro, const vector<pair<string, string>>& defines,
WarningConsolidation &warnings_arg, bool nostrict, bool stochastic, bool check_model_changes, vector<filesystem::path> paths);
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
LanguageOutputType lang, int params_derivs_order, bool transform_unary_ops
#if defined(_WIN32) || defined(__CYGWIN32__)
, bool cygwin, bool msvc, bool mingw
#endif
, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple
, bool nopreprocessoroutput
);
void main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file,
bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream &macro_output);
void void
usage() usage()
{ {
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]" cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] "
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]" "[savemacro[=macro_file]] [onlymacro] [linemacro] [notmpterms] [nolog] [warn_uninit]"
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=julia]" << " [console] [nograph] [nointeractive] [parallel[=cluster_name]] "
"[conffile=path_to_config_file] [parallel_follower_open_mode] "
"[parallel_test] [parallel_use_psexec=true|false]"
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] "
"[compute_xrefs] [output=first|second|third] [language=matlab|julia]"
<< " [params_derivs_order=0|1|2] [transform_unary_ops] " << " [params_derivs_order=0|1|2] [transform_unary_ops] "
#if defined(_WIN32) || defined(__CYGWIN32__) "[exclude_eqs=<equation_tag_list_or_file>] [include_eqs=<equation_tag_list_or_file>]"
<< " [cygwin] [msvc] [mingw]" << " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] "
#endif "[nopathchange] [nopreprocessoroutput]"
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]" << " [mexext=<extension>] [matlabroot=<path>] [onlymodel] [notime] [use_dll] "
"[nocommutativity]"
<< endl; << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* Looks for an options list in the first non-empty line of the .mod file (but rewind
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)
{
vector<string> options;
string first_nonempty_line;
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)
{
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;
}
modfile.seekg(0);
return options;
}
int int
main(int argc, char** argv) main(int argc, char** argv)
{ {
...@@ -83,248 +113,270 @@ main(int argc, char **argv) ...@@ -83,248 +113,270 @@ main(int argc, char **argv)
usage(); usage();
} }
const filesystem::path filename {argv[1]};
ifstream modfile(filename, ios::binary);
if (modfile.fail())
{
cerr << "ERROR: Could not open file: " << filename.string() << endl;
exit(EXIT_FAILURE);
}
// Create options list, using first line of mod-file and command line
vector<string> options = parse_options_line(modfile);
for (int arg = 2; arg < argc; arg++)
options.emplace_back(argv[arg]);
// Parse options
bool notime = false;
bool clear_all = true; bool clear_all = true;
bool clear_global = false; bool clear_global = false;
bool save_macro = false; bool save_macro = false;
string save_macro_file; filesystem::path save_macro_file;
bool debug = false; bool debug = false;
bool no_tmp_terms = false; bool no_tmp_terms = false;
bool only_macro = false; bool only_macro = false;
bool no_line_macro = false; bool line_macro = false;
bool no_empty_line_macro = false;
bool no_log = false;
bool no_warn = false; bool no_warn = false;
int params_derivs_order = 2; int params_derivs_order = 2;
bool warn_uninit = false; bool warn_uninit = false;
bool console = false; bool console = false;
bool nograph = false; bool nograph = false;
bool nointeractive = false; bool nointeractive = false;
#if defined(_WIN32) || defined(__CYGWIN32__) filesystem::path conffile;
bool cygwin = false;
bool msvc = false;
bool mingw = false;
#endif
string parallel_config_file;
bool parallel = false; bool parallel = false;
string cluster_name; string cluster_name;
bool parallel_slave_open_mode = false; bool parallel_follower_open_mode
= false; // Must be the same default as in matlab/default_option_values.m
bool parallel_test = false; bool parallel_test = false;
bool parallel_use_psexec = true; // Must be the same default as in matlab/default_option_values.m
bool nostrict = false; bool nostrict = false;
bool stochastic = false; bool stochastic = false;
bool check_model_changes = false; bool check_model_changes = false;
bool minimal_workspace = false; bool minimal_workspace = false;
bool compute_xrefs = false; bool compute_xrefs = false;
bool transform_unary_ops = false; bool transform_unary_ops = false;
map<string, string> defines; bool gui = false;
vector<string> path; string exclude_eqs, include_eqs;
FileOutputType output_mode{FileOutputType::none}; vector<pair<string, string>> defines;
vector<filesystem::path> paths;
OutputType output_mode {OutputType::standard};
JsonOutputPointType json {JsonOutputPointType::nojson}; JsonOutputPointType json {JsonOutputPointType::nojson};
JsonFileOutputType json_output_mode {JsonFileOutputType::file}; JsonFileOutputType json_output_mode {JsonFileOutputType::file};
bool onlyjson = false; bool onlyjson = false;
bool jsonderivsimple = false; bool jsonderivsimple = false;
LanguageOutputType language {LanguageOutputType::matlab}; LanguageOutputType language {LanguageOutputType::matlab};
bool nopreprocessoroutput = false; string mexext;
filesystem::path matlabroot;
bool onlymodel = false;
bool use_dll = false;
// Parse options for (auto s : options)
for (int arg = 2; arg < argc; arg++)
{ {
if (!strcmp(argv[arg], "debug")) if (s == "debug")
debug = true; debug = true;
else if (!strcmp(argv[arg], "noclearall")) else if (s == "notime")
notime = true;
else if (s == "noclearall")
clear_all = false; clear_all = false;
else if (strlen(argv[arg]) >= 19 && !strncmp(argv[arg], "params_derivs_order", 19)) else if (s.substr(0, 19) == "params_derivs_order")
{ {
if (strlen(argv[arg]) >= 22 || argv[arg][19] != '=' if (s.length() > 21 || s.at(19) != '='
|| !(argv[arg][20] == '0' || argv[arg][20] == '1' || argv[arg][20] == '2')) || !(s.at(20) == '0' || s.at(20) == '1' || s.at(20) == '2'))
{ {
cerr << "Incorrect syntax for params_derivs_order option" << endl; cerr << "Incorrect syntax for params_derivs_order option" << endl;
usage(); usage();
} }
params_derivs_order = atoi(argv[arg] + 20); params_derivs_order = stoi(s.substr(20));
} }
else if (!strcmp(argv[arg], "onlyclearglobals")) else if (s == "onlyclearglobals")
{ {
clear_all = false; clear_all = false;
clear_global = true; clear_global = true;
} }
else if (!strcmp(argv[arg], "onlymacro")) else if (s == "onlymacro")
only_macro = true; only_macro = true;
else if (strlen(argv[arg]) >= 9 && !strncmp(argv[arg], "savemacro", 9)) else if (s.substr(0, 9) == "savemacro")
{ {
save_macro = true; save_macro = true;
if (strlen(argv[arg]) > 9) if (s.length() > 9)
{ {
if (strlen(argv[arg]) == 10 || argv[arg][9] != '=') if (s.length() == 10 || s.at(9) != '=')
{ {
cerr << "Incorrect syntax for savemacro option" << endl; cerr << "Incorrect syntax for savemacro option" << endl;
usage(); usage();
} }
save_macro_file = string(argv[arg] + 10); save_macro_file = s.substr(10);
} }
} }
else if (!strcmp(argv[arg], "nolinemacro")) else if (s == "linemacro")
no_line_macro = true; line_macro = true;
else if (!strcmp(argv[arg], "noemptylinemacro")) else if (s == "notmpterms")
no_empty_line_macro = true;
else if (!strcmp(argv[arg], "notmpterms"))
no_tmp_terms = true; no_tmp_terms = true;
else if (!strcmp(argv[arg], "nolog")) else if (s == "nolog")
no_log = true; {
else if (!strcmp(argv[arg], "nowarn")) // Do nothing, the option is implemented at the dynare.m level.
// We nevertheless accept it, to avoid an “unknown option” error.
}
else if (s == "nowarn")
no_warn = true; no_warn = true;
else if (!strcmp(argv[arg], "warn_uninit")) else if (s == "warn_uninit")
warn_uninit = true; warn_uninit = true;
else if (!strcmp(argv[arg], "console")) else if (s == "console")
console = true; console = true;
else if (!strcmp(argv[arg], "nograph")) else if (s == "nograph")
nograph = true; nograph = true;
else if (!strcmp(argv[arg], "nointeractive")) else if (s == "nointeractive")
nointeractive = true; nointeractive = true;
#if defined(_WIN32) || defined(__CYGWIN32__) else if (s.substr(0, 8) == "conffile")
else if (!strcmp(argv[arg], "cygwin")) {
cygwin = true; if (s.length() <= 9 || s.at(8) != '=')
else if (!strcmp(argv[arg], "msvc"))
msvc = true;
else if (!strcmp(argv[arg], "mingw"))
mingw = true;
#endif
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "conffile", 8))
{
if (strlen(argv[arg]) <= 9 || argv[arg][8] != '=')
{ {
cerr << "Incorrect syntax for conffile option" << endl; cerr << "Incorrect syntax for conffile option" << endl;
usage(); usage();
} }
parallel_config_file = string(argv[arg] + 9); conffile = s.substr(9);
} }
else if (!strcmp(argv[arg], "parallel_slave_open_mode")) else if (s == "parallel_follower_open_mode"
parallel_slave_open_mode = true; || s == "parallel_slave_open_mode") // Kept for backward compatibility, see #86
else if (!strcmp(argv[arg], "parallel_test")) parallel_follower_open_mode = true;
else if (s == "parallel_test")
parallel_test = true; parallel_test = true;
else if (!strcmp(argv[arg], "nostrict")) else if (s.substr(0, 19) == "parallel_use_psexec")
{
if (s.length() <= 20 || s.at(19) != '=')
{
cerr << "Incorrect syntax for parallel_use_psexec option" << endl;
usage();
}
s.erase(0, 20);
if (s == "true")
parallel_use_psexec = true;
else if (s == "false")
parallel_use_psexec = false;
else
{
cerr << "Incorrect syntax for parallel_use_psexec option" << endl;
usage();
}
}
else if (s == "nostrict")
nostrict = true; nostrict = true;
else if (!strcmp(argv[arg], "stochastic")) else if (s == "stochastic")
stochastic = true; stochastic = true;
else if (!strcmp(argv[arg], "fast")) else if (s == "fast")
check_model_changes = true; check_model_changes = true;
else if (!strcmp(argv[arg], "minimal_workspace")) else if (s == "minimal_workspace")
minimal_workspace = true; minimal_workspace = true;
else if (!strcmp(argv[arg], "compute_xrefs")) else if (s == "compute_xrefs")
compute_xrefs = true; compute_xrefs = true;
else if (!strcmp(argv[arg], "transform_unary_ops")) else if (s == "transform_unary_ops")
transform_unary_ops = true; transform_unary_ops = true;
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "parallel", 8)) else if (s.substr(0, 8) == "parallel")
{ {
parallel = true; parallel = true;
if (strlen(argv[arg]) > 8) if (s.length() > 8)
{ {
if (strlen(argv[arg]) == 9 || argv[arg][8] != '=') if (s.length() == 9 || s.at(8) != '=')
{ {
cerr << "Incorrect syntax for parallel option" << endl; cerr << "Incorrect syntax for parallel option" << endl;
usage(); usage();
} }
cluster_name = string(argv[arg] + 9); cluster_name = s.substr(9);
} }
} }
else if (strlen(argv[arg]) >= 2 && !strncmp(argv[arg], "-D", 2)) else if (s.substr(0, 2) == "-D")
{ {
if (strlen(argv[arg]) == 2) if (s.length() == 2)
{ {
cerr << "Incorrect syntax for command line define: the defined variable " cerr << "Incorrect syntax for command line define: the defined variable "
<< "must not be separated from -D by whitespace." << endl; << "must not be separated from -D by whitespace." << endl;
usage(); usage();
} }
size_t equal_index = string(argv[arg]).find('='); if (auto equal_index = s.find('='); equal_index != string::npos)
if (equal_index != string::npos) defines.emplace_back(s.substr(2, equal_index - 2), s.substr(equal_index + 1));
{
string key = string(argv[arg]).erase(equal_index).erase(0, 2);
defines[key] = string(argv[arg]).erase(0, equal_index+1);
}
else else
{ defines.emplace_back(s.substr(2), "true");
string key = string(argv[arg]).erase(0, 2);
defines[key] = "1";
}
} }
else if (strlen(argv[arg]) >= 2 && !strncmp(argv[arg], "-I", 2)) else if (s.substr(0, 2) == "-I")
{ {
if (strlen(argv[arg]) == 2) if (s.length() == 2)
{ {
cerr << "Incorrect syntax for command line define: the defined variable " cerr << "Incorrect syntax for command line define: the defined variable "
<< "must not be separated from -I by whitespace." << endl; << "must not be separated from -I by whitespace." << endl;
usage(); usage();
} }
path.push_back(string(argv[arg]).erase(0, 2)); paths.emplace_back(s.substr(2));
} }
else if (strlen(argv[arg]) >= 6 && !strncmp(argv[arg], "output", 6)) else if (s.substr(0, 6) == "output")
{ {
if (strlen(argv[arg]) <= 7 || argv[arg][6] != '=') if (s.length() <= 7 || s.at(6) != '=')
{ {
cerr << "Incorrect syntax for output option" << endl; cerr << "Incorrect syntax for output option" << endl;
usage(); usage();
} }
if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 7, "dynamic", 7))
output_mode = FileOutputType::dynamic; s.erase(0, 7);
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "first", 5))
output_mode = FileOutputType::first; if (s == "first")
else if (strlen(argv[arg]) == 13 && !strncmp(argv[arg] + 7, "second", 6)) output_mode = OutputType::first;
output_mode = FileOutputType::second; else if (s == "second")
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "third", 5)) output_mode = OutputType::second;
output_mode = FileOutputType::third; else if (s == "third")
output_mode = OutputType::third;
else else
{ {
cerr << "Incorrect syntax for output option" << endl; cerr << "Incorrect syntax for output option" << endl;
usage(); usage();
} }
} }
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "language", 8)) else if (s.substr(0, 8) == "language")
{ {
if (strlen(argv[arg]) <= 9 || argv[arg][8] != '=') if (s.length() <= 9 || s.at(8) != '=')
{ {
cerr << "Incorrect syntax for language option" << endl; cerr << "Incorrect syntax for language option" << endl;
usage(); usage();
} }
if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 9, "julia", 5)) s.erase(0, 9);
if (s == "matlab")
language = LanguageOutputType::matlab;
else if (s == "julia")
language = LanguageOutputType::julia; language = LanguageOutputType::julia;
else
{
// we don't want temp terms in external functions (except Julia)
no_tmp_terms = true;
if (strlen(argv[arg]) == 13 && !strncmp(argv[arg] + 9, "cuda", 4))
language = LanguageOutputType::cuda;
else if (strlen(argv[arg]) == 15 && !strncmp(argv[arg] + 9, "python", 6))
language = LanguageOutputType::python;
else else
{ {
cerr << "Incorrect syntax for language option" << endl; cerr << "Incorrect syntax for language option" << endl;
usage(); usage();
} }
} }
} else if (s == "jsonstdout")
else if (!strcmp(argv[arg], "jsonstdout"))
json_output_mode = JsonFileOutputType::standardout; json_output_mode = JsonFileOutputType::standardout;
else if (!strcmp(argv[arg], "onlyjson")) else if (s == "onlyjson")
onlyjson = true; onlyjson = true;
else if (!strcmp(argv[arg], "nopreprocessoroutput")) else if (s == "nopreprocessoroutput")
nopreprocessoroutput = true; cout.rdbuf(nullptr);
else if (!strcmp(argv[arg], "jsonderivsimple")) else if (s == "jsonderivsimple")
jsonderivsimple = true; jsonderivsimple = true;
else if (strlen(argv[arg]) >= 4 && !strncmp(argv[arg], "json", 4)) else if (s.substr(0, 4) == "json")
{ {
if (strlen(argv[arg]) <= 5 || argv[arg][4] != '=') if (s.length() <= 5 || s.at(4) != '=')
{ {
cerr << "Incorrect syntax for json option" << endl; cerr << "Incorrect syntax for json option" << endl;
usage(); usage();
} }
if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 5, "parse", 5))
s.erase(0, 5);
if (s == "parse")
json = JsonOutputPointType::parsing; json = JsonOutputPointType::parsing;
else if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 5, "check", 5)) else if (s == "check")
json = JsonOutputPointType::checkpass; json = JsonOutputPointType::checkpass;
else if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 5, "transform", 9)) else if (s == "transform")
json = JsonOutputPointType::transformpass; json = JsonOutputPointType::transformpass;
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 5, "compute", 7)) else if (s == "compute")
json = JsonOutputPointType::computingpass; json = JsonOutputPointType::computingpass;
else else
{ {
...@@ -332,80 +384,173 @@ main(int argc, char **argv) ...@@ -332,80 +384,173 @@ main(int argc, char **argv)
usage(); usage();
} }
} }
else if (s.substr(0, 6) == "mexext")
{
if (s.length() <= 7 || s.at(6) != '=')
{
cerr << "Incorrect syntax for mexext option" << endl;
usage();
}
mexext = s.substr(7);
}
else if (s.substr(0, 11) == "exclude_eqs")
{
if (s.length() <= 12 || s.at(11) != '=')
{
cerr << "Incorrect syntax for exclude_eqs option" << endl;
usage();
}
exclude_eqs = s.substr(12);
}
else if (s.substr(0, 11) == "include_eqs")
{
if (s.length() <= 12 || s.at(11) != '=')
{
cerr << "Incorrect syntax for include_eqs option" << endl;
usage();
}
include_eqs = s.substr(12);
}
else if (s.substr(0, 10) == "matlabroot")
{
if (s.length() <= 11 || s.at(10) != '=')
{
cerr << "Incorrect syntax for matlabroot option" << endl;
usage();
}
matlabroot = filesystem::path {s.substr(11)};
}
else if (s == "onlymodel")
onlymodel = true;
else if (s == "gui")
gui = true;
else if (s == "use_dll")
use_dll = true;
else if (s == "nocommutativity")
DataTree::setNoCommutativity();
else else
{ {
cerr << "Unknown option: " << argv[arg] << endl; cerr << "Unknown option: " << s << endl;
usage(); usage();
} }
} }
if (!nopreprocessoroutput)
cout << "Starting preprocessing of the model file ..." << endl; cout << "Starting preprocessing of the model file ..." << endl;
// Determine root of Dynare installation
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")
// Special case: backward compatibility location in matlab/preprocessor64/dynare_m(.exe)?
dynareroot = dynareroot.parent_path();
// Construct basename (i.e. remove file extension if there is one) // Construct basename (i.e. remove file extension if there is one)
string basename = argv[1]; /* Calling string() method on filename.stem(): not necessary on GNU/Linux and macOS because there
string modfile, modfiletxt; is an implicit conversion from filesystem:path to string (i.e. basic_string<char>), but needed
size_t fsc = basename.find_first_of(';'); on Windows because the implicit conversion is only to wstring (i.e. basic_string<wchar_t>). */
if (fsc != string::npos) const string basename {filename.stem().string()};
{
// If a semicolon is found in argv[1], treat it as the text of the modfile
modfile = "mod_file_passed_as_string.mod";
basename = "mod_file_passed_as_string";
modfiletxt = argv[1];
}
else
{
// If a semicolon is NOT found in argv[1], treat it as the name of the modfile
modfile = argv[1];
size_t pos = basename.find_last_of('.');
if (pos != string::npos)
basename.erase(pos);
ifstream modfile(argv[1], ios::binary); // Forbid some basenames, since they will cause trouble (see preprocessor#62)
if (modfile.fail()) set<string> forbidden_basenames = {"T", "y", "x", "params", "steady_state", "it_", "true"};
if (forbidden_basenames.contains(basename))
{ {
cerr << "ERROR: Could not open file: " << argv[1] << endl; cerr << "ERROR: Please use another name for your .mod file. The one you have chosen ("
<< argv[1] << ") conflicts with internal Dynare names." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
stringstream buffer;
buffer << modfile.rdbuf();
modfiletxt = buffer.str();
}
WarningConsolidation warnings(no_warn); WarningConsolidation warnings(no_warn);
// Process config file // Process config file
ConfigFile config_file(parallel, parallel_test, parallel_slave_open_mode, cluster_name); Configuration config {parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec,
config_file.getConfigFileInfo(parallel_config_file); cluster_name};
config_file.checkPass(warnings); config.getConfigFileInfo(conffile, warnings);
config_file.transformPass(); config.checkPass(warnings);
config.transformPass();
// If Include option was passed to the [paths] block of the config file, add // If Include option was passed to the [paths] block of the config file, add
// it to paths before macroprocessing // it to paths before macroprocessing
vector<string> config_include_paths = config_file.getIncludePaths(); for (const auto& it : config.getIncludePaths())
for (vector<string>::const_iterator it = config_include_paths.begin(); paths.emplace_back(it);
it != config_include_paths.end(); it++)
path.push_back(*it);
// Do macro processing /*
stringstream macro_output; * Macro-expand MOD file
main1(modfile, basename, modfiletxt, debug, save_macro, save_macro_file, no_line_macro, no_empty_line_macro, */
defines, path, macro_output); stringstream macro_output
= macroExpandModFile(filename, modfile, debug, save_macro, move(save_macro_file), line_macro,
defines, move(paths));
if (only_macro) if (only_macro)
return EXIT_SUCCESS; return EXIT_SUCCESS;
// Do the rest if (!exclude_eqs.empty() && !include_eqs.empty())
main2(macro_output, basename, debug, clear_all, clear_global, {
no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive, cerr << "You may only pass one of `include_eqs` and `exclude_eqs`" << endl;
parallel, config_file, warnings, nostrict, stochastic, check_model_changes, minimal_workspace, exit(EXIT_FAILURE);
compute_xrefs, output_mode, language, params_derivs_order, transform_unary_ops }
#if defined(_WIN32) || defined(__CYGWIN32__)
, cygwin, msvc, mingw /*
#endif * Process Macro-expanded MOD file
, json, json_output_mode, onlyjson, jsonderivsimple, nopreprocessoroutput */
); ParsingDriver p(warnings, nostrict);
filesystem::remove_all(basename + "/model/json");
// Do parsing and construct internal representation of mod file
unique_ptr<ModFile> mod_file = p.parse(macro_output, debug);
// Handle use_dll option specified on the command line
if (use_dll)
mod_file->use_dll = true;
if (mod_file->use_dll && language == LanguageOutputType::julia)
{
cerr << "ERROR: `use_dll` option is not compatible with Julia" << endl;
exit(EXIT_FAILURE);
}
if (mod_file->use_dll)
ModelTree::initializeMEXCompilationWorkers(max(jthread::hardware_concurrency(), 1U), dynareroot,
mexext);
if (json == JsonOutputPointType::parsing)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
// Run checking pass
mod_file->checkPass(nostrict, stochastic);
if (json == JsonOutputPointType::checkpass)
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,
transform_unary_ops, exclude_eqs, include_eqs);
if (json == JsonOutputPointType::transformpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
// Evaluate parameters initialization, initval, endval and pounds
mod_file->evalAllExpressions(warn_uninit);
// Do computations
mod_file->computingPass(no_tmp_terms, output_mode, params_derivs_order);
if (json == JsonOutputPointType::computingpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, jsonderivsimple);
// Write output files
if (language == LanguageOutputType::julia)
mod_file->writeJuliaOutput(basename);
else
mod_file->writeMOutput(basename, clear_all, clear_global, no_warn, console, nograph,
nointeractive, config, 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
compilation (and is not printed in case of compilation failure). */
if (mod_file->use_dll)
ModelTree::waitForMEXCompilationWorkers();
cout << "Preprocessing completed." << endl;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/*
* Copyright (C) 2015-2017 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sstream>
#include <fstream>
#include "macro/MacroDriver.hh"
bool compareNewline (int i, int j) {
return i == '\n' && j == '\n';
}
void
main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file,
bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream &macro_output)
{
// Do macro processing
MacroDriver m;
m.parse(modfile, basename, modfiletxt, macro_output, debug, no_line_macro, defines, path);
if (save_macro)
{
if (save_macro_file.empty())
save_macro_file = basename + "-macroexp.mod";
ofstream macro_output_file(save_macro_file);
if (macro_output_file.fail())
{
cerr << "Cannot open " << save_macro_file << " for macro output" << endl;
exit(EXIT_FAILURE);
}
string str (macro_output.str());
if (no_empty_line_macro)
str.erase(unique(str.begin(), str.end(), compareNewline), str.end());
macro_output_file << str;
macro_output_file.close();
}
}
/*
* Copyright (C) 2008-2017 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <boost/filesystem.hpp>
#include "ParsingDriver.hh"
#include "ModFile.hh"
#include "ConfigFile.hh"
#include "ExtendedPreprocessorTypes.hh"
void
main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear_global,
bool no_tmp_terms, bool no_log, bool no_warn, bool warn_uninit, bool console,
bool nograph, bool nointeractive, bool parallel, ConfigFile &config_file,
WarningConsolidation &warnings, bool nostrict, bool stochastic, bool check_model_changes,
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
LanguageOutputType language, int params_derivs_order, bool transform_unary_ops
#if defined(_WIN32) || defined(__CYGWIN32__)
, bool cygwin, bool msvc, bool mingw
#endif
, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple
, bool nopreprocessoroutput
)
{
ParsingDriver p(warnings, nostrict);
boost::filesystem::remove_all(basename + "/model/json");
// Do parsing and construct internal representation of mod file
unique_ptr<ModFile> mod_file = p.parse(in, debug);
if (json == JsonOutputPointType::parsing)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput);
// Run checking pass
mod_file->checkPass(nostrict, stochastic);
if (json == JsonOutputPointType::checkpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput);
// Perform transformations on the model (creation of auxiliary vars and equations)
mod_file->transformPass(nostrict, stochastic, compute_xrefs || json == JsonOutputPointType::transformpass, nopreprocessoroutput, transform_unary_ops);
if (json == JsonOutputPointType::transformpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput);
// Evaluate parameters initialization, initval, endval and pounds
mod_file->evalAllExpressions(warn_uninit, nopreprocessoroutput);
// Do computations
mod_file->computingPass(no_tmp_terms, output_mode, params_derivs_order, nopreprocessoroutput);
if (json == JsonOutputPointType::computingpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput, jsonderivsimple);
// Write outputs
if (output_mode != FileOutputType::none)
mod_file->writeExternalFiles(basename, output_mode, language, nopreprocessoroutput);
else
mod_file->writeOutputFiles(basename, clear_all, clear_global, no_log, no_warn, console, nograph,
nointeractive, config_file, check_model_changes, minimal_workspace, compute_xrefs
#if defined(_WIN32) || defined(__CYGWIN32__)
, cygwin, msvc, mingw
#endif
, nopreprocessoroutput
);
if (!nopreprocessoroutput)
cout << "Preprocessing completed." << endl;
}
/*
* Copyright © 2020-2025 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include "EquationTags.hh"
#include <ostream>
#include <regex>
#include <utility>
set<int>
EquationTags::getEqnsByKey(const string& key) const
{
set<int> retval;
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
{
set<int> retval;
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
{
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
{
set<int> retval;
for (const auto& [eqn, tags] : eqn_tags)
{
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:;
}
return retval;
}
void
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)
if (eqn_tags.contains(oldeqn))
{
auto tmp = eqn_tags.extract(oldeqn);
tmp.key() = neweqn;
eqn_tags.insert(move(tmp));
}
}
void
EquationTags::writeCheckSumInfo(ostream& output) const
{
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
{
output << "M_.equations_tags = {" << endl;
for (const auto& [eqn, tags] : eqn_tags)
for (const auto& [key, value] : tags)
output << " " << eqn + 1 << " , '" << key << "' , '" << value << "' ;" << endl;
output << "};" << endl;
}
void
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)");
str = regex_replace(str, backslash, R"(\textbackslash)");
str = regex_replace(str, special_latex_chars, R"(\$&)");
str = regex_replace(str, carrot, R"(\^{})");
str = regex_replace(str, tilde, R"(\textasciitilde{})");
return regex_replace(str, textbackslash, R"(\textbackslash{})");
};
output << R"(\noindent[)";
for (bool wrote_eq_tag {false}; const auto& [key, value] : eqn_tags.at(eqn))
{
if (exchange(wrote_eq_tag, true))
output << ", ";
output << escape_special_latex_symbols(key);
if (!value.empty())
output << "= `" << escape_special_latex_symbols(value) << "'";
}
output << "]" << endl;
}
void
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))
{
if (exchange(wroteFirst, true))
output << ", ";
output << R"(")" << key << R"(": ")" << value << R"(")";
}
output << "}";
}
/*
* Copyright © 2020-2023 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef EQUATION_TAGS_HH
#define EQUATION_TAGS_HH
#include <map>
#include <optional>
#include <set>
#include <string>
using namespace std;
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()});
else
eqn_tags[eqn] = move(tags);
}
//! Add a single equation tag for the given equation
void
add(int eqn, string key, string value)
{
eqn_tags[eqn][move(key)] = move(value);
}
//! Clear all equation tag information
void
clear()
{
eqn_tags.clear();
}
//! 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);
//! Various functions to get info from equation tags
//! Get equation tags for a given equation
[[nodiscard]] map<string, string>
getTagsByEqn(int eqn) const
{
if (auto it = eqn_tags.find(eqn); it != eqn_tags.end())
return it->second;
return {};
}
//! Get equations that have the given key
[[nodiscard]] set<int> getEqnsByKey(const string& key) const;
//! Get equations that have the given key and value
[[nodiscard]] set<int> getEqnsByTag(const string& key, const string& value) const;
//! Get the first equation that has the given key and value
[[nodiscard]] optional<int> getEqnByTag(const string& key, const string& value) const;
// Get equations that have all the given keys and values (seen as a conjunction)
[[nodiscard]] set<int> getEqnsByTags(const map<string, string>& tags_selected) const;
//! Get the tag value given the equation number and key
[[nodiscard]] optional<string>
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())
return it2->second;
return nullopt;
}
//! Get the equations marked dynamic
[[nodiscard]] set<int>
getDynamicEqns() const
{
return getEqnsByTag("dynamic", "");
}
//! Returns true if equation tag with key and value exists
[[nodiscard]] bool
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
[[nodiscard]] bool
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;
};
#endif
Source diff could not be displayed: it is too large. Options to address this: view the blob.
/* /*
* Copyright (C) 2007-2018 Dynare Team * Copyright © 2007-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -14,26 +14,31 @@ ...@@ -14,26 +14,31 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _EXPR_NODE_HH #ifndef EXPR_NODE_HH
#define _EXPR_NODE_HH #define EXPR_NODE_HH
#include <set> #include <concepts>
#include <functional>
#include <map> #include <map>
#include <vector> #include <optional>
#include <ostream> #include <ostream>
#include <functional> #include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std; using namespace std;
#include "SymbolTable.hh" #include "Bytecode.hh"
#include "CodeInterpreter.hh" #include "CommonEnums.hh"
#include "ExternalFunctionsTable.hh" #include "ExternalFunctionsTable.hh"
#include "SymbolList.hh"
class DataTree; class DataTree;
class NumConstNode;
class VariableNode; class VariableNode;
class UnaryOpNode; class UnaryOpNode;
class BinaryOpNode; class BinaryOpNode;
...@@ -48,82 +53,116 @@ struct ExprNodeLess; ...@@ -48,82 +53,116 @@ struct ExprNodeLess;
see the definition of ExprNodeLess */ see the definition of ExprNodeLess */
using temporary_terms_t = set<expr_t, ExprNodeLess>; using temporary_terms_t = set<expr_t, ExprNodeLess>;
/*! Keeps track of array indices of temporary_terms for writing */ /*! Keeps track of array indices of temporary_terms for writing */
using temporary_terms_idxs_t = map<expr_t, int>; using temporary_terms_idxs_t = unordered_map<expr_t, int>;
//! set of temporary terms used in a block
using temporary_terms_inuse_t = set<int>;
using map_idx_t = map<int, int>;
//! Type for evaluation contexts //! Type for evaluation contexts
/*! The key is a symbol id. Lags are assumed to be null */ /*! The key is a symbol id. Lags are assumed to be null */
using eval_context_t = map<int, double>; using eval_context_t = map<int, double>;
//! Type for tracking first/second derivative functions that have already been written as temporary terms //! Type for tracking first/second derivative functions that have already been written as temporary
//! terms
using deriv_node_temp_terms_t = map<pair<int, vector<expr_t>>, int>; using deriv_node_temp_terms_t = map<pair<int, vector<expr_t>>, int>;
//! Type for the substitution map used in the process of substitutitng diff expressions //! Type for the substitution map used for creating aux. vars for diff and unary_ops
//! diff_table[static_expr_t][lag] -> [dynamic_expr_t] /*! Let ≅ be the equivalence relationship such that two expressions e₁ and e₂
using diff_table_t = map<expr_t, map<int, expr_t>>; are equivalent iff e₁ can be obtained from e₂ by shifting all leads/lags by
the same number of periods (e.g. x₋₁+y₂≅x₁+y₄).
//! Possible types of output when writing ExprNode(s)
For each equivalence class, we select a representative element, which is
the class member which has no lead and a variable appearing at current
period (in the previous example, it would be x₋₃+y). (Obviously, if there
is no variable in the expression, then there is only one element in the
class, and that one is the representative)
Each member of an equivalence class is represented by an integer,
corresponding to its distance to the representative element (e.g. x₋₁+y₂
has index 2 and x₁+y₄ has index 4). The representative element has index 0
by definition.
The keys in the std::map are the representative elements of the various
equivalence classes. The values are themselves std::map that describe the
equivalence class: they associate indices of class members to the
expressions with which they should be substituted. */
using lag_equivalence_table_t = map<expr_t, map<int, expr_t>>;
//! Possible types of output when writing ExprNode(s) (not used for bytecode)
enum class ExprNodeOutputType enum class ExprNodeOutputType
{ {
matlabStaticModel, //!< Matlab code, static model matlabStaticModel, //!< Matlab code, static model, legacy representation
matlabDynamicModel, //!< Matlab code, dynamic model matlabDynamicModel, //!< Matlab code, dynamic model, legacy representation
matlabStaticModelSparse, //!< Matlab code, static block decomposed model matlabSparseStaticModel, //!< Matlab code, static model, sparse representation
matlabDynamicModelSparse, //!< Matlab code, dynamic block decomposed model matlabSparseDynamicModel, //!< Matlab code, dynamic model, sparse representation
CDynamicModel, //!< C code, dynamic model CDynamicModel, //!< C code, dynamic model, legacy representation
CStaticModel, //!< C code, static model CStaticModel, //!< C code, static model, legacy representation
juliaStaticModel, //!< Julia code, static model CSparseDynamicModel, //!< C code, dynamic model, sparse representation
juliaDynamicModel, //!< Julia code, dynamic model CSparseStaticModel, //!< C code, static model, sparse representation
juliaStaticModel, //!< Julia code, static model, legacy representation
juliaDynamicModel, //!< Julia code, dynamic model, legacy representation
juliaSparseStaticModel, //!< Julia code, static model, sparse representation
juliaSparseDynamicModel, //!< Julia code, dynamic model, sparse representation
matlabOutsideModel, //!< Matlab code, outside model block (for example in initval) matlabOutsideModel, //!< Matlab code, outside model block (for example in initval)
latexStaticModel, //!< LaTeX code, static model latexStaticModel, //!< LaTeX code, static model
latexDynamicModel, //!< LaTeX code, dynamic model latexDynamicModel, //!< LaTeX code, dynamic model
latexDynamicSteadyStateOperator, //!< LaTeX code, dynamic model, inside a steady state operator latexDynamicSteadyStateOperator, //!< LaTeX code, dynamic model, inside a steady state operator
matlabDynamicSteadyStateOperator, //!< Matlab code, dynamic model, inside a steady state operator matlabDynamicSteadyStateOperator, //!< Matlab code, dynamic model, inside a steady state operator
matlabDynamicSparseSteadyStateOperator, //!< Matlab code, dynamic block decomposed model, inside a steady state operator
CDynamicSteadyStateOperator, //!< C code, dynamic model, inside a steady state operator CDynamicSteadyStateOperator, //!< C code, dynamic model, inside a steady state operator
juliaDynamicSteadyStateOperator, //!< Julia code, dynamic model, inside a steady state operator juliaDynamicSteadyStateOperator, //!< Julia code, dynamic model, inside a steady state operator
steadyStateFile, //!< Matlab code, in the generated steady state file steadyStateFile, //!< Matlab code, in the generated steady state file
juliaSteadyStateFile, //!< Julia code, in the generated steady state file juliaSteadyStateFile, //!< Julia code, in the generated steady state file
matlabDseries, //!< Matlab code for dseries matlabDseries, //!< Matlab code for dseries
epilogueFile //!< Matlab code, in the generated epilogue file juliaTimeDataFrame, //!< Julia code for TimeDataFrame objects
epilogueFile, //!< Matlab code, in the generated epilogue file
occbinDifferenceFile //!< MATLAB, in the generated occbin_difference file
};
// Possible types of output when writing ExprNode(s) in bytecode
enum class ExprNodeBytecodeOutputType
{
dynamicModel,
staticModel,
dynamicSteadyStateOperator, // Inside a steady_state operator
dynamicAssignmentLHS, // Assignment of a dynamic variable on the LHS of a (recursive) equation
staticAssignmentLHS // Assignment of a static variable on the LHS of a (recursive) equation
}; };
inline bool constexpr bool
isMatlabOutput(ExprNodeOutputType output_type) isMatlabOutput(ExprNodeOutputType output_type)
{ {
return output_type == ExprNodeOutputType::matlabStaticModel return output_type == ExprNodeOutputType::matlabStaticModel
|| output_type == ExprNodeOutputType::matlabDynamicModel || output_type == ExprNodeOutputType::matlabDynamicModel
|| output_type == ExprNodeOutputType::matlabSparseStaticModel
|| output_type == ExprNodeOutputType::matlabSparseDynamicModel
|| output_type == ExprNodeOutputType::matlabOutsideModel || output_type == ExprNodeOutputType::matlabOutsideModel
|| output_type == ExprNodeOutputType::matlabStaticModelSparse
|| output_type == ExprNodeOutputType::matlabDynamicModelSparse
|| output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator || output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::matlabDynamicSparseSteadyStateOperator
|| output_type == ExprNodeOutputType::steadyStateFile || output_type == ExprNodeOutputType::steadyStateFile
|| output_type == ExprNodeOutputType::matlabDseries || output_type == ExprNodeOutputType::matlabDseries
|| output_type == ExprNodeOutputType::epilogueFile; || output_type == ExprNodeOutputType::epilogueFile
|| output_type == ExprNodeOutputType::occbinDifferenceFile;
} }
inline bool constexpr bool
isJuliaOutput(ExprNodeOutputType output_type) isJuliaOutput(ExprNodeOutputType output_type)
{ {
return output_type == ExprNodeOutputType::juliaStaticModel return output_type == ExprNodeOutputType::juliaStaticModel
|| output_type == ExprNodeOutputType::juliaDynamicModel || output_type == ExprNodeOutputType::juliaDynamicModel
|| output_type == ExprNodeOutputType::juliaSparseStaticModel
|| output_type == ExprNodeOutputType::juliaSparseDynamicModel
|| output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator || output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::juliaSteadyStateFile; || output_type == ExprNodeOutputType::juliaSteadyStateFile
|| output_type == ExprNodeOutputType::juliaTimeDataFrame;
} }
inline bool constexpr bool
isCOutput(ExprNodeOutputType output_type) isCOutput(ExprNodeOutputType output_type)
{ {
return output_type == ExprNodeOutputType::CDynamicModel return output_type == ExprNodeOutputType::CDynamicModel
|| output_type == ExprNodeOutputType::CStaticModel || output_type == ExprNodeOutputType::CStaticModel
|| output_type == ExprNodeOutputType::CSparseDynamicModel
|| output_type == ExprNodeOutputType::CSparseStaticModel
|| output_type == ExprNodeOutputType::CDynamicSteadyStateOperator; || output_type == ExprNodeOutputType::CDynamicSteadyStateOperator;
} }
inline bool constexpr bool
isLatexOutput(ExprNodeOutputType output_type) isLatexOutput(ExprNodeOutputType output_type)
{ {
return output_type == ExprNodeOutputType::latexStaticModel return output_type == ExprNodeOutputType::latexStaticModel
...@@ -131,17 +170,66 @@ isLatexOutput(ExprNodeOutputType output_type) ...@@ -131,17 +170,66 @@ isLatexOutput(ExprNodeOutputType output_type)
|| output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator; || output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator;
} }
constexpr bool
isSteadyStateOperatorOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::CDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator;
}
constexpr bool
isSparseModelOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::matlabSparseStaticModel
|| output_type == ExprNodeOutputType::matlabSparseDynamicModel
|| output_type == ExprNodeOutputType::juliaSparseStaticModel
|| output_type == ExprNodeOutputType::juliaSparseDynamicModel
|| output_type == ExprNodeOutputType::CSparseDynamicModel
|| output_type == ExprNodeOutputType::CSparseStaticModel;
}
constexpr bool
isAssignmentLHSBytecodeOutput(ExprNodeBytecodeOutputType output_type)
{
return output_type == ExprNodeBytecodeOutputType::staticAssignmentLHS
|| output_type == ExprNodeBytecodeOutputType::dynamicAssignmentLHS;
}
/* Equal to 1 for Matlab langage or Julia, or to 0 for C language. Not defined for LaTeX. /* Equal to 1 for Matlab langage or Julia, or to 0 for C language. Not defined for LaTeX.
In Matlab and Julia, array indexes begin at 1, while they begin at 0 in C */ In Matlab and Julia, array indexes begin at 1, while they begin at 0 in C */
#define ARRAY_SUBSCRIPT_OFFSET(output_type) ((int) (isMatlabOutput(output_type) || isJuliaOutput(output_type))) constexpr int
ARRAY_SUBSCRIPT_OFFSET(ExprNodeOutputType output_type)
{
return static_cast<int>(isMatlabOutput(output_type) || isJuliaOutput(output_type));
}
// Left and right array subscript delimiters: '(' and ')' for Matlab, '[' and ']' for C // Left and right array subscript delimiters: '(' and ')' for Matlab, '[' and ']' for C
#define LEFT_ARRAY_SUBSCRIPT(output_type) (isMatlabOutput(output_type) ? '(' : '[') constexpr char
#define RIGHT_ARRAY_SUBSCRIPT(output_type) (isMatlabOutput(output_type) ? ')' : ']') LEFT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)
{
return isMatlabOutput(output_type) ? '(' : '[';
}
constexpr char
RIGHT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)
{
return isMatlabOutput(output_type) ? ')' : ']';
}
// Left and right parentheses // Left and right parentheses
#define LEFT_PAR(output_type) (isLatexOutput(output_type) ? "\\left(" : "(") inline string
#define RIGHT_PAR(output_type) (isLatexOutput(output_type) ? "\\right)" : ")") LEFT_PAR(ExprNodeOutputType output_type)
{
return isLatexOutput(output_type) ? "\\left(" : "(";
}
inline string
RIGHT_PAR(ExprNodeOutputType output_type)
{
return isLatexOutput(output_type) ? "\\right)" : ")";
}
//! Base class for expression nodes //! Base class for expression nodes
class ExprNode class ExprNode
...@@ -159,11 +247,20 @@ class ExprNode ...@@ -159,11 +247,20 @@ class ExprNode
friend class AbstractExternalFunctionNode; friend class AbstractExternalFunctionNode;
friend class VarExpectationNode; friend class VarExpectationNode;
friend class PacExpectationNode; friend class PacExpectationNode;
private: private:
//! Computes derivative w.r. to a derivation ID (but doesn't store it in derivatives map) //! Computes derivative w.r. to a derivation ID (but doesn't store it in derivatives map)
/*! You shoud use getDerivative() to get the benefit of symbolic a priori and of caching */ /*! You shoud use getDerivative() to get the benefit of symbolic a priori and of caching */
virtual expr_t computeDerivative(int deriv_id) = 0; virtual expr_t computeDerivative(int deriv_id) = 0;
/* Internal helper for getChainRuleDerivative(), that does the computation
but assumes that the caching of this is handled elsewhere */
virtual expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache)
= 0;
protected: protected:
//! Reference to the enclosing DataTree //! Reference to the enclosing DataTree
DataTree& datatree; DataTree& datatree;
...@@ -180,23 +277,40 @@ class ExprNode ...@@ -180,23 +277,40 @@ class ExprNode
//! Used for caching of first order derivatives (when non-null) //! Used for caching of first order derivatives (when non-null)
map<int, expr_t> derivatives; map<int, expr_t> derivatives;
const static int min_cost_matlab{40*90}; constexpr static int min_cost_matlab {40 * 90};
const static int min_cost_c{40*4}; constexpr static int min_cost_c {40 * 4};
inline static int min_cost(bool is_matlab) { return(is_matlab ? min_cost_matlab : min_cost_c); }; constexpr static int
min_cost(bool is_matlab)
{
return is_matlab ? min_cost_matlab : min_cost_c;
}
//! Initializes data member non_null_derivatives
virtual void prepareForDerivation() = 0;
/* Computes the derivatives which are potentially non-null, using symbolic a
priori, similarly to prepareForDerivation(), but in a chain rule
derivation context. See getChainRuleDerivation() for the meaning of
“recursive_variables”. Note that all non-endogenous variables are
automatically considered to have a zero derivative (since they’re never
used in a chain rule context) */
virtual void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const
= 0;
//! Cost of computing current node //! Cost of computing current node
/*! Nodes included in temporary_terms are considered having a null cost */ /*! Nodes included in temporary_terms are considered having a null cost */
virtual int cost(int cost, bool is_matlab) const; [[nodiscard]] virtual int cost(int cost, bool is_matlab) const;
virtual int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const; [[nodiscard]] virtual int
virtual int cost(const map<NodeTreeReference, temporary_terms_t> &temp_terms_map, bool is_matlab) const; cost(const vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms, bool is_matlab) const;
[[nodiscard]] virtual int cost(const map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab) const;
//! For creating equation cross references //! For creating equation cross references
struct EquationInfo struct EquationInfo
{ {
set<pair<int, int>> param; set<pair<int, int>> param, endo, exo, exo_det;
set<pair<int, int>> endo;
set<pair<int, int>> exo;
set<pair<int, int>> exo_det;
}; };
//! If this node is a temporary term, writes its temporary term representation //! If this node is a temporary term, writes its temporary term representation
...@@ -205,55 +319,135 @@ class ExprNode ...@@ -205,55 +319,135 @@ class ExprNode
bool checkIfTemporaryTermThenWrite(ostream& output, ExprNodeOutputType output_type, bool checkIfTemporaryTermThenWrite(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs) const; const temporary_terms_idxs_t& temporary_terms_idxs) const;
// Same as above, for the bytecode case
bool
checkIfTemporaryTermThenWriteBytecode(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs) const;
// Internal helper for matchVariableTimesConstantTimesParam()
virtual void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id,
double& constant, bool at_denominator) const;
/* Computes the representative element and the index under the
lag-equivalence relationship. See the comment above
lag_equivalence_table_t for an explanation of these concepts. */
[[nodiscard]] pair<expr_t, int> getLagEquivalenceClass() const;
/* Computes the set of all sub-expressions that contain the variable
(symb_id, lag).
Note that if a diff operator is encountered:
- diff(expr) will be added to the output set if either expr or expr(-1)
contains the variable;
- the method will be called recursively on expr-expr(-1) */
virtual void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const
= 0;
public: public:
ExprNode(DataTree& datatree_arg, int idx_arg); ExprNode(DataTree& datatree_arg, int idx_arg);
virtual virtual ~ExprNode() = default;
~ExprNode();
ExprNode(const ExprNode&) = delete; ExprNode(const ExprNode&) = delete;
ExprNode(ExprNode &&) = delete;
ExprNode& operator=(const ExprNode&) = delete; ExprNode& operator=(const ExprNode&) = delete;
ExprNode & operator=(ExprNode &&) = delete;
//! Initializes data member non_null_derivatives
virtual void prepareForDerivation() = 0;
//! Returns derivative w.r. to derivation ID //! Returns derivative w.r. to derivation ID
/*! Uses a symbolic a priori to pre-detect null derivatives, and caches the result for other derivatives (to avoid computing it several times) /*! Uses a symbolic a priori to pre-detect null derivatives, and caches the result for other
For an equal node, returns the derivative of lhs minus rhs */ derivatives (to avoid computing it several times) For an equal node, returns the derivative of
lhs minus rhs */
expr_t getDerivative(int deriv_id); expr_t getDerivative(int deriv_id);
//! Computes derivatives by applying the chain rule for some variables /* Computes derivatives by applying the chain rule for some variables.
/*! — “recursive_variables” contains the derivation ID for which chain rules
\param deriv_id The derivation ID with respect to which we are derivating must be applied. Keys are derivation IDs, values are equations of the
\param recursive_variables Contains the derivation ID for which chain rules must be applied. Keys are derivation IDs, values are equations of the form x=f(y) where x is the key variable and x doesn't appear in y form x=f(y) where x is the key variable and x doesn't appear in y
*/ — “non_null_chain_rule_derivatives” is used to store the indices of
virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) = 0; variables that are potentially non-null (using symbolic a priori),
similarly to ExprNode::non_null_derivatives.
— “cache” is used to store already-computed derivatives (in a map
<expression, deriv_id> → derivative)
NB: always returns zero when “deriv_id” corresponds to a non-endogenous
variable (since such variables are never used in a chain rule context).
NB 2: “non_null_chain_rule_derivatives” and “cache” are specific to a given
value of “recursive_variables”, and thus should not be reused accross
calls that use different values of “recursive_variables”.
NB 3: the use of std::unordered_map instead of std::map for caching
purposes improves performance on very very large models (tens of thousands
of equations) */
expr_t getChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache);
//! Returns precedence of node //! Returns precedence of node
/*! Equals 100 for constants, variables, unary ops, and temporary terms */ /*! Equals 100 for constants, variables, unary ops, and temporary terms */
virtual int precedence(ExprNodeOutputType output_t, const temporary_terms_t &temporary_terms) const; [[nodiscard]] virtual int precedence(ExprNodeOutputType output_t,
const temporary_terms_t& temporary_terms) const;
//! Compute temporary terms in this expression
/*!
\param[in] derivOrder the derivation order (first w.r.t. endo/exo,
second w.r.t. params)
\param[out] temp_terms_map the computed temporary terms, associated
with their derivation order
\param[out] reference_count a temporary structure, used to count
references to each node (integer in outer pair is the
reference count, the inner pair is the derivation order)
\param[in] is_matlab whether we are in a MATLAB context, since that
affects the cost of each operator
A node will be marked as a temporary term if it is referenced at least
two times (i.e. has at least two parents), and has a computing cost
(multiplied by reference count) greater to datatree.min_cost
NB: the use of std::unordered_map instead of std::map for caching
purposes improves performance on very large models (⩾5000 equations)
*/
virtual void computeTemporaryTerms(
const pair<int, int>& derivOrder, map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count, bool is_matlab) const;
//! Fills temporary_terms set, using reference counts //! Compute temporary terms in this expression for block decomposed model
/*! A node will be marked as a temporary term if it is referenced at least two times (i.e. has at least two parents), and has a computing cost (multiplied by reference count) greater to datatree.min_cost */ /*!
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, \param[in] blk the block number
map<NodeTreeReference, temporary_terms_t> &temp_terms_map, \param[in] eq the equation number (within the block)
bool is_matlab, NodeTreeReference tr) const; \param[out] blocks_temporary_terms the computed temporary terms, per block
and per equation in the block
\param[out] reference_count a temporary structure, used to count
references to each node (first integer is the
reference count, second integer is the number of the block in which the
expression first appears, third integer is the equation number within the block)
Same rules as computeTemporaryTerms() for computing cost.
NB: the use of std::unordered_{set,map} instead of std::{set,map} for caching
and output improves performance on very large models (⩾5000 equations)
*/
virtual void
computeBlockTemporaryTerms(int blk, int eq,
vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const;
//! Writes output of node, using a Txxx notation for nodes in temporary_terms, and specifiying the set of already written external functions //! Writes output of node, using a Txxx notation for nodes in temporary_terms, and specifiying the
//! set of already written external functions
/*! /*!
\param[in] output the output stream \param[in] output the output stream
\param[in] output_type the type of output (MATLAB, C, LaTeX...) \param[in] output_type the type of output (MATLAB, C, LaTeX...)
\param[in] temporary_terms the nodes that are marked as temporary terms \param[in] temporary_terms the nodes that are marked as temporary terms
\param[in] a map from temporary_terms to integers indexes (in the \param[in] a map from temporary_terms to integers indexes (in the
MATLAB or Julia vector of temporary terms); can be empty MATLAB, C or Julia vector of temporary terms); can be empty
when writing C or MATLAB with block decomposition) when writing MATLAB with block decomposition)
\param[in] tef_terms the set of already written external function nodes \param[in] tef_terms the set of already written external function nodes
*/ */
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const = 0; virtual void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const
= 0;
//! returns true if the expr node contains an external function //! returns true if the expr node contains an external function
virtual bool containsExternalFunction() const = 0; [[nodiscard]] virtual bool containsExternalFunction() const = 0;
//! Writes output of node (with no temporary terms and with "outside model" output type) //! Writes output of node (with no temporary terms and with "outside model" output type)
void writeOutput(ostream& output) const; void writeOutput(ostream& output) const;
...@@ -262,17 +456,26 @@ class ExprNode ...@@ -262,17 +456,26 @@ class ExprNode
void writeOutput(ostream& output, ExprNodeOutputType output_type) const; void writeOutput(ostream& output, ExprNodeOutputType output_type) const;
//! Writes output of node, using a Txxx notation for nodes in temporary_terms //! Writes output of node, using a Txxx notation for nodes in temporary_terms
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs) const; void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs) const;
//! Writes output of node in JSON syntax //! Writes output of node in JSON syntax
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const = 0; virtual void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms,
bool isdynamic = true) const
= 0;
// Returns a string representation of the expression, used by the GDB pretty printer
[[nodiscard]] string toString() const;
//! Writes the Abstract Syntax Tree in JSON //! Writes the Abstract Syntax Tree in JSON
virtual void writeJsonAST(ostream& output) const = 0; virtual void writeJsonAST(ostream& output) const = 0;
virtual int precedenceJson(const temporary_terms_t &temporary_terms) const; [[nodiscard]] virtual int precedenceJson(const temporary_terms_t& temporary_terms) const;
//! Writes the output for an external function, ensuring that the external function is called as few times as possible using temporary terms //! Writes the output for an external function, ensuring that the external function is called as
//! few times as possible using temporary terms
virtual void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type, virtual void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
...@@ -283,14 +486,15 @@ class ExprNode ...@@ -283,14 +486,15 @@ class ExprNode
virtual void writeJsonExternalFunctionOutput(vector<string>& efout, virtual void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
const bool isdynamic = true) const; bool isdynamic = true) const;
virtual void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, virtual void writeBytecodeExternalFunctionOutput(
bool lhs_rhs, const temporary_terms_t &temporary_terms, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const; deriv_node_temp_terms_t& tef_terms) const;
//! Computes the set of all variables of a given symbol type in the expression (with information on lags) //! Computes the set of all variables of a given symbol type in the expression (with information
//! on lags)
/*! /*!
Variables are stored as integer pairs of the form (symb_id, lag). Variables are stored as integer pairs of the form (symb_id, lag).
They are added to the set given in argument. They are added to the set given in argument.
...@@ -299,16 +503,14 @@ class ExprNode ...@@ -299,16 +503,14 @@ class ExprNode
*/ */
virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const = 0; virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const = 0;
//! Find lowest lag for VAR
virtual int VarMinLag() const = 0;
//! Find the maximum lag in a VAR: handles case where LHS is diff //! Find the maximum lag in a VAR: handles case where LHS is diff
virtual int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const = 0; [[nodiscard]] virtual int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const = 0;
//! Finds LHS variable in a VAR equation //! Finds LHS variable in a VAR equation
virtual void collectVARLHSVariable(set<expr_t>& result) const = 0; virtual void collectVARLHSVariable(set<expr_t>& result) const = 0;
//! Computes the set of all variables of a given symbol type in the expression (without information on lags) //! Computes the set of all variables of a given symbol type in the expression (without
//! information on lags)
/*! /*!
Variables are stored as symb_id. Variables are stored as symb_id.
They are added to the set given in argument. They are added to the set given in argument.
...@@ -323,92 +525,96 @@ class ExprNode ...@@ -323,92 +525,96 @@ class ExprNode
They are added to the set given in argument. They are added to the set given in argument.
Note that model local variables are substituted by their expression in the computation. Note that model local variables are substituted by their expression in the computation.
*/ */
virtual void collectEndogenous(set<pair<int, int>> &result) const; void collectEndogenous(set<pair<int, int>>& result) const;
//! Computes the set of exogenous variables in the expression
/*!
Exogenous are stored as integer pairs of the form (type_specific_id, lag).
They are added to the set given in argument.
Note that model local variables are substituted by their expression in the computation.
*/
virtual void collectExogenous(set<pair<int, int>> &result) const;
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const = 0;
virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const;
class EvalException class EvalException
{ {
}; };
class EvalExternalFunctionException : public EvalException class EvalExternalFunctionException : public EvalException
{ {
}; };
virtual double eval(const eval_context_t &eval_context) const noexcept(false) = 0; [[nodiscard]] virtual double eval(const eval_context_t& eval_context) const noexcept(false) = 0;
virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const = 0;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic) const; // Write output to bytecode file
virtual void writeBytecodeOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const
= 0;
//! Creates a static version of this node //! Creates a static version of this node
/*! /*!
This method duplicates the current node by creating a similar node from which all leads/lags have been stripped, This method duplicates the current node by creating a similar node from which all leads/lags
adds the result in the static_datatree argument (and not in the original datatree), and returns it. have been stripped, adds the result in the static_datatree argument (and not in the original
datatree), and returns it.
*/ */
virtual expr_t toStatic(DataTree& static_datatree) const = 0; virtual expr_t toStatic(DataTree& static_datatree) const = 0;
/*! /*!
Compute cross references for equations Compute cross references for equations
*/ */
// virtual void computeXrefs(set<int> &param, set<int> &endo, set<int> &exo, set<int> &exo_det) const = 0; // virtual void computeXrefs(set<int> &param, set<int> &endo, set<int> &exo, set<int> &exo_det)
// const = 0;
virtual void computeXrefs(EquationInfo& ei) const = 0; virtual void computeXrefs(EquationInfo& ei) const = 0;
//! Try to normalize an equation linear in its endogenous variable
virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t>>> &List_of_Op_RHS) const = 0;
//! Returns the maximum lead of endogenous in this expression //! Helper for normalization of equations
/*! Normalize the equation this = rhs.
Must be called on a node containing the desired LHS variable.
Returns an equal node of the form: LHS variable = new RHS.
Must be given the set of all subexpressions that contain the desired LHS variable.
Throws a NormallizationFailed() exception if normalization is not possible. */
virtual BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const
= 0;
class NormalizationFailed
{
};
//! Returns the maximum lead of endogenous in this expression (not incl. heterogeneous endo)
/*! Always returns a non-negative value */ /*! Always returns a non-negative value */
virtual int maxEndoLead() const = 0; [[nodiscard]] virtual int maxEndoLead() const = 0;
//! Returns the maximum lead of exogenous in this expression //! Returns the maximum lead of exogenous in this expression (not incl. heterogeneous exo)
/*! Always returns a non-negative value */ /*! Always returns a non-negative value */
virtual int maxExoLead() const = 0; [[nodiscard]] virtual int maxExoLead() const = 0;
//! Returns the maximum lag of endogenous in this expression //! Returns the maximum lag of endogenous in this expression (not incl. heterogeneous endo)
/*! Always returns a non-negative value */ /*! Always returns a non-negative value */
virtual int maxEndoLag() const = 0; [[nodiscard]] virtual int maxEndoLag() const = 0;
//! Returns the maximum lag of exogenous in this expression //! Returns the maximum lag of exogenous in this expression (not incl. heterogeneous exo)
/*! Always returns a non-negative value */ /*! Always returns a non-negative value */
virtual int maxExoLag() const = 0; [[nodiscard]] virtual int maxExoLag() const = 0;
//! Returns the relative period of the most forward term in this expression /* Returns the maximum lead of endo/exo/exodet in this expression (including heterogeneous
/*! A negative value means that the expression contains only lagged variables */ endo/exo). A negative value means that the expression contains only lagged variables. A value
virtual int maxLead() const = 0; of numeric_limits<int>::min() means that there is no variable. */
[[nodiscard]] virtual int maxLead() const = 0;
//! Returns the relative period of the most backward term in this expression /* Returns the maximum lag of endo/exo/exodet in this expression (including heterogeneous
/*! A negative value means that the expression contains only leaded variables */ endo/exo). A negative value means that the expression contains only leaded variables. A value
virtual int maxLag() const = 0; of numeric_limits<int>::min() means that there is no variable. */
[[nodiscard]] virtual int maxLag() const = 0;
//! Get Max lag of var associated with Pac model /* Returns the maximum lag of endo/exo/exodet (including heterogeneous endo/exo), as if diffs were
//! Takes account of undiffed LHS variables in calculating the max lag expanded. This function behaves as maxLag(), except that it treats diff() differently. For
virtual int PacMaxLag(int lhs_symb_id) const = 0; e.g., on diff(diff(x(-1))), maxLag() returns 1 while maxLagWithDiffsExpanded() returns 3. */
[[nodiscard]] virtual int maxLagWithDiffsExpanded() const = 0;
virtual expr_t undiff() const = 0; [[nodiscard]] virtual expr_t undiff() const = 0;
//! Returns a new expression where all the leads/lags have been shifted backwards by the same amount //! Returns a new expression where all the leads/lags have been shifted backwards by the same
//! amount
/*! /*!
Only acts on endogenous, exogenous, exogenous det Only acts on endogenous, exogenous, exogenous det
\param[in] n The number of lags by which to shift \param[in] n The number of lags by which to shift
\return The same expression except that leads/lags have been shifted backwards \return The same expression except that leads/lags have been shifted backwards
*/ */
virtual expr_t decreaseLeadsLags(int n) const = 0; [[nodiscard]] virtual expr_t decreaseLeadsLags(int n) const = 0;
//! Type for the substitution map used in the process of creating auxiliary vars for leads >= 2 //! Type for the substitution map used in the process of creating auxiliary vars
using subst_table_t = map<const ExprNode*, const VariableNode*>; using subst_table_t = map<const ExprNode*, const VariableNode*>;
//! Type for the substitution map used in the process of substituting adl expressions //! Type for the substitution map used in the process of substituting adl expressions
...@@ -416,102 +622,135 @@ class ExprNode ...@@ -416,102 +622,135 @@ class ExprNode
//! Creates auxiliary endo lead variables corresponding to this expression //! Creates auxiliary endo lead variables corresponding to this expression
/*! /*!
If maximum endogenous lead >= 3, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table. If maximum endogenous lead >= 3, this method will also create intermediary auxiliary var, and
\pre This expression is assumed to have maximum endogenous lead >= 2 will add the equations of the form aux1 = aux2(+1) to the substitution table. \pre This
\param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added expression is assumed to have maximum endogenous lead >= 2 \param[in,out] subst_table The table
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. to which new auxiliary variables and their correspondance will be added \param[out] neweqs
\return The new variable node corresponding to the current expression Equations to be added to the model to match the creation of auxiliary variables. \return The new
variable node corresponding to the current expression
*/ */
VariableNode *createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; VariableNode* createEndoLeadAuxiliaryVarForMyself(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const;
//! Creates auxiliary exo lead variables corresponding to this expression //! Creates auxiliary exo lead variables corresponding to this expression
/*! /*!
If maximum exogenous lead >= 2, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table. If maximum exogenous lead >= 2, this method will also create intermediary auxiliary var, and
\pre This expression is assumed to have maximum exogenous lead >= 1 will add the equations of the form aux1 = aux2(+1) to the substitution table. \pre This
\param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added expression is assumed to have maximum exogenous lead >= 1 \param[in,out] subst_table The table
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. to which new auxiliary variables and their correspondance will be added \param[out] neweqs
\return The new variable node corresponding to the current expression Equations to be added to the model to match the creation of auxiliary variables. \return The new
variable node corresponding to the current expression
*/ */
VariableNode *createExoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; VariableNode* createExoLeadAuxiliaryVarForMyself(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const;
//! Constructs a new expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables //! Constructs a new expression where sub-expressions with max endo lead >= 2 have been replaced
//! by auxiliary variables
/*! /*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr. \param[in,out] subst_table Map used to store expressions that have already be substituted and
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. their corresponding variable, in order to avoid creating two auxiliary variables for the same
sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables.
If the method detects a sub-expr which needs to be substituted, two cases are possible: If the method detects a sub-expr which needs to be substituted, two cases are possible:
- if this expr is in the table, then it will use the corresponding variable and return the substituted expression - if this expr is in the table, then it will use the corresponding variable and return the
- if this expr is not in the table, then it will create an auxiliary endogenous variable, add the substitution in the table and return the substituted expression substituted expression
- if this expr is not in the table, then it will create an auxiliary endogenous variable, add
the substitution in the table and return the substituted expression
\return A new equivalent expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables \return A new equivalent expression where sub-expressions with max endo lead >= 2 have been
replaced by auxiliary variables
*/ */
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const = 0; virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const
= 0;
//! Constructs a new expression where endo variables with max endo lag >= 2 have been replaced by auxiliary variables //! Constructs a new expression where endo variables with max endo lag >= 2 have been replaced by
//! auxiliary variables
/*! /*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr. \param[in,out] subst_table Map used to store expressions that have already be substituted and
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. their corresponding variable, in order to avoid creating two auxiliary variables for the same
sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables.
*/ */
virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0; virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
//! Constructs a new expression where exogenous variables with a lead have been replaced by auxiliary variables //! Constructs a new expression where exogenous variables with a lead have been replaced by
//! auxiliary variables
/*! /*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr. \param[in,out] subst_table Map used to store expressions that have already be substituted and
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. their corresponding variable, in order to avoid creating two auxiliary variables for the same
sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables.
*/ */
virtual expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const = 0; virtual expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
//! Constructs a new expression where exogenous variables with a lag have been replaced by auxiliary variables bool deterministic_model) const
= 0;
//! Constructs a new expression where exogenous variables with a lag have been replaced by
//! auxiliary variables
/*! /*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr. \param[in,out] subst_table Map used to store expressions that have already be substituted and
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. their corresponding variable, in order to avoid creating two auxiliary variables for the same
sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables.
*/ */
virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0; virtual expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const
= 0;
//! Constructs a new expression where the expectation operator has been replaced by auxiliary variables //! Constructs a new expression where the expectation operator has been replaced by auxiliary
//! variables
/*! /*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr. \param[in,out] subst_table Map used to store expressions that have already be substituted and
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. their corresponding variable, in order to avoid creating two auxiliary variables for the same
\param[in] partial_information_model Are we substituting in a partial information model? sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables. \param[in] partial_information_model Are we substituting in a partial
information model?
*/ */
virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const = 0; virtual expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const
= 0;
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const = 0; [[nodiscard]] virtual expr_t decreaseLeadsLagsPredeterminedVariables() const = 0;
//! Constructs a new expression where forward variables (supposed to be at most in t+1) have been replaced by themselves at t, plus a new aux var representing their (time) differentiate //! Constructs a new expression where forward variables (supposed to be at most in t+1) have been
//! replaced by themselves at t, plus a new aux var representing their (time) differentiate
/*! /*!
\param[in] subset variables to which to limit the transformation; transform \param[in] subset variables to which to limit the transformation; transform
all fwrd vars if empty all fwrd vars if empty
\param[in,out] subst_table Map used to store mapping between a given \param[in,out] subst_table Map used to store mapping between a given
forward variable and the aux var that contains its differentiate forward variable and the aux var that contains its differentiate
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. \param[out] neweqs Equations to be added to the model to match the creation of auxiliary
variables.
*/ */
virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0; virtual expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
//! Return true if the nodeID is a numerical constant equal to value and false otherwise //! Return true if the nodeID is a numerical constant equal to value and false otherwise
/*! /*!
\param[in] value of the numerical constante \param[in] value of the numerical constante
\param[out] the boolean equal to true if NodeId is a constant equal to value \param[out] the boolean equal to true if NodeId is a constant equal to value
*/ */
virtual bool isNumConstNodeEqualTo(double value) const = 0; [[nodiscard]] virtual bool isNumConstNodeEqualTo(double value) const = 0;
//! Returns true if the expression contains one or several endogenous variable
virtual bool containsEndogenous() const = 0;
//! Returns true if the expression contains one or several exogenous variable
virtual bool containsExogenous() const = 0;
//! Returns the number of diffs present //! Returns the maximum number of nested diffs in the expression
virtual int countDiffs() const = 0; [[nodiscard]] virtual int countDiffs() const = 0;
//! Return true if the nodeID is a variable withe a type equal to type_arg, a specific variable id aqual to varfiable_id and a lag equal to lag_arg and false otherwise //! Return true if the nodeID is a variable withe a type equal to type_arg, a specific variable id
//! aqual to varfiable_id and a lag equal to lag_arg and false otherwise
/*! /*!
\param[in] the type (type_arg), specifique variable id (variable_id and the lag (lag_arg) \param[in] the type (type_arg), specifique variable id (variable_id and the lag (lag_arg)
\param[out] the boolean equal to true if NodeId is the variable \param[out] the boolean equal to true if NodeId is the variable
*/ */
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const = 0; [[nodiscard]] virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const
= 0;
//! Replaces the Trend var with datatree.One //! Replaces the Trend var with datatree.One
virtual expr_t replaceTrendVar() const = 0; [[nodiscard]] virtual expr_t replaceTrendVar() const = 0;
//! Constructs a new expression where the variable indicated by symb_id has been detrended //! Constructs a new expression where the variable indicated by symb_id has been detrended
/*! /*!
...@@ -523,71 +762,196 @@ class ExprNode ...@@ -523,71 +762,196 @@ class ExprNode
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const = 0; virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const = 0;
//! Substitute adl operator //! Substitute adl operator
virtual expr_t substituteAdl() const = 0; [[nodiscard]] virtual expr_t substituteAdl() const = 0;
//! Substitute VarExpectation nodes //! Substitute out model-local variables
virtual expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const = 0; [[nodiscard]] virtual expr_t substituteModelLocalVariables() const = 0;
//! Substitute VarExpectation nodes
[[nodiscard]] virtual expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const
= 0;
//! Mark diff nodes to be substituted
/*! The various nodes that are equivalent up to a shift of leads/lags are
grouped together in the “nodes” table. See the comment above
lag_equivalence_table_t for more details. */
virtual void findDiffNodes(lag_equivalence_table_t& nodes) const = 0;
//! Substitute diff operator //! Substitute diff operator
virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const = 0; virtual expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
virtual void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const = 0; vector<BinaryOpNode*>& neweqs) const
virtual int findTargetVariable(int lhs_symb_id) const = 0; = 0;
virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
virtual expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0; //! Mark unary ops nodes to be substituted
/*! The various nodes that are equivalent up to a shift of leads/lags are
grouped together in the “nodes” table. See the comment above
lag_equivalence_table_t for more details. */
virtual void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const = 0;
//! Substitute unary ops nodes
virtual expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes,
subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
//! Substitute pac_expectation operator //! Substitute pac_expectation operator
virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) = 0; virtual expr_t substitutePacExpectation(const string& name, expr_t subexpr) = 0;
//! Add ExprNodes to the provided datatree
virtual expr_t clone(DataTree &datatree) const = 0;
//! Move a trend variable with lag/lead to time t by dividing/multiplying by its growth factor
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const = 0;
//! Returns true if the expression is in static form (no lead, no lag, no expectation, no STEADY_STATE) //! Substitute pac_target_nonstationary operator
virtual bool isInStaticForm() const = 0; virtual expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) = 0;
//! Substitute auxiliary variables by their expression in static model [[nodiscard]] virtual optional<int> findTargetVariable(int lhs_symb_id) const = 0;
virtual expr_t substituteStaticAuxiliaryVariable() const = 0;
//! Returns true if model_info_name is referenced by a VarExpectationNode //! Add ExprNodes to the provided datatree
virtual bool isVarModelReferenced(const string &model_info_name) const = 0; virtual expr_t clone(DataTree& alt_datatree) const = 0;
//! Fills parameter information rerhs_symblated to PAC equation //! Move a trend variable with lag/lead to time t by dividing/multiplying by its growth factor
virtual void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars, [[nodiscard]] virtual expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const
set<pair<int, pair<int, int>>> &params_and_vars) const = 0; = 0;
//! Returns true if the expression is in static form (no lead, no lag, no expectation, no
//! STEADY_STATE)
[[nodiscard]] virtual bool isInStaticForm() const = 0;
//! Matches a linear combination of variables (endo or exo), where scalars can be
//! constant*parameter
/*! Returns a list of (variable_id, lag, param_id, constant)
corresponding to the terms in the expression. When there is no
parameter in a term, param_id is nullopt.
Can throw a MatchFailureException.
*/
[[nodiscard]] vector<tuple<int, int, optional<int>, double>>
matchLinearCombinationOfVariables() const;
/* Matches a linear combination of variables (endo or exo), where scalars can
be constant*parameter. In addition, there may be one or more scalar terms
(i.e. without a variable).
Returns a list of (variable_id, lag, param_id, constant)
corresponding to the terms in the expression. When there is no
parameter in a term, param_id is nullopt. When the term is scalar (i.e.
no variable), then variable_id is nullopt.
Can throw a MatchFailureException.
*/
[[nodiscard]] vector<tuple<optional<int>, int, optional<int>, double>>
matchLinearCombinationOfVariablesPlusConstant() const;
/* Matches a parameter, times a linear combination of variables (endo or
exo), where scalars can be constant*parameters.
The first output argument is the symbol ID of the parameter.
The second output argument is the linear combination, in the same format
as the output of matchLinearCombinationOfVariables(). */
[[nodiscard]] pair<int, vector<tuple<int, int, optional<int>, double>>>
matchParamTimesLinearCombinationOfVariables() const;
/* Matches a linear combination of endogenous, where scalars can be any
constant expression (i.e. containing no endogenous, no exogenous and no
exogenous deterministic). The linear combination can contain constant
terms (intercept).
Returns a pair composed of:
– the terms of the form endogenous*scalar, as a list of (endo_id, constant expr);
– the sum of all constant (intercept) terms */
[[nodiscard]] pair<vector<pair<int, expr_t>>, expr_t>
matchLinearCombinationOfEndogenousWithConstant() const;
/* Matches an expression of the form parameter*(var1-endo2).
endo2 must correspond to symb_id. var1 must be an endogenous or an
exogenous; it must be of the form X(-1) or log(X(-1)) or log(X)(-1) (unary ops aux var),
where X itself is *not* an aux var.
Returns the symbol IDs of the parameter and of var1.
Throws a MatchFailureException otherwise */
[[nodiscard]] pair<int, int> matchParamTimesTargetMinusVariable(int symb_id) const;
//! Fills info for non optimizing part of PAC equation
virtual void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const = 0;
//! Returns true if expression is of the form: //! Returns true if expression is of the form:
//! param * (endog op endog op ...) + param * (endog op endog op ...) + ... //! param * (endog op endog op ...) + param * (endog op endog op ...) + ...
virtual bool isParamTimesEndogExpr() const = 0; [[nodiscard]] virtual bool isParamTimesEndogExpr() const = 0;
//! Finds the share of optimizing agents in the PAC equation,
//! the expr node associated with it,
//! and the expr node associated with the non-optimizing part
virtual void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
expr_t &optim_part,
expr_t &non_optim_part) const = 0;
//! Adds PAC equation param info to pac_expectation
virtual void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) = 0;
//! Fills var_model info for pac_expectation node
virtual void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) = 0;
//! Fills the AR matrix structure
virtual void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const = 0;
//! Fills the EC matrix structure //! Fills the EC matrix structure
virtual void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, void fillErrorCorrectionRow(int eqn, const vector<int>& nontarget_lhs,
map<tuple<int, int, int>, expr_t> &EC) const = 0; const vector<int>& target_lhs, map<tuple<int, int>, expr_t>& A0,
map<tuple<int, int>, expr_t>& A0star) const;
//! Replaces variables found in BinaryOpNode::findConstantEquations() with their constant values
virtual expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const = 0;
//! Returns true if PacExpectationNode encountered //! Returns true if PacExpectationNode encountered
virtual bool containsPacExpectation(const string &pac_model_name = "") const = 0; [[nodiscard]] virtual bool containsPacExpectation(const string& pac_model_name = "") const = 0;
//! Returns true if PacTargetNonstationaryNode encountered
[[nodiscard]] virtual bool containsPacTargetNonstationary(const string& pac_model_name = "") const
= 0;
//! Decompose an expression into its additive terms
/*! Returns a list of terms, with their sign (either 1 or -1, depending
on whether the terms appears with a plus or a minus).
The current_sign argument should normally be left to 1.
If current_sign == -1, then all signs are inverted */
virtual void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign = 1) const;
//! Decompose an expression into its multiplicative factors
/*! Returns a list of factors, with their exponents (either 1 or -1, depending
on whether the factors appear at the numerator or the denominator).
The current_exponent argument should normally be left to 1.
If current_exponent == -1, then all exponents are inverted */
virtual void decomposeMultiplicativeFactors(vector<pair<expr_t, int>>& factors,
int current_exponent = 1) const;
// Matches an expression of the form variable*constant*parameter
/* Returns a tuple (variable_id, lag, param_id, constant).
If `variable_obligatory` is true, then the expression must contain a variable.
If present, the variable must be an exogenous or an endogenous. If absent,
and `variable_obligatory` is false, then variable_id is nullopt.
The constant is optional (in which case 1 is returned); there can be
several multiplicative constants; constants can also appear at the
denominator (i.e. after a divide sign).
The parameter is optional (in which case param_id is nullopt).
If the expression is not of the expected form, throws a
MatchFailureException
*/
[[nodiscard]] tuple<optional<int>, int, optional<int>, double>
matchVariableTimesConstantTimesParam(bool variable_obligatory) const;
/* Matches an expression of the form endogenous*constant where constant is an
expression containing no endogenous, no exogenous and no exogenous deterministic.
Returns (endo_id, constant expr).
Note that it will also match a simple endogenous (in which case the
constant will of course be equal to one). */
[[nodiscard]] virtual pair<int, expr_t> matchEndogenousTimesConstant() const;
//! Exception thrown when matching fails
struct MatchFailureException
{
const string message;
};
//! Fills map /* Match an expression of the form ∏ x(l)ᵏ, where x are endogenous, as used
virtual void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const = 0; in the match_moments block.
For each factor, adds an integer in the 3 vectors in argument (symb_id in
the first, lag in the second, exponent in the third).
Throws a MatchFailureException if not of the right form. */
virtual void matchMatchedMoment(vector<int>& symb_ids, vector<int>& lags,
vector<int>& powers) const;
/* Returns true if the expression contains no endogenous, no exogenous and no
exogenous deterministic */
[[nodiscard]] bool isConstant() const;
// Returns true if the expression contains an exogenous or an exogenous deterministic
[[nodiscard]] bool hasExogenous() const;
// Substitutes orig_symb_id(±l) with exp(aux_symb_id(±l)) (used for “var(log)”)
[[nodiscard]] virtual expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const = 0;
/* Matches an expression that constitutes a complementarity condition.
If successful, returns a triplet (endo_symb_id, lower_bound, upper_bound).
Otherwise, throws a MatchFailureException. */
[[nodiscard]] virtual tuple<int, expr_t, expr_t>
matchComplementarityCondition(const optional<int>& heterogeneity_dimension = nullopt) const;
/* Replaces aggregation operators (e.g. SUM()) by new auxiliary variables.
Also declares those aggregation operators in the HeterogeneityTable, so as to
compute their index in the dedicated vector in argument of the dynamic/static files. */
[[nodiscard]] virtual expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
}; };
//! Object used to compare two nodes (using their indexes) //! Object used to compare two nodes (using their indexes)
...@@ -604,190 +968,238 @@ struct ExprNodeLess ...@@ -604,190 +968,238 @@ struct ExprNodeLess
}; };
//! Numerical constant node //! Numerical constant node
/*! The constant is necessarily non-negative (this is enforced at the NumericalConstants class level) */ /*! The constant is necessarily non-negative (this is enforced at the NumericalConstants class
* level) */
class NumConstNode : public ExprNode class NumConstNode : public ExprNode
{ {
private: public:
//! Id from numerical constants table //! Id from numerical constants table
const int id; const int id;
private:
expr_t computeDerivative(int deriv_id) override; expr_t computeDerivative(int deriv_id) override;
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
protected:
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id, double& constant,
bool at_denominator) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
public: public:
NumConstNode(DataTree& datatree_arg, int idx_arg, int id_arg); NumConstNode(DataTree& datatree_arg, int idx_arg, int id_arg);
int void writeOutput(ostream& output, ExprNodeOutputType output_type,
get_id() const const temporary_terms_t& temporary_terms,
{ const temporary_terms_idxs_t& temporary_terms_idxs,
return id; const deriv_node_temp_terms_t& tef_terms) const override;
};
void prepareForDerivation() override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
bool containsExternalFunction() const override; const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
double eval(const eval_context_t &eval_context) const noexcept(false) override; void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree& static_datatree) const override; expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override; void computeXrefs(EquationInfo& ei) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t>>> &List_of_Op_RHS) const override; BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override; [[nodiscard]] int maxEndoLead() const override;
int maxEndoLead() const override; [[nodiscard]] int maxExoLead() const override;
int maxExoLead() const override; [[nodiscard]] int maxEndoLag() const override;
int maxEndoLag() const override; [[nodiscard]] int maxExoLag() const override;
int maxExoLag() const override; [[nodiscard]] int maxLead() const override;
int maxLead() const override; [[nodiscard]] int maxLag() const override;
int maxLag() const override; [[nodiscard]] int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override; [[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override; [[nodiscard]] expr_t undiff() const override;
int PacMaxLag(int lhs_symb_id) const override; [[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t undiff() const override; expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t decreaseLeadsLags(int n) const override; bool deterministic_model) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override; expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override; expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t substituteAdl() const override; bool partial_information_model) const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override; [[nodiscard]] expr_t substituteAdl() const override;
void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override; [[nodiscard]] expr_t substituteModelLocalVariables() const override;
void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override; [[nodiscard]] expr_t
int findTargetVariable(int lhs_symb_id) const override; substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findDiffNodes(lag_equivalence_table_t& nodes) const override;
expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override; [[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override; expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; vector<BinaryOpNode*>& neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override; expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
bool containsEndogenous() const override; vector<BinaryOpNode*>& neweqs) const override;
bool containsExogenous() const override; expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
int countDiffs() const override; expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override; [[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t replaceTrendVar() const override; expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override; expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override; expr_t clone(DataTree& alt_datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override; [[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
bool isInStaticForm() const override; [[nodiscard]] bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override; expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override; [[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override; [[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override; = "") const override;
bool containsPacExpectation(const string &pac_model_name = "") const override; [[nodiscard]] bool isParamTimesEndogExpr() const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>> [[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
&params_vars_and_scaling_factor) const override; [[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars, vector<BinaryOpNode*>& neweqs) const override;
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
expr_t &optim_part,
expr_t &non_optim_part) const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
expr_t substituteStaticAuxiliaryVariable() const override;
}; };
//! Symbol or variable node //! Symbol or variable node
class VariableNode : public ExprNode class VariableNode : public ExprNode
{ {
friend class UnaryOpNode; friend class UnaryOpNode;
private:
public:
//! Id from the symbol table //! Id from the symbol table
const int symb_id; const int symb_id;
//! A positive value is a lead, a negative is a lag //! A positive value is a lead, a negative is a lag
const int lag; const int lag;
private:
expr_t computeDerivative(int deriv_id) override; expr_t computeDerivative(int deriv_id) override;
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
protected:
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id, double& constant,
bool at_denominator) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
public: public:
VariableNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg, int lag_arg); VariableNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg, int lag_arg);
void prepareForDerivation() override; [[nodiscard]] SymbolType get_type() const;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; [[nodiscard]] string getName() const;
[[nodiscard]] int getDerivID() const;
[[nodiscard]] int getTypeSpecificID() const;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
bool containsExternalFunction() const override; const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void computeTemporaryTerms(map<expr_t, int > &reference_count, [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
temporary_terms_t &temporary_terms, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
map<expr_t, pair<int, int>> &first_occurence, const temporary_terms_t& temporary_terms,
int Curr_block, const temporary_terms_idxs_t& temporary_terms_idxs,
vector< vector<temporary_terms_t>> &v_temporary_terms, const deriv_node_temp_terms_t& tef_terms) const override;
int equation) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree& static_datatree) const override; expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override; void computeXrefs(EquationInfo& ei) const override;
SymbolType get_type() const; BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
int [[nodiscard]] int maxEndoLead() const override;
get_symb_id() const [[nodiscard]] int maxExoLead() const override;
{ [[nodiscard]] int maxEndoLag() const override;
return symb_id; [[nodiscard]] int maxExoLag() const override;
}; [[nodiscard]] int maxLead() const override;
int [[nodiscard]] int maxLag() const override;
get_lag() const [[nodiscard]] int maxLagWithDiffsExpanded() const override;
{ [[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
return lag; [[nodiscard]] expr_t undiff() const override;
}; [[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t>>> &List_of_Op_RHS) const override; expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override; bool deterministic_model) const override;
int maxEndoLead() const override; expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
int maxExoLead() const override; vector<BinaryOpNode*>& neweqs) const override;
int maxEndoLag() const override; expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
int maxExoLag() const override; bool deterministic_model) const override;
int maxLead() const override;
int maxLag() const override;
int VarMinLag() const override;
int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override;
int PacMaxLag(int lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override; expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override; expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t substituteAdl() const override; bool partial_information_model) const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override; [[nodiscard]] expr_t substituteAdl() const override;
void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override; [[nodiscard]] expr_t substituteModelLocalVariables() const override;
void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override; [[nodiscard]] expr_t
int findTargetVariable(int lhs_symb_id) const override; substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findDiffNodes(lag_equivalence_table_t& nodes) const override;
expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override; [[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override; expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; vector<BinaryOpNode*>& neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override; expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
bool containsEndogenous() const override; vector<BinaryOpNode*>& neweqs) const override;
bool containsExogenous() const override; expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
int countDiffs() const override; expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override; [[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t replaceTrendVar() const override; expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override; expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override; expr_t clone(DataTree& alt_datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override; [[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
bool isInStaticForm() const override; [[nodiscard]] bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override; expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override; [[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override; [[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override; = "") const override;
bool containsPacExpectation(const string &pac_model_name = "") const override; [[nodiscard]] bool isParamTimesEndogExpr() const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>> void matchMatchedMoment(vector<int>& symb_ids, vector<int>& lags,
&params_vars_and_scaling_factor) const override; vector<int>& powers) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars, [[nodiscard]] pair<int, expr_t> matchEndogenousTimesConstant() const override;
set<pair<int, pair<int, int>>> &params_and_vars) const override; [[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share, [[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
expr_t &optim_part, vector<BinaryOpNode*>& neweqs) const override;
expr_t &non_optim_part) const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
}; };
//! Unary operator node //! Unary operator node
class UnaryOpNode : public ExprNode class UnaryOpNode : public ExprNode
{ {
private: protected:
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id, double& constant,
bool at_denominator) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
// Returns the node obtained by applying a transformation recursively on the argument (in same
// datatree)
template<typename Callable, typename... Args>
requires invocable<Callable, expr_t, Args...>
expr_t
recurseTransform(Callable&& op, Args&&... args) const
{
expr_t substarg {invoke(forward<Callable>(op), arg, forward<Args>(args)...)};
return buildSimilarUnaryOpNode(substarg, datatree);
}
public:
const expr_t arg; const expr_t arg;
//! Stores the information set. Only used for expectation operator //! Stores the information set. Only used for expectation operator
const int expectation_information_set; const int expectation_information_set;
...@@ -796,22 +1208,40 @@ private: ...@@ -796,22 +1208,40 @@ private:
const UnaryOpcode op_code; const UnaryOpcode op_code;
const string adl_param_name; const string adl_param_name;
const vector<int> adl_lags; const vector<int> adl_lags;
private:
expr_t computeDerivative(int deriv_id) override; expr_t computeDerivative(int deriv_id) override;
int cost(int cost, bool is_matlab) const override; expr_t
int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override; computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
int cost(const map<NodeTreeReference, temporary_terms_t> &temp_terms_map, bool is_matlab) const override; unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
[[nodiscard]] int cost(int cost, bool is_matlab) const override;
[[nodiscard]] int cost(const vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
bool is_matlab) const override;
[[nodiscard]] int cost(const map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab) const override;
//! Returns the derivative of this node if darg is the derivative of the argument //! Returns the derivative of this node if darg is the derivative of the argument
expr_t composeDerivatives(expr_t darg, int deriv_id); expr_t composeDerivatives(expr_t darg, int deriv_id);
public: public:
UnaryOpNode(DataTree &datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg); UnaryOpNode(DataTree& datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg,
void prepareForDerivation() override; int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg,
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, string adl_param_name_arg, vector<int> adl_lags_arg);
map<NodeTreeReference, temporary_terms_t> &temp_terms_map, void computeTemporaryTerms(const pair<int, int>& derivOrder,
bool is_matlab, NodeTreeReference tr) const override; map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
bool is_matlab) const override;
void computeBlockTemporaryTerms(
int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
bool containsExternalFunction() const override; const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type, void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
...@@ -819,124 +1249,147 @@ public: ...@@ -819,124 +1249,147 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout, void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override; bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, ExprNodeBytecodeOutputType output_type,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override; deriv_node_temp_terms_t& tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
static double eval_opcode(UnaryOpcode op_code, double v) noexcept(false); static double eval_opcode(UnaryOpcode op_code, double v) noexcept(false);
double eval(const eval_context_t &eval_context) const noexcept(false) override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
//! Returns operand const temporary_terms_t& temporary_terms,
expr_t const temporary_terms_idxs_t& temporary_terms_idxs,
get_arg() const const deriv_node_temp_terms_t& tef_terms) const override;
{
return (arg);
};
//! Returns op code
UnaryOpcode
get_op_code() const
{
return (op_code);
};
expr_t toStatic(DataTree& static_datatree) const override; expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override; void computeXrefs(EquationInfo& ei) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t>>> &List_of_Op_RHS) const override; BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override; [[nodiscard]] int maxEndoLead() const override;
int maxEndoLead() const override; [[nodiscard]] int maxExoLead() const override;
int maxExoLead() const override; [[nodiscard]] int maxEndoLag() const override;
int maxEndoLag() const override; [[nodiscard]] int maxExoLag() const override;
int maxExoLag() const override; [[nodiscard]] int maxLead() const override;
int maxLead() const override; [[nodiscard]] int maxLag() const override;
int maxLag() const override; [[nodiscard]] int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override; [[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override; [[nodiscard]] expr_t undiff() const override;
int PacMaxLag(int lhs_symb_id) const override; [[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t undiff() const override; expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t decreaseLeadsLags(int n) const override; bool deterministic_model) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; //! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and
//! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and argument //! argument
expr_t buildSimilarUnaryOpNode(expr_t alt_arg, DataTree& alt_datatree) const; expr_t buildSimilarUnaryOpNode(expr_t alt_arg, DataTree& alt_datatree) const;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override; expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override; expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t substituteAdl() const override; bool partial_information_model) const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override; [[nodiscard]] expr_t substituteAdl() const override;
void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override; [[nodiscard]] expr_t substituteModelLocalVariables() const override;
bool createAuxVarForUnaryOpNode() const; [[nodiscard]] expr_t
void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override; substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
int findTargetVariable(int lhs_symb_id) const override; void findDiffNodes(lag_equivalence_table_t& nodes) const override;
expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; [[nodiscard]] bool createAuxVarForUnaryOpNode() const;
expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override; [[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override; expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; vector<BinaryOpNode*>& neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override; expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
bool containsEndogenous() const override; vector<BinaryOpNode*>& neweqs) const override;
bool containsExogenous() const override; expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
int countDiffs() const override; expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override; [[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t replaceTrendVar() const override; expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override; expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override; expr_t clone(DataTree& alt_datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override; [[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
bool isInStaticForm() const override; [[nodiscard]] bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override; expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override; [[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override; [[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override; = "") const override;
bool containsPacExpectation(const string &pac_model_name = "") const override; [[nodiscard]] bool isParamTimesEndogExpr() const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>> void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign) const override;
&params_vars_and_scaling_factor) const override; [[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars, [[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
set<pair<int, pair<int, int>>> &params_and_vars) const override; vector<BinaryOpNode*>& neweqs) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
expr_t &optim_part,
expr_t &non_optim_part) const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
}; };
//! Binary operator node //! Binary operator node
class BinaryOpNode : public ExprNode class BinaryOpNode : public ExprNode
{ {
private: protected:
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id, double& constant,
bool at_denominator) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
public:
const expr_t arg1, arg2; const expr_t arg1, arg2;
const BinaryOpcode op_code; const BinaryOpcode op_code;
const int powerDerivOrder;
const string adlparam;
private:
expr_t computeDerivative(int deriv_id) override; expr_t computeDerivative(int deriv_id) override;
int cost(int cost, bool is_matlab) const override; expr_t
int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override; computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
int cost(const map<NodeTreeReference, temporary_terms_t> &temp_terms_map, bool is_matlab) const override; unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
[[nodiscard]] int cost(int cost, bool is_matlab) const override;
[[nodiscard]] int cost(const vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
bool is_matlab) const override;
[[nodiscard]] int cost(const map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab) const override;
//! Returns the derivative of this node if darg1 and darg2 are the derivatives of the arguments //! Returns the derivative of this node if darg1 and darg2 are the derivatives of the arguments
expr_t composeDerivatives(expr_t darg1, expr_t darg2); expr_t composeDerivatives(expr_t darg1, expr_t darg2);
const int powerDerivOrder; // Returns the node obtained by applying a transformation recursively on the arguments (in same
const string adlparam; // datatree)
template<typename Callable, typename... Args>
requires invocable<Callable, expr_t, Args...>
expr_t
recurseTransform(Callable&& op, Args&&... args) const
{
expr_t substarg1 {invoke(forward<Callable>(op), arg1, forward<Args>(args)...)};
expr_t substarg2 {invoke(forward<Callable>(op), arg2, forward<Args>(args)...)};
return buildSimilarBinaryOpNode(substarg1, substarg2, datatree);
}
public: public:
BinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg, BinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg, BinaryOpcode op_code_arg,
BinaryOpcode op_code_arg, const expr_t arg2_arg, int powerDerivOrder); const expr_t arg2_arg, int powerDerivOrder);
void prepareForDerivation() override; [[nodiscard]] int precedenceJson(const temporary_terms_t& temporary_terms) const override;
int precedenceJson(const temporary_terms_t &temporary_terms) const override; [[nodiscard]] int precedence(ExprNodeOutputType output_type,
int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override; const temporary_terms_t& temporary_terms) const override;
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, void computeTemporaryTerms(const pair<int, int>& derivOrder,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map, map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab, NodeTreeReference tr) const override; unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; bool is_matlab) const override;
void computeBlockTemporaryTerms(
int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
bool containsExternalFunction() const override; const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type, void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
...@@ -944,156 +1397,198 @@ public: ...@@ -944,156 +1397,198 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout, void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override; bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, ExprNodeBytecodeOutputType output_type,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override; deriv_node_temp_terms_t& tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override; static double eval_opcode(double v1, BinaryOpcode op_code, double v2,
static double eval_opcode(double v1, BinaryOpcode op_code, double v2, int derivOrder) noexcept(false); int derivOrder) noexcept(false);
double eval(const eval_context_t &eval_context) const noexcept(false) override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
virtual expr_t Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const; const temporary_terms_t& temporary_terms,
//! Returns first operand const temporary_terms_idxs_t& temporary_terms_idxs,
expr_t const deriv_node_temp_terms_t& tef_terms) const override;
get_arg1() const expr_t Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const;
{
return (arg1);
};
//! Returns second operand
expr_t
get_arg2() const
{
return (arg2);
};
//! Returns op code
BinaryOpcode
get_op_code() const
{
return (op_code);
};
int
get_power_deriv_order() const
{
return powerDerivOrder;
}
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacNonOptimizingPartHelper(const expr_t arg1, const expr_t arg2,
set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const;
void getPacOptimizingPartHelper(const expr_t arg1, const expr_t arg2,
int lhs_orig_symb_id,
pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &ar_params_and_vars) const;
void getPacLHS(pair<int, int> &lhs);
expr_t toStatic(DataTree& static_datatree) const override; expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override; void computeXrefs(EquationInfo& ei) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t>>> &List_of_Op_RHS) const override; BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override; //! Try to normalize an equation with respect to a given dynamic variable.
int maxEndoLead() const override; /*! Should only be called on Equal nodes. The variable must appear in the equation. */
int maxExoLead() const override; [[nodiscard]] BinaryOpNode* normalizeEquation(int symb_id, int lag) const;
int maxEndoLag() const override; [[nodiscard]] int maxEndoLead() const override;
int maxExoLag() const override; [[nodiscard]] int maxExoLead() const override;
int maxLead() const override; [[nodiscard]] int maxEndoLag() const override;
int maxLag() const override; [[nodiscard]] int maxExoLag() const override;
int VarMinLag() const override; [[nodiscard]] int maxLead() const override;
int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override; [[nodiscard]] int maxLag() const override;
int PacMaxLag(int lhs_symb_id) const override; [[nodiscard]] int maxLagWithDiffsExpanded() const override;
expr_t undiff() const override; [[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
expr_t decreaseLeadsLags(int n) const override; [[nodiscard]] expr_t undiff() const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; [[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
//! Creates another BinaryOpNode with the same opcode, but with a possibly different datatree and arguments expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
//! Creates another BinaryOpNode with the same opcode, but with a possibly different datatree and
//! arguments
expr_t buildSimilarBinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, DataTree& alt_datatree) const; expr_t buildSimilarBinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, DataTree& alt_datatree) const;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override; expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override; expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t substituteAdl() const override; bool partial_information_model) const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override; [[nodiscard]] expr_t substituteAdl() const override;
void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override; [[nodiscard]] expr_t substituteModelLocalVariables() const override;
void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override; [[nodiscard]] expr_t
bool findTargetVariableHelper1(int lhs_symb_id, int rhs_symb_id) const; substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
int findTargetVariableHelper(const expr_t arg1, const expr_t arg2, int lhs_symb_id) const; void findDiffNodes(lag_equivalence_table_t& nodes) const override;
int findTargetVariable(int lhs_symb_id) const override; void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; [[nodiscard]] bool findTargetVariableHelper1(int lhs_symb_id, int rhs_symb_id) const;
expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; optional<int> findTargetVariableHelper(const expr_t arg1, const expr_t arg2,
expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override; int lhs_symb_id) const;
expr_t decreaseLeadsLagsPredeterminedVariables() const override; [[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
bool isNumConstNodeEqualTo(double value) const override; vector<BinaryOpNode*>& neweqs) const override;
bool containsEndogenous() const override; expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
bool containsExogenous() const override; vector<BinaryOpNode*>& neweqs) const override;
int countDiffs() const override; expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override; expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
expr_t replaceTrendVar() const override; [[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override; expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override; expr_t clone(DataTree& alt_datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override; [[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
//! Function to write out the oPowerNode in expr_t terms as opposed to writing out the function itself //! Function to write out the oPowerNode in expr_t terms as opposed to writing out the function
expr_t unpackPowerDeriv() const; //! itself
[[nodiscard]] expr_t unpackPowerDeriv() const;
//! Returns MULT_i*(lhs-rhs) = 0, creating multiplier MULT_i //! Returns MULT_i*(lhs-rhs) = 0, creating multiplier MULT_i
expr_t addMultipliersToConstraints(int i); expr_t addMultipliersToConstraints(int i);
//! Returns the non-zero hand-side of an equation (that must have a hand side equal to zero) //! Returns the non-zero hand side of an equation (that must have a hand side equal to zero)
expr_t getNonZeroPartofEquation() const; [[nodiscard]] expr_t getNonZeroPartofEquation() const;
bool isInStaticForm() const override; [[nodiscard]] bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override; void fillAutoregressiveRow(int eqn, const vector<int>& lhs,
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
void fillAutoregressiveRowHelper(expr_t arg1, expr_t arg2,
int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
void fillErrorCorrectionRowHelper(expr_t arg1, expr_t arg2,
int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs,
map<tuple<int, int, int>, expr_t>& AR) const; map<tuple<int, int, int>, expr_t>& AR) const;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override; //! Finds equations where a variable is equal to a constant
bool containsPacExpectation(const string &pac_model_name = "") const override; void findConstantEquations(map<VariableNode*, NumConstNode*>& table) const;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars, expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
set<pair<int, pair<int, int>>> &params_and_vars) const override; [[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share, [[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
expr_t &optim_part, = "") const override;
expr_t &non_optim_part) const override; /*
bool isParamTimesEndogExpr() const override; ec_params_and_vars:
bool isVarModelReferenced(const string &model_info_name) const override; - 1st element = feedback force parameter
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override; - 2nd element = list of terms in the cointegration relationship (symb_id,
//! Substitute auxiliary variables by their expression in static model is target ?, multiplicative scalar); this form theoretically allows for a
expr_t substituteStaticAuxiliaryVariable() const override; linear combination in the cointegration, though for the time being we allow
//! Substitute auxiliary variables by their expression in static model auxiliary variable definition less than that
virtual expr_t substituteStaticAuxiliaryDefinition() const; ar_params_and_vars: elements are indexed according to lag (index 0 is lag
1); each tuple is (parameter_id, variable_id, variable_lag) where
variable_lag is *not* the lag order in the AR
(because variable is an AUX_DIFF_LAG)
*/
void getPacAREC(
int lhs_symb_id, int lhs_orig_symb_id,
pair<int, vector<tuple<int, bool, int>>>& ec_params_and_vars,
vector<tuple<optional<int>, optional<int>, int>>& ar_params_and_vars,
vector<tuple<int, int, optional<int>, double>>& additive_vars_params_and_constants) const;
//! Finds the share of optimizing agents in the PAC equation,
//! the expr node associated with it,
//! and the expr node associated with the non-optimizing part
[[nodiscard]] tuple<optional<int>, expr_t, expr_t, expr_t>
getPacOptimizingShareAndExprNodes(int lhs_orig_symb_id) const;
[[nodiscard]] pair<optional<int>, expr_t>
getPacOptimizingShareAndExprNodesHelper(int lhs_orig_symb_id) const;
[[nodiscard]] expr_t getPacNonOptimizingPart(int optim_share_symb_id) const;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign) const override;
void decomposeMultiplicativeFactors(vector<pair<expr_t, int>>& factors,
int current_exponent = 1) const override;
void matchMatchedMoment(vector<int>& symb_ids, vector<int>& lags,
vector<int>& powers) const override;
[[nodiscard]] pair<int, expr_t> matchEndogenousTimesConstant() const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
[[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] tuple<int, expr_t, expr_t>
matchComplementarityCondition(const optional<int>& heterogeneity_dimension
= nullopt) const override;
}; };
//! Trinary operator node //! Trinary operator node
class TrinaryOpNode : public ExprNode class TrinaryOpNode : public ExprNode
{ {
friend class ModelTree; friend class ModelTree;
private:
public:
const expr_t arg1, arg2, arg3; const expr_t arg1, arg2, arg3;
const TrinaryOpcode op_code; const TrinaryOpcode op_code;
protected:
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
private:
expr_t computeDerivative(int deriv_id) override; expr_t computeDerivative(int deriv_id) override;
int cost(int cost, bool is_matlab) const override; expr_t
int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override; computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
int cost(const map<NodeTreeReference, temporary_terms_t> &temp_terms_map, bool is_matlab) const override; unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
//! Returns the derivative of this node if darg1, darg2 and darg3 are the derivatives of the arguments unordered_map<expr_t, map<int, expr_t>>& cache) override;
[[nodiscard]] int cost(int cost, bool is_matlab) const override;
[[nodiscard]] int cost(const vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
bool is_matlab) const override;
[[nodiscard]] int cost(const map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab) const override;
//! Returns the derivative of this node if darg1, darg2 and darg3 are the derivatives of the
//! arguments
expr_t composeDerivatives(expr_t darg1, expr_t darg2, expr_t darg3); expr_t composeDerivatives(expr_t darg1, expr_t darg2, expr_t darg3);
// Returns the node obtained by applying a transformation recursively on the arguments (in same
// datatree)
template<typename Callable, typename... Args>
requires invocable<Callable, expr_t, Args...>
expr_t
recurseTransform(Callable&& op, Args&&... args) const
{
expr_t substarg1 {invoke(forward<Callable>(op), arg1, forward<Args>(args)...)};
expr_t substarg2 {invoke(forward<Callable>(op), arg2, forward<Args>(args)...)};
expr_t substarg3 {invoke(forward<Callable>(op), arg3, forward<Args>(args)...)};
return buildSimilarTrinaryOpNode(substarg1, substarg2, substarg3, datatree);
}
public: public:
TrinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg, TrinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg,
TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg); TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg);
void prepareForDerivation() override; [[nodiscard]] int precedence(ExprNodeOutputType output_type,
int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override; const temporary_terms_t& temporary_terms) const override;
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, void computeTemporaryTerms(const pair<int, int>& derivOrder,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map, map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab, NodeTreeReference tr) const override; unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; bool is_matlab) const override;
void computeBlockTemporaryTerms(
int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
bool containsExternalFunction() const override; const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type, void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
...@@ -1101,223 +1596,278 @@ public: ...@@ -1101,223 +1596,278 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout, void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override; bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, ExprNodeBytecodeOutputType output_type,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override; deriv_node_temp_terms_t& tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
static double eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) noexcept(false); static double eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) noexcept(false);
double eval(const eval_context_t &eval_context) const noexcept(false) override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree& static_datatree) const override; expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override; void computeXrefs(EquationInfo& ei) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t>>> &List_of_Op_RHS) const override; BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override; [[nodiscard]] int maxEndoLead() const override;
int maxEndoLead() const override; [[nodiscard]] int maxExoLead() const override;
int maxExoLead() const override; [[nodiscard]] int maxEndoLag() const override;
int maxEndoLag() const override; [[nodiscard]] int maxExoLag() const override;
int maxExoLag() const override; [[nodiscard]] int maxLead() const override;
int maxLead() const override; [[nodiscard]] int maxLag() const override;
int maxLag() const override; [[nodiscard]] int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override; [[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override; [[nodiscard]] expr_t undiff() const override;
int PacMaxLag(int lhs_symb_id) const override; [[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t undiff() const override; expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t decreaseLeadsLags(int n) const override; bool deterministic_model) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; //! Creates another TrinaryOpNode with the same opcode, but with a possibly different datatree and
//! Creates another TrinaryOpNode with the same opcode, but with a possibly different datatree and arguments //! arguments
expr_t buildSimilarTrinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, expr_t alt_arg3, DataTree &alt_datatree) const; expr_t buildSimilarTrinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, expr_t alt_arg3,
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; DataTree& alt_datatree) const;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override; expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override; expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t substituteAdl() const override; bool partial_information_model) const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override; [[nodiscard]] expr_t substituteAdl() const override;
void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override; [[nodiscard]] expr_t substituteModelLocalVariables() const override;
void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override; [[nodiscard]] expr_t
int findTargetVariable(int lhs_symb_id) const override; substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findDiffNodes(lag_equivalence_table_t& nodes) const override;
expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override; [[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override; expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; vector<BinaryOpNode*>& neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override; expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
bool containsEndogenous() const override; vector<BinaryOpNode*>& neweqs) const override;
bool containsExogenous() const override; expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
int countDiffs() const override; expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override; [[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t replaceTrendVar() const override; expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override; expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override; expr_t clone(DataTree& alt_datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override; [[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
bool isInStaticForm() const override; [[nodiscard]] bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override; expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override; [[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override; [[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override; = "") const override;
bool containsPacExpectation(const string &pac_model_name = "") const override; [[nodiscard]] bool isParamTimesEndogExpr() const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>> [[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
&params_vars_and_scaling_factor) const override; vector<BinaryOpNode*>& neweqs) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars, [[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
expr_t &optim_part,
expr_t &non_optim_part) const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
}; };
//! External function node //! External function node
class AbstractExternalFunctionNode : public ExprNode class AbstractExternalFunctionNode : public ExprNode
{ {
public:
const int symb_id;
const vector<expr_t> arguments;
private: private:
expr_t computeDerivative(int deriv_id) override; expr_t computeDerivative(int deriv_id) override;
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
virtual expr_t composeDerivatives(const vector<expr_t>& dargs) = 0; virtual expr_t composeDerivatives(const vector<expr_t>& dargs) = 0;
// Computes the maximum of f applied to all arguments (result will always be non-negative)
int maxHelper(const function<int(expr_t)>& f) const;
// Returns the node obtained by applying a transformation recursively on the arguments (in same
// datatree)
template<typename Callable, typename... Args>
requires invocable<Callable, expr_t, Args...>
expr_t
recurseTransform(Callable&& op, Args&&... args) const
{
vector<expr_t> arguments_subst;
for (auto argument : arguments)
arguments_subst.push_back(invoke(forward<Callable>(op), argument, forward<Args>(args)...));
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
}
protected: protected:
//! Thrown when trying to access an unknown entry in external_function_node_map //! Thrown when trying to access an unknown entry in external_function_node_map
class UnknownFunctionNameAndArgs class UnknownFunctionNameAndArgs
{ {
}; };
const int symb_id; void prepareForDerivation() override;
const vector<expr_t> arguments; void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
//! Returns true if the given external function has been written as a temporary term //! Returns true if the given external function has been written as a temporary term
bool alreadyWrittenAsTefTerm(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const; [[nodiscard]] bool alreadyWrittenAsTefTerm(int the_symb_id,
const deriv_node_temp_terms_t& tef_terms) const;
//! Returns the index in the tef_terms map of this external function //! Returns the index in the tef_terms map of this external function
int getIndxInTefTerms(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const noexcept(false); [[nodiscard]] int getIndxInTefTerms(int the_symb_id,
const deriv_node_temp_terms_t& tef_terms) const
noexcept(false);
//! Helper function to write output arguments of any given external function //! Helper function to write output arguments of any given external function
void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const; void writeExternalFunctionArguments(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const;
void writeJsonASTExternalFunctionArguments(ostream& output) const; void writeJsonASTExternalFunctionArguments(ostream& output) const;
void writeJsonExternalFunctionArguments(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const; void writeJsonExternalFunctionArguments(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms,
bool isdynamic) const;
void writeBytecodeExternalFunctionArguments(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const;
/*! Returns a predicate that tests whether an other ExprNode is an external /*! Returns a predicate that tests whether an other ExprNode is an external
function which is computed by the same external function call (i.e. it has function which is computed by the same external function call (i.e. it has
the same so-called "Tef" index) */ the same so-called "Tef" index) */
virtual function<bool (expr_t)> sameTefTermPredicate() const = 0; [[nodiscard]] virtual function<bool(expr_t)> sameTefTermPredicate() const = 0;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
public: public:
AbstractExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg, AbstractExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg,
vector<expr_t> arguments_arg); vector<expr_t> arguments_arg);
void prepareForDerivation() override; [[nodiscard]] string getName() const;
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, void computeTemporaryTerms(const pair<int, int>& derivOrder,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map, map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab, NodeTreeReference tr) const override; unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override = 0; bool is_matlab) const override;
void computeBlockTemporaryTerms(
int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override
= 0;
void writeJsonAST(ostream& output) const override = 0; void writeJsonAST(ostream& output) const override = 0;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const override = 0; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
bool containsExternalFunction() const override; const deriv_node_temp_terms_t& tef_terms,
bool isdynamic = true) const override
= 0;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type, void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const override = 0; deriv_node_temp_terms_t& tef_terms) const override
= 0;
void writeJsonExternalFunctionOutput(vector<string>& efout, void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
const bool isdynamic = true) const override = 0; bool isdynamic = true) const override
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, = 0;
bool lhs_rhs, const temporary_terms_t &temporary_terms, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, ExprNodeBytecodeOutputType output_type,
deriv_node_temp_terms_t &tef_terms) const override = 0; const temporary_terms_t& temporary_terms,
void computeTemporaryTerms(map<expr_t, int> &reference_count, const temporary_terms_idxs_t& temporary_terms_idxs,
temporary_terms_t &temporary_terms, deriv_node_temp_terms_t& tef_terms) const override
map<expr_t, pair<int, int>> &first_occurence, = 0;
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override = 0;
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
double eval(const eval_context_t &eval_context) const noexcept(false) override; void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
unsigned int compileExternalFunctionArguments(ostream &CompileCode, unsigned int &instruction_number, const temporary_terms_t& temporary_terms,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t& tef_terms) const override
const deriv_node_temp_terms_t &tef_terms) const; = 0;
expr_t toStatic(DataTree& static_datatree) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override = 0;
expr_t toStatic(DataTree &static_datatree) const override = 0;
void computeXrefs(EquationInfo& ei) const override = 0; void computeXrefs(EquationInfo& ei) const override = 0;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t>>> &List_of_Op_RHS) const override; BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override; [[nodiscard]] int maxEndoLead() const override;
int maxEndoLead() const override; [[nodiscard]] int maxExoLead() const override;
int maxExoLead() const override; [[nodiscard]] int maxEndoLag() const override;
int maxEndoLag() const override; [[nodiscard]] int maxExoLag() const override;
int maxExoLag() const override; [[nodiscard]] int maxLead() const override;
int maxLead() const override; [[nodiscard]] int maxLag() const override;
int maxLag() const override; [[nodiscard]] int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override; [[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override; [[nodiscard]] expr_t undiff() const override;
int PacMaxLag(int lhs_symb_id) const override; [[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t undiff() const override; expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t decreaseLeadsLags(int n) const override; bool deterministic_model) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override; expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override; expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
expr_t substituteAdl() const override; bool partial_information_model) const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override; [[nodiscard]] expr_t substituteAdl() const override;
void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override; [[nodiscard]] expr_t substituteModelLocalVariables() const override;
void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override; [[nodiscard]] expr_t
int findTargetVariable(int lhs_symb_id) const override; substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findDiffNodes(lag_equivalence_table_t& nodes) const override;
expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override; [[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const = 0; expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
expr_t decreaseLeadsLagsPredeterminedVariables() const override; vector<BinaryOpNode*>& neweqs) const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
bool isNumConstNodeEqualTo(double value) const override; vector<BinaryOpNode*>& neweqs) const override;
bool containsEndogenous() const override; expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
bool containsExogenous() const override; expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
int countDiffs() const override; virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override; DataTree& alt_datatree) const
virtual void writePrhs(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms, const string &ending) const; = 0;
expr_t replaceTrendVar() const override; [[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
void writePrhs(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override; expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override = 0; expr_t clone(DataTree& alt_datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override; [[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
bool isInStaticForm() const override; [[nodiscard]] bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override; expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override; [[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override; [[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override; = "") const override;
bool containsPacExpectation(const string &pac_model_name = "") const override; [[nodiscard]] bool isParamTimesEndogExpr() const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>> [[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
&params_vars_and_scaling_factor) const override; [[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars, vector<BinaryOpNode*>& neweqs) const override;
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
expr_t &optim_part,
expr_t &non_optim_part) const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
}; };
class ExternalFunctionNode : public AbstractExternalFunctionNode class ExternalFunctionNode : public AbstractExternalFunctionNode
{ {
friend class FirstDerivExternalFunctionNode; friend class FirstDerivExternalFunctionNode;
friend class SecondDerivExternalFunctionNode; friend class SecondDerivExternalFunctionNode;
private: private:
expr_t composeDerivatives(const vector<expr_t>& dargs) override; expr_t composeDerivatives(const vector<expr_t>& dargs) override;
protected: protected:
function<bool (expr_t)> sameTefTermPredicate() const override; [[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
public: public:
ExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg, ExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg,
const vector<expr_t>& arguments_arg); const vector<expr_t>& arguments_arg);
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type, void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
...@@ -1325,48 +1875,45 @@ public: ...@@ -1325,48 +1875,45 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout, void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override; bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, ExprNodeBytecodeOutputType output_type,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override; deriv_node_temp_terms_t& tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
temporary_terms_t &temporary_terms, const temporary_terms_t& temporary_terms,
map<expr_t, pair<int, int>> &first_occurence, const temporary_terms_idxs_t& temporary_terms_idxs,
int Curr_block, const deriv_node_temp_terms_t& tef_terms) const override;
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override; void computeXrefs(EquationInfo& ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override; expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
expr_t clone(DataTree &datatree) const override; DataTree& alt_datatree) const override;
}; };
class FirstDerivExternalFunctionNode : public AbstractExternalFunctionNode class FirstDerivExternalFunctionNode : public AbstractExternalFunctionNode
{ {
private: public:
const int inputIndex; const int inputIndex;
private:
expr_t composeDerivatives(const vector<expr_t>& dargs) override; expr_t composeDerivatives(const vector<expr_t>& dargs) override;
protected: protected:
function<bool (expr_t)> sameTefTermPredicate() const override; [[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
public: public:
FirstDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg, FirstDerivExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int top_level_symb_id_arg,
int top_level_symb_id_arg, const vector<expr_t>& arguments_arg, int inputIndex_arg);
const vector<expr_t> &arguments_arg, void writeOutput(ostream& output, ExprNodeOutputType output_type,
int inputIndex_arg); const temporary_terms_t& temporary_terms,
void computeTemporaryTerms(map<expr_t, int> &reference_count, const temporary_terms_idxs_t& temporary_terms_idxs,
temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t& tef_terms) const override;
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
void compile(ostream &CompileCode, unsigned int &instruction_number, const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
bool lhs_rhs, const temporary_terms_t &temporary_terms, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type, void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
...@@ -1375,43 +1922,43 @@ public: ...@@ -1375,43 +1922,43 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout, void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override; bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, ExprNodeBytecodeOutputType output_type,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override; deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override; void computeXrefs(EquationInfo& ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override; expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
expr_t clone(DataTree &datatree) const override; DataTree& alt_datatree) const override;
}; };
class SecondDerivExternalFunctionNode : public AbstractExternalFunctionNode class SecondDerivExternalFunctionNode : public AbstractExternalFunctionNode
{ {
private: public:
const int inputIndex1; const int inputIndex1;
const int inputIndex2; const int inputIndex2;
private:
expr_t composeDerivatives(const vector<expr_t>& dargs) override; expr_t composeDerivatives(const vector<expr_t>& dargs) override;
protected: protected:
function<bool (expr_t)> sameTefTermPredicate() const override; [[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
public: public:
SecondDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg, SecondDerivExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int top_level_symb_id_arg,
int top_level_symb_id_arg, const vector<expr_t>& arguments_arg, int inputIndex1_arg,
const vector<expr_t> &arguments_arg,
int inputIndex1_arg,
int inputIndex2_arg); int inputIndex2_arg);
void computeTemporaryTerms(map<expr_t, int> &reference_count, void writeOutput(ostream& output, ExprNodeOutputType output_type,
temporary_terms_t &temporary_terms, const temporary_terms_t& temporary_terms,
map<expr_t, pair<int, int>> &first_occurence, const temporary_terms_idxs_t& temporary_terms_idxs,
int Curr_block, const deriv_node_temp_terms_t& tef_terms) const override;
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
void compile(ostream &CompileCode, unsigned int &instruction_number, const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
bool lhs_rhs, const temporary_terms_t &temporary_terms, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type, void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
...@@ -1420,201 +1967,168 @@ public: ...@@ -1420,201 +1967,168 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout, void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override; bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, ExprNodeBytecodeOutputType output_type,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override; deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override; void computeXrefs(EquationInfo& ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override; expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
expr_t clone(DataTree &datatree) const override; DataTree& alt_datatree) const override;
}; };
class VarExpectationNode : public ExprNode /* Common superclass for nodes that have the following two characteristics:
– they take a submodel name as an argument
– they will be substituted out in the middle of the transform pass
*/
class SubModelNode : public ExprNode
{ {
private:
const string model_name;
public: public:
VarExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name_arg); const string model_name;
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, SubModelNode(DataTree& datatree_arg, int idx_arg, string model_name_arg);
map<NodeTreeReference, temporary_terms_t> &temp_terms_map, void computeTemporaryTerms(const pair<int, int>& derivOrder,
bool is_matlab, NodeTreeReference tr) const override; map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
void computeTemporaryTerms(map<expr_t, int> &reference_count, bool is_matlab) const override;
temporary_terms_t &temporary_terms, void computeBlockTemporaryTerms(
map<expr_t, pair<int, int>> &first_occurence, int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
int Curr_block, unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
expr_t toStatic(DataTree& static_datatree) const override; expr_t toStatic(DataTree& static_datatree) const override;
expr_t clone(DataTree &datatree) const override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int VarMinLag() const override;
int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override;
int PacMaxLag(int lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
void prepareForDerivation() override;
expr_t computeDerivative(int deriv_id) override; expr_t computeDerivative(int deriv_id) override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override; [[nodiscard]] int maxEndoLead() const override;
bool containsExternalFunction() const override; [[nodiscard]] int maxExoLead() const override;
double eval(const eval_context_t &eval_context) const noexcept(false) override; [[nodiscard]] int maxEndoLag() const override;
void computeXrefs(EquationInfo &ei) const override; [[nodiscard]] int maxExoLag() const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; [[nodiscard]] int maxLead() const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; [[nodiscard]] int maxLag() const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override; [[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
[[nodiscard]] expr_t undiff() const override;
[[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
[[nodiscard]] int countDiffs() const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override; expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override; [[nodiscard]] bool containsExternalFunction() const override;
expr_t substituteAdl() const override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override; void computeXrefs(EquationInfo& ei) const override;
void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override; expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override; bool partial_information_model) const override;
int findTargetVariable(int lhs_symb_id) const override; [[nodiscard]] expr_t substituteAdl() const override;
expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; [[nodiscard]] expr_t substituteModelLocalVariables() const override;
expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; void findDiffNodes(lag_equivalence_table_t& nodes) const override;
expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override; void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t>>> &List_of_Op_RHS) const override; [[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number, expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
bool lhs_rhs, const temporary_terms_t &temporary_terms, vector<BinaryOpNode*>& neweqs) const override;
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
bool containsEndogenous() const override; [[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
bool containsExogenous() const override; [[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int countDiffs() const override; int lag_arg) const override;
bool isNumConstNodeEqualTo(double value) const override; [[nodiscard]] bool isInStaticForm() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override; [[nodiscard]] bool isParamTimesEndogExpr() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override; expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
expr_t replaceTrendVar() const override; vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override; expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override; [[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
bool isInStaticForm() const override; [[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override; [[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override; vector<BinaryOpNode*>& neweqs) const override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override; protected:
bool containsPacExpectation(const string &pac_model_name = "") const override; void prepareForDerivation() override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>> void prepareForChainRuleDerivation(
&params_vars_and_scaling_factor) const override; const map<int, BinaryOpNode*>& recursive_variables,
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars, unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
set<pair<int, pair<int, int>>> &params_and_vars) const override; void computeSubExprContainingVariable(int symb_id, int lag,
void getPacOptimizingShareAndExprNodes(set<int> &optim_share, set<expr_t>& contain_var) const override;
expr_t &optim_part,
expr_t &non_optim_part) const override; private:
bool isParamTimesEndogExpr() const override; expr_t
bool isVarModelReferenced(const string &model_info_name) const override; computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override; unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
expr_t substituteStaticAuxiliaryVariable() const override; unordered_map<expr_t, map<int, expr_t>>& cache) override;
};
class VarExpectationNode : public SubModelNode
{
public:
VarExpectationNode(DataTree& datatree_arg, int idx_arg, string model_name_arg);
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
}; };
class PacExpectationNode : public ExprNode class PacExpectationNode : public SubModelNode
{ {
private:
const string model_name;
string var_model_name;
int growth_symb_id;
bool stationary_vars_present, nonstationary_vars_present;
vector<int> lhs;
pair<int, int> lhs_pac_var;
int max_lag, pac_max_lag;
vector<int> h0_indices, h1_indices;
int growth_param_index, equation_number;
int optim_share_index;
pair<int, pair<vector<int>, vector<bool>>> ec_params_and_vars;
set<pair<int, pair<int, int>>> ar_params_and_vars;
set<pair<int, pair<pair<int, int>, double>>> params_vars_and_scaling_factor;
public: public:
PacExpectationNode(DataTree& datatree_arg, int idx_arg, string model_name); PacExpectationNode(DataTree& datatree_arg, int idx_arg, string model_name);
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, void writeOutput(ostream& output, ExprNodeOutputType output_type,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map, const temporary_terms_t& temporary_terms,
bool is_matlab, NodeTreeReference tr) const override; const temporary_terms_idxs_t& temporary_terms_idxs,
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
expr_t toStatic(DataTree &static_datatree) const override;
expr_t clone(DataTree &datatree) const override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int VarMinLag() const override;
int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override;
int PacMaxLag(int lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
void prepareForDerivation() override;
expr_t computeDerivative(int deriv_id) override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
bool containsExternalFunction() const override;
double eval(const eval_context_t &eval_context) const noexcept(false) override;
void computeXrefs(EquationInfo &ei) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
expr_t substituteAdl() const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override;
void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override;
int findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t>>> &List_of_Op_RHS) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override; expr_t clone(DataTree& alt_datatree) const override;
void collectVARLHSVariable(set<expr_t> &result) const override; [[nodiscard]] int maxLagWithDiffsExpanded() const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override; [[nodiscard]] expr_t
bool containsEndogenous() const override; substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
bool containsExogenous() const override; expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
int countDiffs() const override; expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
bool isNumConstNodeEqualTo(double value) const override; [[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; [[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
expr_t decreaseLeadsLagsPredeterminedVariables() const override; = "") const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override; void writeJsonAST(ostream& output) const override;
expr_t replaceTrendVar() const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override; const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override; };
bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override; class PacTargetNonstationaryNode : public SubModelNode
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override; {
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override; public:
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override; PacTargetNonstationaryNode(DataTree& datatree_arg, int idx_arg, string model_name);
bool containsPacExpectation(const string &pac_model_name = "") const override; void writeOutput(ostream& output, ExprNodeOutputType output_type,
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>> const temporary_terms_t& temporary_terms,
&params_vars_and_scaling_factor) const override; const temporary_terms_idxs_t& temporary_terms_idxs,
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars, const deriv_node_temp_terms_t& tef_terms) const override;
set<pair<int, pair<int, int>>> &params_and_vars) const override; expr_t clone(DataTree& alt_datatree) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share, [[nodiscard]] int maxLagWithDiffsExpanded() const override;
expr_t &optim_part, [[nodiscard]] expr_t
expr_t &non_optim_part) const override; substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
bool isParamTimesEndogExpr() const override; expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
bool isVarModelReferenced(const string &model_info_name) const override; expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override; [[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
expr_t substituteStaticAuxiliaryVariable() const override; [[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
}; };
#endif #endif
/* /*
* Copyright (C) 2014-2017 Dynare Team * Copyright © 2014-2023 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -14,27 +14,26 @@ ...@@ -14,27 +14,26 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _EXTENDED_PREPROCESSOR_TYPES_HH #ifndef EXTENDED_PREPROCESSOR_TYPES_HH
#define _EXTENDED_PREPROCESSOR_TYPES_HH #define EXTENDED_PREPROCESSOR_TYPES_HH
enum class FileOutputType // Values for the “output” option
enum class OutputType
{ {
none, // outputs files for Matlab/Octave processing standard, // Default value, infer the derivation order from .mod file only
dynamic, // outputs <fname>_dynamic.* and related files first, // Output only 1st dynamic derivatives with no other computations
first, // outputs <fname>_first_derivatives.* and related files second, // Output at least 2nd dynamic derivatives
second, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.* and related files third, // Output at least 3rd dynamic derivatives
third, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.*, <fname>_third_derivatives.* and related files
}; };
// Values for the “language” option
enum class LanguageOutputType enum class LanguageOutputType
{ {
matlab, // outputs files for Matlab/Octave processing matlab, // outputs files for MATLAB/Octave processing
cuda, // outputs files for CUDA (not yet implemented)
julia, // outputs files for Julia julia, // outputs files for Julia
python, // outputs files for Python (not yet implemented) (not yet implemented)
}; };
enum class JsonFileOutputType enum class JsonFileOutputType
...@@ -43,6 +42,7 @@ enum class JsonFileOutputType ...@@ -43,6 +42,7 @@ enum class JsonFileOutputType
standardout, // output JSON files to stdout standardout, // output JSON files to stdout
}; };
// Values for the “json” option
enum class JsonOutputPointType enum class JsonOutputPointType
{ {
nojson, // don't output JSON nojson, // don't output JSON
...@@ -51,4 +51,5 @@ enum class JsonOutputPointType ...@@ -51,4 +51,5 @@ enum class JsonOutputPointType
transformpass, // output JSON after the transform pass transformpass, // output JSON after the transform pass
computingpass // output JSON after the computing pass computingpass // output JSON after the computing pass
}; };
#endif #endif
/* /*
* Copyright (C) 2010-2015 Dynare Team * Copyright © 2010-2015 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -14,23 +14,20 @@ ...@@ -14,23 +14,20 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <cstdlib>
#include <cassert> #include <cassert>
#include <cerrno>
#include <cmath> #include <cmath>
#include <cstdlib>
#include <iostream> #include <iostream>
#include "ExternalFunctionsTable.hh" #include "ExternalFunctionsTable.hh"
#include "SymbolTable.hh" #include "SymbolTable.hh"
ExternalFunctionsTable::ExternalFunctionsTable()
= default;
void 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(symb_id >= 0);
assert(external_function_options_arg.nargs > 0); assert(external_function_options_arg.nargs > 0);
...@@ -67,11 +64,14 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function ...@@ -67,11 +64,14 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function
if (external_function_options_chng.secondDerivSymbID != IDNotSet if (external_function_options_chng.secondDerivSymbID != IDNotSet
&& external_function_options_chng.firstDerivSymbID == 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); 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 != symb_id
&& external_function_options_chng.firstDerivSymbID != IDNotSet) && external_function_options_chng.firstDerivSymbID != IDNotSet)
{ {
...@@ -84,29 +84,40 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function ...@@ -84,29 +84,40 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function
if (exists(symb_id)) if (exists(symb_id))
{ {
bool ok_to_overwrite = false; 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; 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 { // 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)) if (external_function_options_chng.nargs != getNargs(symb_id))
{ {
cerr << "ERROR: The number of arguments passed to the external_function() statement do not " cerr << "ERROR: The number of arguments passed to the external_function() statement "
<< "match the number of arguments passed to a previous call or declaration of the top-level function."<< endl; "do not "
<< "match the number of arguments passed to a previous call or declaration of "
"the top-level function."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (external_function_options_chng.firstDerivSymbID != getFirstDerivSymbID(symb_id)) if (external_function_options_chng.firstDerivSymbID != getFirstDerivSymbID(symb_id))
{ {
cerr << "ERROR: The first derivative function passed to the external_function() statement does not " cerr << "ERROR: The first derivative function passed to the external_function() "
<< "match the first derivative function passed to a previous call or declaration of the top-level function."<< endl; "statement does not "
<< "match the first derivative function passed to a previous call or "
"declaration of the top-level function."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (external_function_options_chng.secondDerivSymbID != getSecondDerivSymbID(symb_id)) if (external_function_options_chng.secondDerivSymbID != getSecondDerivSymbID(symb_id))
{ {
cerr << "ERROR: The second derivative function passed to the external_function() statement does not " cerr << "ERROR: The second derivative function passed to the external_function() "
<< "match the second derivative function passed to a previous call or declaration of the top-level function."<< endl; "statement does not "
<< "match the second derivative function passed to a previous call or "
"declaration of the top-level function."
<< endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
......
/* /*
* Copyright (C) 2010-2015 Dynare Team * Copyright © 2010-2023 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -14,32 +14,29 @@ ...@@ -14,32 +14,29 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef _EXTERNALFUNCTIONSTABLE_HH #ifndef EXTERNAL_FUNCTIONS_TABLE_HH
#define _EXTERNALFUNCTIONSTABLE_HH #define EXTERNAL_FUNCTIONS_TABLE_HH
using namespace std;
#include <algorithm>
#include <iostream> #include <iostream>
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
using namespace std;
//! Handles external functions //! Handles external functions
class ExternalFunctionsTable class ExternalFunctionsTable
{ {
public: public:
//! Thrown when trying to access an unknown symbol (by id) //! Thrown when trying to access an unknown symbol (by id)
class UnknownExternalFunctionSymbolIDException struct UnknownExternalFunctionSymbolIDException
{ {
public:
//! Symbol ID //! Symbol ID
int id; int id;
explicit UnknownExternalFunctionSymbolIDException(int id_arg) : id{id_arg}
{
}
}; };
/* For all arguments, -2 means not set /* For all arguments, -2 means not set
...@@ -53,73 +50,62 @@ public: ...@@ -53,73 +50,62 @@ public:
}; };
using external_function_table_type = map<int, external_function_options>; using external_function_table_type = map<int, external_function_options>;
//! Symbol ID used when no external function exists that calculates the derivative //! Symbol ID used when no external function exists that calculates the derivative
const static int IDNotSet = -1; constexpr static int IDNotSet = -1;
//! Symbol ID used when the derivative is obtained from the top-level function //! Symbol ID used when the derivative is obtained from the top-level function
const static int IDSetButNoNameProvided = -2; constexpr static int IDSetButNoNameProvided = -2;
//! Default number of arguments when nargs is not specified //! Default number of arguments when nargs is not specified
const static int defaultNargs = 1; constexpr static int defaultNargs = 1;
private: private:
//! Map containing options provided to external_functions() //! Map containing options provided to external_functions()
external_function_table_type externalFunctionTable; external_function_table_type externalFunctionTable;
public: public:
ExternalFunctionsTable();
//! Adds an external function to the table as well as its derivative functions //! 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 //! See if the function exists in the External Functions Table
inline bool exists(int symb_id) const; [[nodiscard]] inline bool exists(int symb_id) const;
//! Get the number of arguments for a given external function //! Get the number of arguments for a given external function
inline int getNargs(int symb_id) const noexcept(false); [[nodiscard]] inline int getNargs(int symb_id) const noexcept(false);
//! Get the symbol_id of the first derivative function //! Get the symbol_id of the first derivative function
inline int getFirstDerivSymbID(int symb_id) const noexcept(false); [[nodiscard]] inline int getFirstDerivSymbID(int symb_id) const noexcept(false);
//! Get the symbol_id of the second derivative function //! Get the symbol_id of the second derivative function
inline int getSecondDerivSymbID(int symb_id) const noexcept(false); [[nodiscard]] inline int getSecondDerivSymbID(int symb_id) const noexcept(false);
//! Returns the total number of unique external functions declared or used in the .mod file
inline int get_total_number_of_unique_model_block_external_functions() const;
}; };
inline bool inline bool
ExternalFunctionsTable::exists(int symb_id) const ExternalFunctionsTable::exists(int symb_id) const
{ {
auto iter = externalFunctionTable.find(symb_id); return externalFunctionTable.contains(symb_id);
return (iter != externalFunctionTable.end());
} }
inline int inline int
ExternalFunctionsTable::getNargs(int symb_id) const noexcept(false) ExternalFunctionsTable::getNargs(int symb_id) const noexcept(false)
{ {
if (exists(symb_id)) if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return externalFunctionTable.find(symb_id)->second.nargs; return it->second.nargs;
else else
throw UnknownExternalFunctionSymbolIDException(symb_id); throw UnknownExternalFunctionSymbolIDException {symb_id};
} }
inline int inline int
ExternalFunctionsTable::getFirstDerivSymbID(int symb_id) const noexcept(false) ExternalFunctionsTable::getFirstDerivSymbID(int symb_id) const noexcept(false)
{ {
if (exists(symb_id)) if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return externalFunctionTable.find(symb_id)->second.firstDerivSymbID; return it->second.firstDerivSymbID;
else else
throw UnknownExternalFunctionSymbolIDException(symb_id); throw UnknownExternalFunctionSymbolIDException {symb_id};
} }
inline int inline int
ExternalFunctionsTable::getSecondDerivSymbID(int symb_id) const noexcept(false) ExternalFunctionsTable::getSecondDerivSymbID(int symb_id) const noexcept(false)
{ {
if (exists(symb_id)) if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return externalFunctionTable.find(symb_id)->second.secondDerivSymbID; return it->second.secondDerivSymbID;
else else
throw UnknownExternalFunctionSymbolIDException(symb_id); throw UnknownExternalFunctionSymbolIDException {symb_id};
}
inline int
ExternalFunctionsTable::get_total_number_of_unique_model_block_external_functions() const
{
int number_of_unique_model_block_external_functions = 0;
for (auto it : externalFunctionTable)
if (it.second.nargs > 0)
number_of_unique_model_block_external_functions++;
return number_of_unique_model_block_external_functions;
} }
#endif #endif
/*
* Copyright © 2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <utility>
#include "HeterogeneityTable.hh"
#include "SymbolTable.hh"
void
HeterogeneityTable::setSymbolTable(SymbolTable* symbol_table_arg)
{
symbol_table = symbol_table_arg;
}
int
HeterogeneityTable::addDimension(string name)
{
if (name_to_id.contains(name))
throw AlreadyDeclaredDimensionException {move(name)};
int id {static_cast<int>(id_to_name.size())};
name_to_id.emplace(name, id);
id_to_name.push_back(move(name));
return id;
}
bool
HeterogeneityTable::exists(const string& name) const
{
return name_to_id.contains(name);
}
int
HeterogeneityTable::getID(const string& name) const
{
if (auto it = name_to_id.find(name); it != name_to_id.end())
return it->second;
else
throw UnknownDimensionNameException {name};
}
string
HeterogeneityTable::getName(int id) const
{
if (id < 0 || id >= static_cast<int>(id_to_name.size()))
throw UnknownDimensionIDException {id};
else
return id_to_name[id];
}
bool
HeterogeneityTable::empty() const
{
return name_to_id.empty();
}
vector<string>
HeterogeneityTable::getDimensions() const
{
return id_to_name;
}
int
HeterogeneityTable::size() const
{
return static_cast<int>(name_to_id.size());
}
void
HeterogeneityTable::addSummedHeterogeneousEndogenous(int symb_id)
{
assert(symbol_table->getType(symb_id) == SymbolType::heterogeneousEndogenous);
if (summed_het_endo_to_index.contains(symb_id))
throw AlreadyDeclaredSummedHeterogeneousEndogenousException {symb_id};
int index {static_cast<int>(index_to_summed_het_endo.size())};
summed_het_endo_to_index.emplace(symb_id, index);
index_to_summed_het_endo.push_back(symb_id);
}
int
HeterogeneityTable::getSummedHeterogenousEndogenousIndex(int symb_id) const
{
if (auto it = summed_het_endo_to_index.find(symb_id); it != summed_het_endo_to_index.end())
return it->second;
else
throw UnknownSummedHeterogeneousEndogenousException {symb_id};
}
int
HeterogeneityTable::aggregateEndoSize() const
{
return index_to_summed_het_endo.size();
}
void
HeterogeneityTable::writeOutput(ostream& output) const
{
for (size_t id {0}; id < id_to_name.size(); id++)
output << "M_.heterogeneity(" << id + 1 << ").dimension_name = '" << id_to_name[id] << "';"
<< endl;
output << "M_.heterogeneity_aggregates = {" << endl;
for (int symb_id : index_to_summed_het_endo)
output << "'sum', " << symbol_table->getHeterogeneityDimension(symb_id) + 1 << ", "
<< symbol_table->getTypeSpecificID(symb_id) + 1 << ";" << endl;
output << "};" << endl;
}
void
HeterogeneityTable::writeJsonOutput(ostream& output) const
{
assert(!empty());
output << R"("heterogeneity_dimension": [)";
for (bool first_written {false}; const auto& dim : id_to_name)
{
if (exchange(first_written, true))
output << ", ";
output << '"' << dim << '"';
}
output << "]" << endl;
}
/*
* Copyright © 2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef HETEROGENEITY_TABLE_HH
#define HETEROGENEITY_TABLE_HH
#include <map>
#include <ostream>
#include <string>
#include <vector>
using namespace std;
class SymbolTable; // Forward declaration, to avoid circularity
/*
There is a guarantee that heterogeneity IDs are increasing, i.e. if dimension A is added after
dimension B, then the ID of A is greater than the ID of B.
Moreover, the IDs form a contiguous interval starting at 0.
*/
class HeterogeneityTable
{
private:
// Maps dimension names to IDs
map<string, int> name_to_id;
// Maps dimension IDs to names
vector<string> id_to_name;
SymbolTable* symbol_table {nullptr}; // Cannot be a reference, because of circularity
/* Keeps track of the SUM() operator instances.
Maps a symbol ID that appears inside a SUM() operator into an index in
M_.heterogeneity_aggregates */
map<int, int> summed_het_endo_to_index;
// Maps an index in M_.heterogeneity_aggregates into a symbol ID
vector<int> index_to_summed_het_endo;
public:
void setSymbolTable(SymbolTable* symbol_table_arg);
struct AlreadyDeclaredDimensionException
{
// Dimension name
const string name;
};
struct UnknownDimensionNameException
{
// Dimension name
const string name;
};
struct UnknownDimensionIDException
{
// Dimension ID
const int id;
};
// Returns the dimension ID
int addDimension(string name);
[[nodiscard]] bool exists(const string& name) const;
[[nodiscard]] int getID(const string& name) const;
[[nodiscard]] string getName(int id) const;
[[nodiscard]] bool empty() const;
[[nodiscard]] vector<string> getDimensions() const;
[[nodiscard]] int size() const;
struct AlreadyDeclaredSummedHeterogeneousEndogenousException
{
const int symb_id;
};
struct UnknownSummedHeterogeneousEndogenousException
{
const int symb_id;
};
void addSummedHeterogeneousEndogenous(int symb_id);
[[nodiscard]] int getSummedHeterogenousEndogenousIndex(int symb_id) const;
[[nodiscard]] int aggregateEndoSize() const;
void writeOutput(ostream& output) const;
void writeJsonOutput(ostream& output) const;
};
#endif
/*
* Copyright © 2024-2025 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <iostream>
#include "HeterogeneousModel.hh"
HeterogeneousModel::HeterogeneousModel(SymbolTable& symbol_table_arg,
NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg,
int heterogeneity_dimension_arg) :
ModelTree {symbol_table_arg, num_constants_arg, external_functions_table_arg,
heterogeneity_table_arg, true},
heterogeneity_dimension {heterogeneity_dimension_arg}
{
}
HeterogeneousModel&
HeterogeneousModel::operator=(const HeterogeneousModel& m)
{
ModelTree::operator=(m);
assert(heterogeneity_dimension == m.heterogeneity_dimension);
deriv_id_table = m.deriv_id_table;
inv_deriv_id_table = m.inv_deriv_id_table;
return *this;
}
void
HeterogeneousModel::computeChainRuleJacobian()
{
cerr << "Heterogeneous::computeChainRuleJacobian(): unimplemented" << endl;
exit(EXIT_FAILURE);
}
int
HeterogeneousModel::getBlockJacobianEndoCol([[maybe_unused]] int blk, [[maybe_unused]] int var,
[[maybe_unused]] int lead_lag) const
{
cerr << "Heterogeneous::getBlockJacobianEndoCol(): unimplemented" << endl;
exit(EXIT_FAILURE);
}
int
HeterogeneousModel::getMFS() const
{
cerr << "Heterogeneous::getMFS(): unimplemented" << endl;
exit(EXIT_FAILURE);
}
void
HeterogeneousModel::computeDerivIDs()
{
set<pair<int, int>> dynvars;
for (auto& equation : equations)
{
equation->collectDynamicVariables(SymbolType::heterogeneousEndogenous, dynvars);
equation->collectDynamicVariables(SymbolType::heterogeneousExogenous, dynvars);
equation->collectDynamicVariables(SymbolType::endogenous, dynvars);
equation->collectDynamicVariables(SymbolType::exogenous, dynvars);
equation->collectDynamicVariables(SymbolType::parameter, dynvars);
}
for (const auto& [symb_id, lead_lag] : dynvars)
{
auto type {symbol_table.getType(symb_id)};
if (isHeterogeneous(type))
assert(symbol_table.getHeterogeneityDimension(symb_id) == heterogeneity_dimension);
if (type == SymbolType::heterogeneousEndogenous || type == SymbolType::endogenous)
assert(abs(lead_lag) <= 1);
if (type == SymbolType::heterogeneousExogenous || type == SymbolType::exogenous)
assert(lead_lag == 0);
int deriv_id {static_cast<int>(deriv_id_table.size())};
deriv_id_table.emplace(pair {symb_id, lead_lag}, deriv_id);
inv_deriv_id_table.emplace_back(symb_id, lead_lag);
}
}
/*
* Unfold complementarity conditions: (i) declare the multipliers associated
* with each bound constraint μ_l and μ_u ; (ii) add or substract the
* multiplier into the associated condition; (iii) add the the complementarity
* slackness conditions into the set of equations. For example,
* households choose {cₜ, aₜ₊₁} to maximize expected lifetime utility:
* max 𝐸ₜ [∑ₛ₌₀^∞ βˢ · u(cₜ₊ₛ)]
*
* Subject to:
* 1. Budget constraint: cₜ + aₜ₊₁ = yₜ + (1 + rₜ) · aₜ
* 2. Borrowing constraint: aₜ₊₁ ≥ aₘᵢₙ
*
* Let u'(cₜ) denote the marginal utility of consumption.
* Let μₜ ≥ 0 be the Lagrange multiplier on the borrowing constraint.
*
* Then, the Euler equation becomes:
* u′(cₜ) = β · (1 + rₜ₊₁) · u′(cₜ₊₁) − μₜ
*
* Together with:
* aₜ₊₁ ≥ aₘᵢₙ [primal feasibility]
* μₜ ≥ 0 [dual feasibility]
* μₜ · (aₜ₊₁ − aₘᵢₙ) = 0 [complementarity slackness]
* Note that the primal feasibility and dual feasibility constraints are not
* introduced here, but Bhandari et al. (2023) show in Appendix B.1 that they
* are redundant.
*/
void
HeterogeneousModel::transformPass()
{
for (int i = 0; i < static_cast<int>(equations.size()); ++i)
{
if (!complementarity_conditions[i])
continue;
/*
* `const auto& [symb_id, lb, ub] = *complementarity_conditions[i];` was not used here because
* the call to `addEquation` may eventually lead to a resize of the
* `complementarity_conditions` vector, which may invalidate the reference to its element. We
* take a copy instead for safety.
*/
auto [symb_id, lb, ub] = *complementarity_conditions[i];
VariableNode* var = getVariable(symb_id);
if (lb)
{
int mu_id = symbol_table.addHeterogeneousMultiplierAuxiliaryVar(
heterogeneity_dimension, i, "MULT_L_" + symbol_table.getName(symb_id));
expr_t mu_L = AddVariable(mu_id);
auto substeq = AddEqual(AddPlus(equations[i]->arg1, mu_L), equations[i]->arg2);
assert(substeq);
equations[i] = substeq;
addEquation(AddEqual(AddTimes(mu_L, AddMinus(var, lb)), Zero), nullopt);
}
if (ub)
{
int mu_id = symbol_table.addHeterogeneousMultiplierAuxiliaryVar(
heterogeneity_dimension, i, "MULT_U_" + symbol_table.getName(symb_id));
auto mu_U = AddVariable(mu_id);
auto substeq = AddEqual(AddMinus(equations[i]->arg1, mu_U), equations[i]->arg2);
assert(substeq);
equations[i] = substeq;
addEquation(AddEqual(AddTimes(mu_U, AddMinus(ub, var)), Zero), nullopt);
}
}
}
void
HeterogeneousModel::computingPass(int derivsOrder, bool no_tmp_terms, bool use_dll)
{
assert(!use_dll); // Not yet implemented
computeDerivIDs();
set<int> vars;
for (auto& [symb_lag, deriv_id] : deriv_id_table)
if (symbol_table.getType(symb_lag.first) != SymbolType::parameter)
vars.insert(deriv_id);
cout << "Computing " << modelClassName() << " derivatives (order " << derivsOrder << ")." << endl;
computeDerivatives(derivsOrder, vars);
computeTemporaryTerms(!use_dll, no_tmp_terms);
computeMCPEquationsReordering(heterogeneity_dimension);
}
void
HeterogeneousModel::writeModelFiles(const string& basename, bool julia) const
{
assert(!julia); // Not yet implemented
writeSparseModelMFiles<true>(basename, heterogeneity_dimension);
writeComplementarityConditionsFile<true>(basename, heterogeneity_dimension);
}
int
HeterogeneousModel::getJacobianCol(int deriv_id, bool sparse) const
{
assert(sparse);
SymbolType type {getTypeByDerivID(deriv_id)};
int tsid {getTypeSpecificIDByDerivID(deriv_id)};
int lag {getLagByDerivID(deriv_id)};
if (type == SymbolType::heterogeneousEndogenous)
return tsid + (lag + 1) * symbol_table.het_endo_nbr(heterogeneity_dimension);
int shift {3 * symbol_table.het_endo_nbr(heterogeneity_dimension)};
if (type == SymbolType::heterogeneousExogenous)
return shift + tsid;
shift += symbol_table.het_exo_nbr(heterogeneity_dimension);
if (type == SymbolType::endogenous)
return shift + tsid + (lag + 1) * symbol_table.endo_nbr();
shift += symbol_table.endo_nbr();
if (type == SymbolType::exogenous)
return shift + tsid;
throw UnknownDerivIDException();
}
int
HeterogeneousModel::getJacobianColsNbr(bool sparse) const
{
assert(sparse);
return 3 * (symbol_table.het_endo_nbr(heterogeneity_dimension) + symbol_table.endo_nbr())
+ symbol_table.het_exo_nbr(heterogeneity_dimension) + symbol_table.exo_nbr();
}
SymbolType
HeterogeneousModel::getTypeByDerivID(int deriv_id) const noexcept(false)
{
return symbol_table.getType(getSymbIDByDerivID(deriv_id));
}
int
HeterogeneousModel::getLagByDerivID(int deriv_id) const noexcept(false)
{
if (deriv_id < 0 || deriv_id >= static_cast<int>(inv_deriv_id_table.size()))
throw UnknownDerivIDException();
return inv_deriv_id_table[deriv_id].second;
}
int
HeterogeneousModel::getSymbIDByDerivID(int deriv_id) const noexcept(false)
{
if (deriv_id < 0 || deriv_id >= static_cast<int>(inv_deriv_id_table.size()))
throw UnknownDerivIDException();
return inv_deriv_id_table[deriv_id].first;
}
int
HeterogeneousModel::getTypeSpecificIDByDerivID(int deriv_id) const
{
return symbol_table.getTypeSpecificID(getSymbIDByDerivID(deriv_id));
}
int
HeterogeneousModel::getDerivID(int symb_id, int lead_lag) const noexcept(false)
{
if (auto it = deriv_id_table.find({symb_id, lead_lag}); it == deriv_id_table.end())
throw UnknownDerivIDException();
else
return it->second;
}
void
HeterogeneousModel::writeDriverOutput(ostream& output) const
{
std::vector<int> state_var;
for (int endoID = 0; endoID < symbol_table.het_endo_nbr(heterogeneity_dimension); endoID++)
try
{
getDerivID(symbol_table.getID(SymbolType::heterogeneousEndogenous, endoID,
heterogeneity_dimension),
-1);
if (ranges::find(state_var, endoID) == state_var.end())
state_var.push_back(endoID);
}
catch (UnknownDerivIDException& e)
{
}
output << "M_.heterogeneity(" << heterogeneity_dimension + 1 << ").state_var = [";
for (int it : state_var)
output << it + 1 << " ";
output << "];" << endl;
output << "M_.heterogeneity(" << heterogeneity_dimension + 1 << ").dynamic_tmp_nbr = [";
for (const auto& it : temporary_terms_derivatives)
output << it.size() << "; ";
output << "];" << endl;
writeDriverSparseIndicesHelper(
"heterogeneity("s + to_string(heterogeneity_dimension + 1) + ").dynamic", output);
output << "M_.heterogeneity(" << heterogeneity_dimension + 1
<< ").dynamic_mcp_equations_reordering = [";
for (auto i : mcp_equations_reordering)
output << i + 1 << "; ";
output << "];" << endl;
}
/*
* Copyright © 2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef HETEROGENEOUS_MODEL_HH
#define HETEROGENEOUS_MODEL_HH
#include <string>
#include "ModelTree.hh"
using namespace std;
class HeterogeneousModel : public ModelTree
{
public:
const int heterogeneity_dimension;
HeterogeneousModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg, int heterogeneity_dimension_arg);
HeterogeneousModel(const HeterogeneousModel& m) = default;
HeterogeneousModel& operator=(const HeterogeneousModel& m);
void transformPass();
void computingPass(int derivsOrder, bool no_tmp_terms, bool use_dll);
void writeModelFiles(const string& basename, bool julia) const;
void writeDriverOutput(ostream& output) const;
[[nodiscard]] int getJacobianCol(int deriv_id, bool sparse) const override;
[[nodiscard]] int getJacobianColsNbr(bool sparse) const override;
#if 0
void substituteEndoLeadGreaterThanTwo();
//! Transforms the model by removing all lags greater or equal than 2 on endos
void substituteEndoLagGreaterThanTwo();
//! Transforms the model by removing all leads on exos
/*! Note that this can create new lags on endos and exos */
void substituteExoLead();
//! Transforms the model by removing all lags on exos
void substituteExoLag();
//! 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
void transformPredeterminedVariables();
//! Substitutes out all model-local variables
void substituteModelLocalVariables();
#endif
// FIXME: the following 5 functions are identical to those in DynamicModel. Factorization?
[[nodiscard]] int getDerivID(int symb_id, int lead_lag) const noexcept(false) override;
[[nodiscard]] SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;
[[nodiscard]] int getLagByDerivID(int deriv_id) const noexcept(false) override;
[[nodiscard]] int getSymbIDByDerivID(int deriv_id) const noexcept(false) override;
[[nodiscard]] int getTypeSpecificIDByDerivID(int deriv_id) const override;
protected:
void computeChainRuleJacobian() override;
int getBlockJacobianEndoCol(int blk, int var, int lead_lag) const override;
string
modelClassName() const override
{
return "dynamic model for heterogeneity dimension '"
+ heterogeneity_table.getName(heterogeneity_dimension) + "'";
}
int getMFS() const override;
private:
// Maps a pair (symbol ID, lead/lag) to a deriv ID
map<pair<int, int>, int> deriv_id_table;
// Maps a deriv ID to a pair (symbol ID, lead/lag)
vector<pair<int, int>> inv_deriv_id_table;
// Allocates the derivation IDs for all endogenous variables for this heterogeneity dimension
void computeDerivIDs();
};
#endif