Skip to content
Snippets Groups Projects

Compare revisions

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

Source

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

Target

Select target project
  • normann/preprocessor
  • Dynare/preprocessor
  • FerhatMihoubi/preprocessor
  • MichelJuillard/preprocessor
  • sebastien/preprocessor
  • lnsongxf/preprocessor
  • albop/preprocessor
  • DoraK/preprocessor
  • amg/preprocessor
  • wmutschl/preprocessor
  • JohannesPfeifer/preprocessor
11 results
Select Git revision
  • aux_vars_fix
  • master
  • rework_pac
  • created_preprocessor_repo
4 results
Show changes
Showing
with 14798 additions and 13905 deletions
/*
* Copyright (C) 2003-2018 Dynare Team
* Copyright © 2003-2025 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,28 +14,29 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <boost/filesystem.hpp>
#include <iterator>
#include <ranges>
#include "DataTree.hh"
DataTree::DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg) :
symbol_table(symbol_table_arg),
num_constants(num_constants_arg),
external_functions_table(external_functions_table_arg)
bool DataTree::no_commutativity = false;
void
DataTree::initConstants()
{
Zero = AddNonNegativeConstant("0");
One = AddNonNegativeConstant("1");
Two = AddNonNegativeConstant("2");
Three = AddNonNegativeConstant("3");
MinusOne = AddUMinus(One);
......@@ -46,81 +47,174 @@ DataTree::DataTree(SymbolTable &symbol_table_arg,
Pi = AddNonNegativeConstant("3.141592653589793");
}
DataTree::~DataTree() = default;
DataTree::DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg, bool is_dynamic_arg) :
symbol_table {symbol_table_arg},
num_constants {num_constants_arg},
external_functions_table {external_functions_table_arg},
heterogeneity_table {heterogeneity_table_arg},
is_dynamic {is_dynamic_arg}
{
initConstants();
}
expr_t
DataTree::DataTree(const DataTree& d) :
symbol_table {d.symbol_table},
num_constants {d.num_constants},
external_functions_table {d.external_functions_table},
heterogeneity_table {d.heterogeneity_table},
is_dynamic {d.is_dynamic},
local_variables_vector {d.local_variables_vector}
{
// Constants must be initialized first because they are used in some Add* methods
initConstants();
// 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)
it->clone(*this);
assert(node_list.size() == d.node_list.size());
}
DataTree&
DataTree::operator=(const DataTree& d)
{
assert(&symbol_table == &d.symbol_table);
assert(&num_constants == &d.num_constants);
assert(&external_functions_table == &d.external_functions_table);
assert(&heterogeneity_table == &d.heterogeneity_table);
assert(is_dynamic == d.is_dynamic);
num_const_node_map.clear();
variable_node_map.clear();
unary_op_node_map.clear();
binary_op_node_map.clear();
trinary_op_node_map.clear();
external_function_node_map.clear();
var_expectation_node_map.clear();
pac_expectation_node_map.clear();
pac_target_nonstationary_node_map.clear();
first_deriv_external_function_node_map.clear();
second_deriv_external_function_node_map.clear();
node_list.clear();
// Constants must be initialized first because they are used in some Add* methods
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)
it->clone(*this);
assert(node_list.size() == d.node_list.size());
local_variables_vector = d.local_variables_vector;
return *this;
}
NumConstNode*
DataTree::AddNonNegativeConstant(const string& value)
{
int id = num_constants.AddNonNegativeConstant(value);
auto it = num_const_node_map.find(id);
if (it != num_const_node_map.end())
if (auto it = num_const_node_map.find(id); it != num_const_node_map.end())
return it->second;
auto sp = make_unique<NumConstNode>(*this, node_list.size(), id);
auto p = sp.get();
node_list.push_back(move(sp));
num_const_node_map[id] = p;
num_const_node_map.emplace(id, p);
return p;
}
VariableNode*
DataTree::AddVariableInternal(int symb_id, int lag)
DataTree::AddVariable(int symb_id, int lag)
{
auto it = variable_node_map.find({ symb_id, lag });
if (it != variable_node_map.end())
if (lag != 0 && !is_dynamic)
{
cerr << "Leads/lags not authorized in this DataTree" << endl;
exit(EXIT_FAILURE);
}
if (auto it = variable_node_map.find({symb_id, lag}); it != variable_node_map.end())
return it->second;
auto sp = make_unique<VariableNode>(*this, node_list.size(), symb_id, lag);
auto p = sp.get();
node_list.push_back(move(sp));
variable_node_map[{ symb_id, lag }] = p;
variable_node_map.try_emplace({symb_id, lag}, p);
return p;
}
VariableNode*
DataTree::getVariable(int symb_id, int lag) const
{
auto it = variable_node_map.find({symb_id, lag});
if (it == variable_node_map.end())
{
cerr << "DataTree::getVariable: unknown variable node for symb_id=" << symb_id
<< " and lag=" << lag << endl;
exit(EXIT_FAILURE);
}
return it->second;
}
bool
DataTree::ParamUsedWithLeadLagInternal() const
{
for (const auto & it : variable_node_map)
if (symbol_table.getType(it.first.first) == SymbolType::parameter && it.first.second != 0)
for (const auto& [symb_lag, expr] : variable_node_map)
if (symbol_table.getType(symb_lag.first) == SymbolType::parameter && symb_lag.second != 0)
return true;
return false;
}
VariableNode *
DataTree::AddVariable(int symb_id, int lag)
{
assert(lag == 0);
return AddVariableInternal(symb_id, lag);
}
expr_t
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
auto *uarg2 = dynamic_cast<UnaryOpNode *>(iArg2);
if (uarg2 != nullptr && uarg2->get_op_code() == UnaryOpcode::uminus)
return AddMinus(iArg1, uarg2->get_arg());
if (auto uarg2 = dynamic_cast<UnaryOpNode*>(iArg2);
uarg2 && uarg2->op_code == UnaryOpcode::uminus)
return AddMinus(iArg1, uarg2->arg);
// Simplify (-x)+y in y-x
if (auto uarg1 = dynamic_cast<UnaryOpNode*>(iArg1);
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 "+"
// Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx)
{
expr_t tmp = iArg1;
iArg1 = iArg2;
iArg2 = tmp;
}
if (iArg1->idx > iArg2->idx && !no_commutativity) // NOLINT(clang-analyzer-core.NullDereference)
swap(iArg1, iArg2);
return AddBinaryOp(iArg1, BinaryOpcode::plus, iArg2);
}
else if (iArg1 != Zero)
return iArg1;
else if (iArg2 != Zero)
return iArg2;
else
return Zero;
}
expr_t
DataTree::AddMinus(expr_t iArg1, expr_t iArg2)
......@@ -134,53 +228,71 @@ DataTree::AddMinus(expr_t iArg1, expr_t iArg2)
if (iArg1 == iArg2)
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);
}
expr_t
DataTree::AddUMinus(expr_t iArg1)
{
if (iArg1 != Zero)
{
if (iArg1 == Zero)
return Zero;
// Simplify -(-x) in x
auto *uarg = dynamic_cast<UnaryOpNode *>(iArg1);
if (uarg != nullptr && uarg->get_op_code() == UnaryOpcode::uminus)
return uarg->get_arg();
if (auto uarg = dynamic_cast<UnaryOpNode*>(iArg1); uarg && uarg->op_code == UnaryOpcode::uminus)
return uarg->arg;
return AddUnaryOp(UnaryOpcode::uminus, iArg1);
}
else
return Zero;
}
expr_t
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)
return AddUMinus(iArg2);
else if (iArg2 == MinusOne)
if (iArg2 == MinusOne)
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 "*"
// Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx)
{
expr_t tmp = iArg1;
iArg1 = iArg2;
iArg2 = tmp;
}
if (iArg1->idx > iArg2->idx && !no_commutativity) // NOLINT(clang-analyzer-core.NullDereference)
swap(iArg1, 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
DataTree::AddDivide(expr_t iArg1, expr_t iArg2) noexcept(false)
......@@ -201,6 +313,21 @@ DataTree::AddDivide(expr_t iArg1, expr_t iArg2) noexcept(false)
if (iArg1 == iArg2)
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);
}
......@@ -243,16 +370,20 @@ DataTree::AddDifferent(expr_t iArg1, expr_t iArg2)
expr_t
DataTree::AddPower(expr_t iArg1, expr_t iArg2)
{
if (iArg1 != Zero && iArg2 != Zero && iArg1 != One && iArg2 != One)
return AddBinaryOp(iArg1, BinaryOpcode::power, iArg2);
else if (iArg1 == One)
return One;
else if (iArg2 == One)
return iArg1;
else if (iArg2 == Zero)
// This one comes first, because 0⁰=1
if (iArg2 == Zero)
return One;
else
if (iArg1 == Zero)
return Zero;
if (iArg1 == One)
return One;
if (iArg2 == One)
return iArg1;
return AddBinaryOp(iArg1, BinaryOpcode::power, iArg2);
}
expr_t
......@@ -265,167 +396,197 @@ DataTree::AddPowerDeriv(expr_t iArg1, expr_t iArg2, int powerDerivOrder)
expr_t
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);
}
expr_t
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
DataTree::AddExp(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::exp, iArg1);
else
if (iArg1 == Zero)
return One;
return AddUnaryOp(UnaryOpcode::exp, iArg1);
}
expr_t
DataTree::AddLog(expr_t iArg1)
{
if (iArg1 != Zero && iArg1 != One)
return AddUnaryOp(UnaryOpcode::log, iArg1);
else if (iArg1 == One)
if (iArg1 == One)
return Zero;
else
if (iArg1 == Zero)
{
cerr << "ERROR: log(0) not defined!" << endl;
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
DataTree::AddLog10(expr_t iArg1)
{
if (iArg1 != Zero && iArg1 != One)
return AddUnaryOp(UnaryOpcode::log10, iArg1);
else if (iArg1 == One)
if (iArg1 == One)
return Zero;
else
if (iArg1 == Zero)
{
cerr << "ERROR: log10(0) not defined!" << endl;
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
DataTree::AddCos(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::cos, iArg1);
else
if (iArg1 == Zero)
return One;
return AddUnaryOp(UnaryOpcode::cos, iArg1);
}
expr_t
DataTree::AddSin(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::sin, iArg1);
else
if (iArg1 == Zero)
return Zero;
return AddUnaryOp(UnaryOpcode::sin, iArg1);
}
expr_t
DataTree::AddTan(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::tan, iArg1);
else
if (iArg1 == Zero)
return Zero;
return AddUnaryOp(UnaryOpcode::tan, iArg1);
}
expr_t
DataTree::AddAcos(expr_t iArg1)
{
if (iArg1 != One)
return AddUnaryOp(UnaryOpcode::acos, iArg1);
else
if (iArg1 == One)
return Zero;
return AddUnaryOp(UnaryOpcode::acos, iArg1);
}
expr_t
DataTree::AddAsin(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::asin, iArg1);
else
if (iArg1 == Zero)
return Zero;
return AddUnaryOp(UnaryOpcode::asin, iArg1);
}
expr_t
DataTree::AddAtan(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::atan, iArg1);
else
if (iArg1 == Zero)
return Zero;
return AddUnaryOp(UnaryOpcode::atan, iArg1);
}
expr_t
DataTree::AddCosh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::cosh, iArg1);
else
if (iArg1 == Zero)
return One;
return AddUnaryOp(UnaryOpcode::cosh, iArg1);
}
expr_t
DataTree::AddSinh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::sinh, iArg1);
else
if (iArg1 == Zero)
return Zero;
return AddUnaryOp(UnaryOpcode::sinh, iArg1);
}
expr_t
DataTree::AddTanh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::tanh, iArg1);
else
if (iArg1 == Zero)
return Zero;
return AddUnaryOp(UnaryOpcode::tanh, iArg1);
}
expr_t
DataTree::AddAcosh(expr_t iArg1)
{
if (iArg1 != One)
return AddUnaryOp(UnaryOpcode::acosh, iArg1);
else
if (iArg1 == One)
return Zero;
return AddUnaryOp(UnaryOpcode::acosh, iArg1);
}
expr_t
DataTree::AddAsinh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::asinh, iArg1);
else
if (iArg1 == Zero)
return Zero;
return AddUnaryOp(UnaryOpcode::asinh, iArg1);
}
expr_t
DataTree::AddAtanh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::atanh, iArg1);
else
if (iArg1 == Zero)
return Zero;
return AddUnaryOp(UnaryOpcode::atanh, iArg1);
}
expr_t
DataTree::AddSqrt(expr_t iArg1)
{
if (iArg1 != Zero)
if (iArg1 == Zero)
return Zero;
if (iArg1 == One)
return One;
return AddUnaryOp(UnaryOpcode::sqrt, iArg1);
else
}
expr_t
DataTree::AddCbrt(expr_t iArg1)
{
if (iArg1 == Zero)
return Zero;
if (iArg1 == One)
return One;
return AddUnaryOp(UnaryOpcode::cbrt, iArg1);
}
expr_t
......@@ -433,9 +594,10 @@ DataTree::AddAbs(expr_t iArg1)
{
if (iArg1 == Zero)
return Zero;
if (iArg1 == One)
return One;
else
return AddUnaryOp(UnaryOpcode::abs, iArg1);
}
......@@ -444,19 +606,29 @@ DataTree::AddSign(expr_t iArg1)
{
if (iArg1 == Zero)
return Zero;
if (iArg1 == One)
return One;
else
return AddUnaryOp(UnaryOpcode::sign, iArg1);
}
expr_t
DataTree::AddErf(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(UnaryOpcode::erf, iArg1);
else
if (iArg1 == 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
......@@ -498,7 +670,8 @@ DataTree::AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id)
expr_t
DataTree::AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id)
{
return AddUnaryOp(UnaryOpcode::steadyStateParam2ndDeriv, iArg1, 0, param1_symb_id, param2_symb_id);
return AddUnaryOp(UnaryOpcode::steadyStateParam2ndDeriv, iArg1, 0, param1_symb_id,
param2_symb_id);
}
expr_t
......@@ -510,35 +683,49 @@ DataTree::AddExpectation(int iArg1, expr_t iArg2)
expr_t
DataTree::AddVarExpectation(const string& model_name)
{
auto it = var_expectation_node_map.find(model_name);
if (it != var_expectation_node_map.end())
if (auto it = var_expectation_node_map.find(model_name); it != var_expectation_node_map.end())
return it->second;
auto sp = make_unique<VarExpectationNode>(*this, node_list.size(), model_name);
auto p = sp.get();
node_list.push_back(move(sp));
var_expectation_node_map[model_name] = p;
var_expectation_node_map.emplace(model_name, p);
return p;
}
expr_t
DataTree::AddPacExpectation(const string& model_name)
{
auto it = pac_expectation_node_map.find(model_name);
if (it != pac_expectation_node_map.end())
if (auto it = pac_expectation_node_map.find(model_name); it != pac_expectation_node_map.end())
return it->second;
auto sp = make_unique<PacExpectationNode>(*this, node_list.size(), model_name);
auto p = sp.get();
node_list.push_back(move(sp));
pac_expectation_node_map[model_name] = p;
pac_expectation_node_map.emplace(model_name, p);
return p;
}
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)
{
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
......@@ -547,11 +734,10 @@ DataTree::AddLocalVariable(int symb_id, expr_t value) noexcept(false)
assert(symbol_table.getType(symb_id) == SymbolType::modelLocalVariable);
// Throw an exception if symbol already declared
auto it = local_variables_table.find(symb_id);
if (it != local_variables_table.end())
throw LocalVariableException(symbol_table.getName(symb_id));
if (local_variables_table.contains(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);
}
......@@ -560,157 +746,150 @@ DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments)
{
assert(symbol_table.getType(symb_id) == SymbolType::externalFunction);
auto it = external_function_node_map.find({ arguments, symb_id });
if (it != external_function_node_map.end())
if (auto it = external_function_node_map.find({arguments, symb_id});
it != external_function_node_map.end())
return it->second;
auto sp = make_unique<ExternalFunctionNode>(*this, node_list.size(), symb_id, arguments);
auto p = sp.get();
node_list.push_back(move(sp));
external_function_node_map[{ arguments, symb_id }] = p;
external_function_node_map.try_emplace({arguments, symb_id}, p);
return p;
}
expr_t
DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index)
DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index)
{
assert(symbol_table.getType(top_level_symb_id) == SymbolType::externalFunction);
auto it
if (auto it
= 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;
auto sp = make_unique<FirstDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index);
auto sp = make_unique<FirstDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id,
arguments, input_index);
auto p = sp.get();
node_list.push_back(move(sp));
first_deriv_external_function_node_map[{ arguments, input_index, top_level_symb_id }] = p;
first_deriv_external_function_node_map.try_emplace({arguments, input_index, top_level_symb_id},
p);
return p;
}
expr_t
DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2)
DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index1, int input_index2)
{
assert(symbol_table.getType(top_level_symb_id) == SymbolType::externalFunction);
auto it
= second_deriv_external_function_node_map.find({ arguments, input_index1, input_index2,
top_level_symb_id });
if (it != second_deriv_external_function_node_map.end())
if (auto it = second_deriv_external_function_node_map.find(
{arguments, input_index1, input_index2, top_level_symb_id});
it != second_deriv_external_function_node_map.end())
return it->second;
auto sp = make_unique<SecondDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index1, input_index2);
auto sp = make_unique<SecondDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id,
arguments, input_index1, input_index2);
auto p = sp.get();
node_list.push_back(move(sp));
second_deriv_external_function_node_map[{ 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;
}
expr_t
DataTree::AddSum(expr_t arg)
{
return AddUnaryOp(UnaryOpcode::sum, arg);
}
bool
DataTree::isSymbolUsed(int symb_id) const
{
for (const auto & it : variable_node_map)
if (it.first.first == symb_id)
if (ranges::any_of(views::keys(variable_node_map),
[=](const auto& symb_lag) { return symb_lag.first == symb_id; }))
return true;
if (local_variables_table.find(symb_id) != local_variables_table.end())
if (local_variables_table.contains(symb_id))
return true;
return false;
}
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();
}
SymbolType
DataTree::getTypeByDerivID(int deriv_id) const noexcept(false)
DataTree::getTypeByDerivID([[maybe_unused]] int deriv_id) const noexcept(false)
{
throw UnknownDerivIDException();
}
int
DataTree::getLagByDerivID(int deriv_id) const noexcept(false)
DataTree::getLagByDerivID([[maybe_unused]] int deriv_id) const noexcept(false)
{
throw UnknownDerivIDException();
}
int
DataTree::getSymbIDByDerivID(int deriv_id) const noexcept(false)
DataTree::getSymbIDByDerivID([[maybe_unused]] int deriv_id) const noexcept(false)
{
throw UnknownDerivIDException();
}
void
DataTree::addAllParamDerivId(set<int> &deriv_id_set)
{
}
int
DataTree::getDynJacobianCol(int deriv_id) const noexcept(false)
DataTree::getTypeSpecificIDByDerivID([[maybe_unused]] int deriv_id) const
{
throw UnknownDerivIDException();
}
bool
DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
void
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
DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
{
for (const auto & it : binary_op_node_map)
if (get<2>(it.first) == opcode)
return true;
return false;
return ranges::any_of(views::keys(unary_op_node_map),
[=](const auto& key) { return get<1>(key) == opcode; });
}
bool
DataTree::isTrinaryOpUsed(TrinaryOpcode opcode) const
DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const
{
for (const auto & it : trinary_op_node_map)
if (get<3>(it.first) == opcode)
return true;
return false;
}
bool
DataTree::isExternalFunctionUsed(int symb_id) const
set<int> var;
for (const auto& [key, value] : unary_op_node_map)
if (get<1>(key) == opcode)
{
for (const auto & it : external_function_node_map)
if (it.first.second == symb_id)
value->collectVariables(type, var);
if (!var.empty())
return true;
}
return false;
}
bool
DataTree::isFirstDerivExternalFunctionUsed(int symb_id) const
DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
{
for (const auto & it : first_deriv_external_function_node_map)
if (get<2>(it.first) == symb_id)
return true;
return false;
return ranges::any_of(views::keys(binary_op_node_map),
[=](const auto& key) { return get<2>(key) == opcode; });
}
bool
DataTree::isSecondDerivExternalFunctionUsed(int symb_id) const
DataTree::isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const
{
set<int> var;
for (const auto& [key, value] : binary_op_node_map)
if (get<2>(key) == opcode)
{
for (const auto & it : second_deriv_external_function_node_map)
if (get<3>(it.first) == symb_id)
value->collectVariables(type, var);
if (!var.empty())
return true;
}
return false;
}
......@@ -718,94 +897,94 @@ int
DataTree::minLagForSymbol(int symb_id) const
{
int r = 0;
for (const auto & it : variable_node_map)
if (it.first.first == symb_id && it.first.second < r)
r = it.first.second;
for (const auto& [symb_lag, expr] : variable_node_map)
if (symb_lag.first == symb_id)
r = min(r, symb_lag.second);
return r;
}
void
DataTree::writePowerDerivCHeader(ostream &output) const
DataTree::writeCHelpersDefinition(ostream& output) const
{
if (isBinaryOpUsed(BinaryOpcode::powerDeriv))
output << "double getPowerDeriv(double, double, int);" << 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
output << "// The k-th derivative of x^p" << endl
<< "inline double" << endl
<< "getPowerDeriv(double x, double p, int k)" << endl
<< "{" << endl
<< "#ifdef _MSC_VER" << endl
<< "# define nearbyint(x) (fabs((x)-floor(x)) < fabs((x)-ceil(x)) ? floor(x) : ceil(x))" << endl
<< "#endif" << endl
<< " if ( fabs(x) < " << near_zero << " && p > 0 && k > p && fabs(p-nearbyint(p)) < " << near_zero << " )" << endl
<< " if (fabs(x) < " << power_deriv_near_zero
<< " && p >= 0 && k > p && fabs(p-nearbyint(p)) < " << power_deriv_near_zero << ')'
<< endl
<< " return 0.0;" << endl
<< " else" << endl
<< " {" << endl
<< " int i = 0;" << endl
<< " double dxp = pow(x, p-k);" << endl
<< " for (; i<k; i++)" << endl
<< " for (int i = 0; i<k; i++)" << endl
<< " dxp *= p--;" << endl
<< " return dxp;" << 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
DataTree::writeNormcdfCHeader(ostream &output) const
DataTree::writeCHelpersDeclaration(ostream& output) const
{
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
if (isTrinaryOpUsed(TrinaryOpcode::normcdf))
output << "#ifdef _MSC_VER" << endl
<< "double normcdf(double);" << endl
<< "#endif" << endl;
#endif
if (isBinaryOpUsed(BinaryOpcode::powerDeriv))
output << "extern inline double getPowerDeriv(double x, double p, int k);" << endl;
if (isUnaryOpUsed(UnaryOpcode::sign))
output << "extern inline double sign(double x);" << endl;
}
void
DataTree::writeNormcdf(ostream &output) const
{
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
if (isTrinaryOpUsed(TrinaryOpcode::normcdf))
output << endl
<< "#ifdef _MSC_VER" << endl
<< "/*" << endl
<< " * Define normcdf for MSVC compiler" << endl
<< " */" << endl
<< "double normcdf(double x)" << endl
<< "{" << endl
<< "#if _MSC_VER >= 1700" << endl
<< " return 0.5 * erfc(-x * M_SQRT1_2);" << endl
<< "#else" << endl
<< " // From http://www.johndcook.com/blog/cpp_phi" << endl
<< " double a1 = 0.254829592;" << endl
<< " double a2 = -0.284496736;" << endl
<< " double a3 = 1.421413741;" << endl
<< " double a4 = -1.453152027;" << endl
<< " double a5 = 1.061405429;" << endl
<< " double p = 0.3275911;" << endl
<< " int sign = (x < 0) ? -1 : 1;" << endl
<< " 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
vector<string>
DataTree::strsplit(string_view str, char delim)
{
vector<string> result;
while (true)
{
size_t idx {str.find(delim)};
if (auto sub {str.substr(0, idx)}; !sub.empty())
result.emplace_back(sub);
if (idx == string_view::npos)
break;
str.remove_prefix(idx + 1);
}
return result;
}
filesystem::path
DataTree::packageDir(const string_view& package)
{
filesystem::path d;
for (const auto& it : strsplit(package, '.'))
d /= "+" + it;
return d;
}
string
DataTree::packageDir(const string &package)
void
DataTree::writeToFileIfModified(stringstream& new_contents, const filesystem::path& filename)
{
ifstream old_file {filename, ios::in | ios::binary};
if (old_file.is_open()
&& ranges::equal(istreambuf_iterator<char> {old_file}, istreambuf_iterator<char> {},
istreambuf_iterator<char> {new_contents}, istreambuf_iterator<char> {}))
return;
old_file.close();
new_contents.seekg(0);
ofstream new_file {filename, ios::out | ios::binary};
if (!new_file.is_open())
{
regex pat{"\\."};
string dirname = "+" + regex_replace(package, pat, "/+");
boost::filesystem::create_directories(dirname);
return dirname;
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.
*
......@@ -14,27 +14,31 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _DATATREE_HH
#define _DATATREE_HH
#ifndef DATA_TREE_HH
#define DATA_TREE_HH
using namespace std;
#include <string>
#include <cmath>
#include <filesystem>
#include <iomanip>
#include <map>
#include <vector>
#include <memory>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "SymbolTable.hh"
#include "NumericalConstants.hh"
#include "ExternalFunctionsTable.hh"
#include "ExprNode.hh"
#include "ExternalFunctionsTable.hh"
#include "HeterogeneityTable.hh"
#include "NumericalConstants.hh"
#include "SubModel.hh"
#include "SymbolTable.hh"
using namespace std;
class DataTree
{
......@@ -45,8 +49,14 @@ public:
NumericalConstants& num_constants;
//! A reference to the 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?
/* 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;
protected:
private:
//! num_constant_id -> NumConstNode
using num_const_node_map_t = map<int, NumConstNode*>;
num_const_node_map_t num_const_node_map;
......@@ -55,8 +65,10 @@ protected:
using variable_node_map_t = map<pair<int, int>, VariableNode*>;
variable_node_map_t variable_node_map;
//! (arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags) -> UnaryOpNode
using unary_op_node_map_t = map<tuple<expr_t, UnaryOpcode, int, int, int, string, vector<int>>, UnaryOpNode *>;
//! (arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags) ->
//! UnaryOpNode
using unary_op_node_map_t
= map<tuple<expr_t, UnaryOpcode, int, int, int, string, vector<int>>, UnaryOpNode*>;
unary_op_node_map_t unary_op_node_map;
//! ( arg1, arg2, opCode, order of Power Derivative) -> BinaryOpNode
......@@ -79,61 +91,73 @@ protected:
using pac_expectation_node_map_t = map<string, PacExpectationNode*>;
pac_expectation_node_map_t pac_expectation_node_map;
// model_name -> PacTargetNonstationaryNode
using pac_target_nonstationary_node_map_t = map<string, PacTargetNonstationaryNode*>;
pac_target_nonstationary_node_map_t pac_target_nonstationary_node_map;
// (arguments, deriv_idx, symb_id) -> FirstDerivExternalFunctionNode
using first_deriv_external_function_node_map_t = map<tuple<vector<expr_t>, int, int>, FirstDerivExternalFunctionNode *>;
using first_deriv_external_function_node_map_t
= map<tuple<vector<expr_t>, int, int>, FirstDerivExternalFunctionNode*>;
first_deriv_external_function_node_map_t first_deriv_external_function_node_map;
// (arguments, deriv_idx1, deriv_idx2, symb_id) -> SecondDerivExternalFunctionNode
using second_deriv_external_function_node_map_t = map<tuple<vector<expr_t>, int, int, int>, SecondDerivExternalFunctionNode *>;
using second_deriv_external_function_node_map_t
= map<tuple<vector<expr_t>, int, int, int>, SecondDerivExternalFunctionNode*>;
second_deriv_external_function_node_map_t second_deriv_external_function_node_map;
// Flag to disable simplifications related to commutativity of addition and multiplication
static bool no_commutativity;
protected:
//! Stores local variables value (maps symbol ID to corresponding node)
map<int, expr_t> local_variables_table;
//! Stores the order of appearance of local variables in the model block. Needed following change in #563
//! Stores the order of appearance of local variables in the model block. Needed following change
//! in #563
vector<int> local_variables_vector;
//! Internal implementation of AddVariable(), without the check on the lag
VariableNode *AddVariableInternal(int symb_id, int lag);
//! Internal implementation of ParamUsedWithLeadLag()
bool ParamUsedWithLeadLagInternal() const;
[[nodiscard]] bool ParamUsedWithLeadLagInternal() const;
/*! Takes a MATLAB/Octave package name (possibly with several levels nested using dots),
and returns the name of the corresponding filesystem directory (which
is created by the function if it does not exist).
In practice the package nesting is used for the planner_objective (stored
inside +objective subdir). */
static string packageDir(const string &package);
/* Writes the contents of “new_contents” to the file “filename”. However, if
the file already exists and would not be modified by this operation, then do
nothing. */
static void writeToFileIfModified(stringstream& new_contents, const filesystem::path& filename);
private:
const static int constants_precision{16};
constexpr static int constants_precision {16};
//! The list of nodes
vector<unique_ptr<ExprNode>> node_list;
inline expr_t AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set = 0, int param1_symb_id = 0, int param2_symb_id = 0, const string &adl_param_name = "", const vector<int> &adl_lags = vector<int>());
inline expr_t AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder = 0);
inline expr_t AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set = 0,
int param1_symb_id = 0, int param2_symb_id = 0,
const string& adl_param_name = "",
const vector<int>& adl_lags = vector<int>());
inline expr_t AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2,
int powerDerivOrder = 0);
inline expr_t AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3);
//! Initializes the predefined constants, used only from the constructors
void initConstants();
public:
DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg);
DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg, bool is_dynamic_arg = false);
virtual ~DataTree() = default;
virtual
~DataTree();
DataTree(const DataTree& d);
DataTree& operator=(const DataTree& d);
//! 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
class LocalVariableException
struct LocalVariableException
{
public:
string name;
LocalVariableException(string name_arg) : name(move(name_arg))
{
}
};
class DivisionByZeroException
......@@ -142,10 +166,13 @@ public:
inline expr_t AddPossiblyNegativeConstant(double val);
//! Adds a non-negative numerical constant (possibly Inf or NaN)
expr_t AddNonNegativeConstant(const string &value);
NumConstNode* AddNonNegativeConstant(const string& value);
//! Adds a variable
/*! The default implementation of the method refuses any lag != 0 */
virtual VariableNode *AddVariable(int symb_id, int lag = 0);
VariableNode* AddVariable(int symb_id, int lag = 0);
//! Gets a variable
/*! Same as AddVariable, except that it fails if the variable node has not
already been created */
[[nodiscard]] VariableNode* getVariable(int symb_id, int lag = 0) const;
//! Adds "arg1+arg2" to model tree
expr_t AddPlus(expr_t iArg1, expr_t iArg2);
//! Adds "arg1-arg2" to model tree
......@@ -210,12 +237,16 @@ public:
expr_t AddAtanh(expr_t iArg1);
//! Adds "sqrt(arg)" to model tree
expr_t AddSqrt(expr_t iArg1);
//! Adds "cbrt(arg)" to model tree
expr_t AddCbrt(expr_t iArg1);
//! Adds "abs(arg)" to model tree
expr_t AddAbs(expr_t iArg1);
//! Adds "sign(arg)" to model tree
expr_t AddSign(expr_t iArg1);
//! Adds "erf(arg)" to model tree
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
expr_t AddMax(expr_t iArg1, expr_t iArg2);
//! Adds "min(arg1,arg2)" to model tree
......@@ -231,94 +262,136 @@ public:
//! Add 2nd derivative of steady state w.r.t. parameter to model tree
expr_t AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id);
//! Adds "arg1=arg2" to model tree
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
expr_t AddVarExpectation(const string& model_name);
//! Adds pac_expectation command to model tree
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
void AddLocalVariable(int symb_id, expr_t value) noexcept(false);
//! Adds an external function node
expr_t AddExternalFunction(int symb_id, const vector<expr_t>& arguments);
//! Adds an external function node for the first derivative of an external function
expr_t AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index);
expr_t AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index);
//! Adds an external function node for the second derivative of an external function
expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2);
expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index1, int input_index2);
// Adds "SUM(arg)" to model tree
expr_t AddSum(expr_t arg);
//! 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
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
bool isBinaryOpUsed(BinaryOpcode opcode) const;
//! Checks if a given trinary op is used somewhere in the data tree
bool isTrinaryOpUsed(TrinaryOpcode opcode) const;
//! Checks if a given external function is used somewhere in the data tree
bool isExternalFunctionUsed(int symb_id) const;
//! 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 !!)
[[nodiscard]] bool isBinaryOpUsed(BinaryOpcode opcode) const;
//! Checks if a given binary op is used somewhere in the data tree on an endogenous variable
[[nodiscard]] bool isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const;
//! Returns the minimum lag (as a negative number) of the given symbol in the whole data tree (and
//! not only in the equations !!)
/*! Returns 0 if the symbol is not used */
int minLagForSymbol(int symb_id) const;
//! Write the C Header for getPowerDeriv when use_dll is used
void writePowerDerivCHeader(ostream &output) const;
//! Write getPowerDeriv in C
void writePowerDeriv(ostream &output) const;
//! Write the C Header for normcdf when use_dll is used
void writeNormcdfCHeader(ostream &output) const;
//! Write normcdf in C
void writeNormcdf(ostream &output) const;
[[nodiscard]] int minLagForSymbol(int symb_id) const;
/* Writes definitions of C function helpers (getPowerDeriv(), sign()) as
inline functions */
void writeCHelpersDefinition(ostream& output) const;
/* Writes declarations of C function helpers (getPowerDeriv(), sign()) as
extern inline (external definition). Those need to be included in exactly
one translation unit. That external definition will be used or not,
depending on the optimization decision by the compiler.
See https://en.cppreference.com/w/c/language/inline */
void writeCHelpersDeclaration(ostream& output) const;
//! Thrown when trying to access an unknown variable by deriv_id
class UnknownDerivIDException
{
};
//! Raised when a trend is declared twice
class TrendException
struct TrendException
{
public:
string name;
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
virtual int getDerivID(int symb_id, int lag) const noexcept(false);
virtual SymbolType getTypeByDerivID(int deriv_id) const noexcept(false);
virtual int getLagByDerivID(int deriv_id) const noexcept(false);
virtual int getSymbIDByDerivID(int deriv_id) const noexcept(false);
//! Returns the column of the dynamic Jacobian associated to a derivation ID
virtual int getDynJacobianCol(int deriv_id) const noexcept(false);
//! Adds to the set all the deriv IDs corresponding to parameters
virtual void addAllParamDerivId(set<int> &deriv_id_set);
/* Returns the column of the Jacobian associated to a derivation ID.
The “sparse” argument selects between the legacy representation and the
sparse representation. */
[[nodiscard]] virtual int
getJacobianCol([[maybe_unused]] int deriv_id, [[maybe_unused]] bool sparse) const
{
throw UnknownDerivIDException();
}
//! Returns bool indicating whether DataTree represents a Dynamic Model (returns true in DynamicModel.hh)
virtual bool
isDynamic() const
/* Returns the number of columns of the Jacobian
The “sparse” argument selects between the legacy representation and the
sparse representation. */
[[nodiscard]] virtual int
getJacobianColsNbr([[maybe_unused]] bool sparse) const
{
return false;
};
throw UnknownDerivIDException();
}
class UnknownLocalVariableException
//! Adds to the set all the deriv IDs corresponding to parameters
virtual void addAllParamDerivId(set<int>& deriv_id_set);
struct UnknownLocalVariableException
{
public:
//! Symbol ID
int id;
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);
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;
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
......@@ -329,7 +402,7 @@ DataTree::AddPossiblyNegativeConstant(double v)
if (isnan(v))
return NaN;
if (isinf(v))
return (v < 0 ? MinusInfinity : Infinity);
return v < 0 ? MinusInfinity : Infinity;
bool neg = false;
if (v < 0)
......@@ -349,21 +422,23 @@ DataTree::AddPossiblyNegativeConstant(double v)
}
inline expr_t
DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int param1_symb_id, int param2_symb_id, const string &adl_param_name, const vector<int> &adl_lags)
DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int param1_symb_id,
int param2_symb_id, const string& adl_param_name, const vector<int>& adl_lags)
{
// If the node already exists in tree, share it
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 (it != unary_op_node_map.end())
if (auto it = unary_op_node_map.find({arg, op_code, arg_exp_info_set, param1_symb_id,
param2_symb_id, adl_param_name, adl_lags});
it != unary_op_node_map.end())
return it->second;
// Try to reduce to a constant
// Case where arg is a constant and op_code == UnaryOpcode::uminus (i.e. we're adding a negative constant) is skipped
auto *carg = dynamic_cast<NumConstNode *>(arg);
if (op_code != UnaryOpcode::uminus || carg == nullptr)
// Case where arg is a constant and op_code == UnaryOpcode::uminus (i.e. we're adding a negative
// constant) is skipped
if (auto carg = dynamic_cast<NumConstNode*>(arg); op_code != UnaryOpcode::uminus || !carg)
{
try
{
double argval = arg->eval(eval_context_t());
double argval = arg->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double val = UnaryOpNode::eval_opcode(op_code, argval);
return AddPossiblyNegativeConstant(val);
}
......@@ -372,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();
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;
}
inline expr_t
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 (it != binary_op_node_map.end())
if (auto it = binary_op_node_map.find({arg1, arg2, op_code, powerDerivOrder});
it != binary_op_node_map.end())
return it->second;
// Try to reduce to a constant
try
{
double argval1 = arg1->eval(eval_context_t());
double argval2 = arg2->eval(eval_context_t());
double argval1 = arg1->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double argval2 = arg2->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder);
return AddPossiblyNegativeConstant(val);
}
......@@ -398,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();
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;
}
inline expr_t
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 (it != trinary_op_node_map.end())
if (auto it = trinary_op_node_map.find({arg1, arg2, arg3, op_code});
it != trinary_op_node_map.end())
return it->second;
// Try to reduce to a constant
try
{
double argval1 = arg1->eval(eval_context_t());
double argval2 = arg2->eval(eval_context_t());
double argval3 = arg3->eval(eval_context_t());
double argval1 = arg1->eval({});
double argval2 = arg2->eval({});
double argval3 = arg3->eval({});
double val = TrinaryOpNode::eval_opcode(argval1, op_code, argval2, argval3);
return AddPossiblyNegativeConstant(val);
}
......@@ -428,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 p = sp.get();
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;
}
......
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.
*
......@@ -14,39 +14,87 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _DYNAMICMODEL_HH
#define _DYNAMICMODEL_HH
using namespace std;
#ifndef DYNAMIC_MODEL_HH
#define DYNAMIC_MODEL_HH
#include <filesystem>
#include <fstream>
#include <boost/crc.hpp>
#include "Bytecode.hh"
#include "StaticModel.hh"
using namespace std;
//! Stores a dynamic model
class DynamicModel : public ModelTree
{
friend class StaticModel; // For reading static_mfs from converting constructor
public:
//! A reference to the trend component model table
TrendComponentModelTable& trend_component_model_table;
//! A reference to the 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:
// 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};
//! Stores equations declared as [static]
/*! They will be used in toStatic() to replace equations marked as [dynamic] */
/*! They will be used in the conversion to StaticModel to replace equations marked as [dynamic] */
vector<BinaryOpNode*> static_only_equations;
//! 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]
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>;
//! Maps a pair (symbol_id, lag) to a deriv ID
......@@ -54,215 +102,236 @@ private:
//! Maps a deriv ID to a pair (symbol_id, lag)
vector<pair<int, int>> inv_deriv_id_table;
//! Maps a deriv_id to the column index of the dynamic Jacobian
/*! Contains only endogenous, exogenous and exogenous deterministic */
/* Maps a deriv_id to the column index of the dynamic Jacobian, in the legacy
representation.
Contains only endogenous, exogenous and exogenous deterministic */
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)
/*! Set by computeDerivIDs() */
int max_lag, max_lead;
int max_lag {0}, max_lead {0};
//! Maximum lag and lead over endogenous variables (positive values)
/*! Set by computeDerivIDs() */
int max_endo_lag, max_endo_lead;
int max_endo_lag {0}, max_endo_lead {0};
//! Maximum lag and lead over exogenous variables (positive values)
/*! Set by computeDerivIDs() */
int max_exo_lag, max_exo_lead;
int max_exo_lag {0}, max_exo_lead {0};
//! Maximum lag and lead over deterministic exogenous variables (positive values)
/*! Set by computeDerivIDs() */
int max_exo_det_lag, max_exo_det_lead;
int max_exo_det_lag {0}, max_exo_det_lead {0};
//! Maximum lag and lead over all types of variables (positive values) of original model
int max_lag_orig, max_lead_orig;
int max_lag_orig {0}, max_lead_orig {0}, max_lag_with_diffs_expanded_orig {0};
//! Maximum lag and lead over endogenous variables (positive values) of original model
int max_endo_lag_orig, max_endo_lead_orig;
int max_endo_lag_orig {0}, max_endo_lead_orig {0};
//! Maximum lag and lead over exogenous variables (positive values) of original model
int max_exo_lag_orig, max_exo_lead_orig;
//! Maximum lag and lead over deterministic exogenous variables (positive values) of original model
int max_exo_det_lag_orig, max_exo_det_lead_orig;
int max_exo_lag_orig {0}, max_exo_lead_orig {0};
//! Maximum lag and lead over deterministic exogenous variables (positive values) of original
//! model
int max_exo_det_lag_orig {0}, max_exo_det_lead_orig {0};
//! Cross reference information
// Cross reference information: eq → set of (symb_id, lag) for each symbol type
map<int, ExprNode::EquationInfo> xrefs;
map<pair<int, int>, set<int>> xref_param;
map<pair<int, int>, set<int>> xref_endo;
map<pair<int, int>, set<int>> xref_exo;
map<pair<int, int>, set<int>> xref_exo_det;
// Reverse cross reference information: (symb_id, lag) → eqs
map<pair<int, int>, set<int>> xref_param, xref_endo, xref_exo, xref_exo_det;
//! Nonzero equations in the Hessian
map<int, string> nonzero_hessian_eqs;
set<int> nonzero_hessian_eqs;
//! Number of columns of dynamic jacobian
/*! Set by computeDerivID()s and computeDynJacobianCols() */
int dynJacobianColsNbr;
//! Temporary terms for block decomposed models
vector< vector<temporary_terms_t>> v_temporary_terms;
//! Creates mapping for variables and equations they are present in
map<int, set<int>> variableMapping;
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>
using first_chain_rule_derivatives_t = map< pair< int, pair< int, int>>, expr_t>;
first_chain_rule_derivatives_t first_chain_rule_derivatives;
//! Used for var_expectation and var_model
map<string, set<int>> var_expectation_functions_to_write;
// 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;
//! Writes dynamic model file (Julia version)
void writeDynamicJuliaFile(const string &dynamic_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;
//! Writes the code of the block-decomposed model in virtual machine bytecode
void writeDynamicBlockBytecode(const string& basename) const;
//! Writes the code of the model in virtual machine bytecode
void writeModelEquationsCode(const string &basename, const map_idx_t &map_idx) const;
void writeSetAuxiliaryVariables(const string &basename, const bool julia) const;
void writeAuxVarRecursiveDefinitions(ostream &output, ExprNodeOutputType output_type) const;
void writeDynamicBytecode(const string& basename) const;
//! Computes jacobian and prepares for equation normalization
/*! Using values from initval/endval blocks and parameter initializations:
- computes the jacobian for the model w.r. to contemporaneous variables
- removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff)
*/
//void evaluateJacobian(const eval_context_t &eval_context, jacob_map *j_m, bool dynamic);
// Write the block structure of the model in the driver file
void writeBlockDriverOutput(ostream& output) const;
//! return a map on the block jacobian
map<pair<pair<int, pair<int, int>>, pair<int, int>>, int> get_Derivatives(int block);
//! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables
void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives);
// Used by determineBlockDerivativesType()
enum class BlockDerivativeType
{
standard,
chainRule,
normalizedChainRule
};
string reform(string name) const;
map_idx_t map_idx;
/* For each tuple (lag, eq, var) within the given block, determine the type
of the derivative to be computed. Indices are within the block (i.e.
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 computeTemporaryTermsOrdered();
void computeChainRuleJacobian() override;
//! creates a mapping from the index of temporary terms to a natural index
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;
string reform(const string& name) const;
//! Get the type corresponding to a derivation ID
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;
//! Get the symbol ID corresponding to a derivation ID
int getSymbIDByDerivID(int deriv_id) const noexcept(false) override;
int getTypeSpecificIDByDerivID(int deriv_id) const override;
//! 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
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
/*! 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();
//! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
void collect_block_first_order_derivatives();
//! Collecte the informations about exogenous, deterministic exogenous and endogenous from the previous block for each block
void collectBlockVariables();
/* Compute the Jacobian column indices in the block decomposition case
(stored in blocks_jacob_cols_*).
Also fills auxiliary structures related to “other” endogenous and
exogenous: blocks{,_derivatives}_{other_endo,exo_exo_det} */
void computeBlockDynJacobianCols();
//! Factorized code for substitutions of leads/lags
/*! \param[in] type determines which type of variables is concerned
\param[in] deterministic_model whether we are in a deterministic model (only for exogenous leads/lags)
\param[in] subset variables to which to apply the transformation (only for diff of forward vars)
\param[in] deterministic_model whether we are in a deterministic model (only for exogenous
leads/lags) \param[in] subset variables to which to apply the transformation (only for diff of
forward vars)
*/
void substituteLeadLagInternal(AuxVarType type, bool deterministic_model, const vector<string> &subset);
private:
//! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
bool global_temporary_terms;
//! 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;
void substituteLeadLagInternal(AuxVarType type, bool deterministic_model,
const vector<string>& subset);
//! Help computeXrefs to compute the reverse references (i.e. param->eqs, endo->eqs, etc)
void computeRevXref(map<pair<int, int>, set<int>> &xrefset, const set<pair<int, int>> &eiref, int eqn);
void computeRevXref(map<pair<int, int>, set<int>>& xrefset, const set<pair<int, int>>& eiref,
int eqn);
//! Write reverse cross references
void writeRevXrefs(ostream &output, const map<pair<int, int>, set<int>> &xrefmap, const string &type) const;
//! 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;
//! List for each equation its block number
vector<int> equation_block;
//! Used for var_expectation and var_model
map<string, set<int>> var_expectation_functions_to_write;
//! Used for pac_expectation operator
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,
void writeRevXrefs(ostream& output, const map<pair<int, int>, set<int>>& xrefmap,
const string& type) const;
/* Writes MATLAB/Octave wrapper function for computing residuals and
derivatives at the same time (legacy representation) */
void writeDynamicMWrapperFunction(const string& name, const string& ending) const;
/* Helper for writing MATLAB/Octave functions for residuals/derivatives and
their temporary terms (legacy representation) */
void writeDynamicMFileHelper(const string& basename, const string& name, const string& retvalname,
const string& name_tt, size_t ttlen, const string& previous_tt_name,
const ostringstream& init_s, const ostringstream& end_s,
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
void writeDynamicMatlabCompatLayer(const string &basename) const;
/* Create the compatibility dynamic.m file for MATLAB/Octave not yet using
the temporary terms array interface (legacy representation) */
void writeDynamicMCompatFile(const string& basename) const;
//! Internal helper for the copy constructor and assignment operator
/*! Copies all the structures that contain ExprNode*, by the converting the
pointers into their equivalent in the new tree */
void copyHelper(const DynamicModel& m);
/* 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});
}
void getEquationNumbersFromTags(vector<int> &eqnumber, set<string> &eqtags) const;
// Used to check consistency of bind/relax tags; the keys are equation names
map<string, OccbinRegimeTracker> occbin_regime_trackers;
void findPacExpectationEquationNumbers(vector<int> &eqnumber) const;
protected:
string
modelClassName() const override
{
return "dynamic model";
}
public:
DynamicModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
DynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg,
TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg);
//! Adds a variable node
/*! This implementation allows for non-zero lag */
VariableNode *AddVariable(int symb_id, int lag = 0) override;
DynamicModel(const DynamicModel& m);
DynamicModel& operator=(const DynamicModel& m);
//! Compute cross references
void computeXrefs();
......@@ -270,23 +339,25 @@ public:
//! Write cross references
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 hessian whether 2nd derivatives w.r. to exo, exo_det and endo should be computed (implies jacobianExo = true)
\param thirdDerivatives whether 3rd derivatives w.r. to endo/exo/exo_det should be computed (implies jacobianExo = true)
\param paramsDerivsOrder order of derivatives w.r. to a pair (endo/exo/exo_det, parameter) to be computed (>0 implies jacobianExo = true)
\param eval_context evaluation context for normalization
\param no_tmp_terms if true, no temporary terms will be computed in the dynamic files
\param derivsOrder order of derivatives w.r. to exo, exo_det and endo should be computed
(implies jacobianExo = true when order >= 2) \param paramsDerivsOrder order of derivatives w.r.
to a pair (endo/exo/exo_det, parameter) to be computed (>0 implies jacobianExo = true) \param
eval_context evaluation context for normalization \param no_tmp_terms if true, no temporary
terms will be computed in the dynamic files
*/
void computingPass(bool jacobianExo, bool hessian, bool thirdDerivatives, int paramsDerivsOrder,
const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool use_dll, bool bytecode, const bool nopreprocessoroutput);
//! Writes model initialization and lead/lag incidence matrix to output
void writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const;
void computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t& eval_context,
bool no_tmp_terms, bool block, bool use_dll);
//! Writes information about the dynamic model to the driver file
void writeDriverOutput(ostream& output, bool compute_xrefs) const;
//! Write JSON AST
void writeJsonAST(ostream& output) const;
//! Write JSON variable mapping
void writeJsonVariableMapping(ostream& output) const;
//! Write JSON Output
void writeJsonOutput(ostream& output) const;
......@@ -299,67 +370,70 @@ public:
//! Write JSON Output representation of dynamic model after computing pass
void writeJsonComputingPassOutput(ostream& output, bool writeDetails) const;
//! Write JSON prams derivatives file
void writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const;
//! Write JSON params derivatives
void writeJsonParamsDerivatives(ostream& output, bool writeDetails) const;
//! Write cross reference output if the xref maps have been filed
void writeJsonXrefs(ostream& output) const;
void writeJsonXrefsHelper(ostream &output, const map<pair<int, int>, set<int>> &xrefs) const;
void writeJsonXrefsHelper(ostream& output, const map<pair<int, int>, set<int>>& xrefmap) const;
//! Print equations that have non-zero second derivatives
void printNonZeroHessianEquations(ostream& output) const;
//! Set the equations that have non-zero second derivatives
void setNonZeroHessianEquations(map<int, string> &eqs);
//! Fill Autoregressive Matrix for var_model/trend_component_model
void fillAutoregressiveMatrix(map<string, map<tuple<int, int, int>, expr_t>> &ARr, bool is_trend_component_model) const;
//! Tells whether Hessian has been computed
/*! This is needed to know whether no non-zero equation in Hessian means a
zero Hessian or Hessian not computed */
bool
isHessianComputed() const
{
return computed_derivs_order >= 2;
}
//! Fill Error Component Matrix for trend_component_model
void fillErrorComponentMatrix(map<string, map<tuple<int, int, int>, expr_t>> &ECr, ExprNode::subst_table_t &diff_subst_table) const;
/* Check whether the model is linear, by verifying that the hessian is zero,
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 fillTrendComponentModelTableFromOrigModel(StaticModel &static_model) const;
void fillTrendComponentmodelTableAREC(ExprNode::subst_table_t &diff_subst_table) const;
//! Fill the Var Model Table
//! Fill the trend component model table with information available from the original model
void fillTrendComponentModelTableFromOrigModel() const;
/* Fill the trend component model table with information about AR/EC
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 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
//! after substitution of auxiliary variables and find the trend variables
//! in the trend_component model
void updateVarAndTrendModel() const;
//! Add aux equations (and aux variables) for variables declared in var_model
//! at max order if they don't already exist
void addEquationsForVar();
//! 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;
//! Writes dynamic model file
void writeDynamicFile(const string &basename, bool block, bool bytecode, bool use_dll, int order, bool julia) const;
//! Writes dynamic model file (+ bytecode)
void writeDynamicFile(const string& basename, bool use_dll, const string& mexext,
const filesystem::path& matlabroot, bool julia) const;
//! 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 static model (only the equations)
/*! It assumes that the static model given in argument has just been allocated */
void toStatic(StaticModel &static_model) const;
//! Expands equation tags with default equation names (available "name" tag or LHS variable or
//! equation ID)
void expandEqTags();
//! Find endogenous variables not used in model
set<int> findUnusedEndogenous();
......@@ -369,20 +443,36 @@ public:
//! Set the max leads/lags of the original model
void setLeadsLagsOrig();
//! Copies a dynamic model (only the equations)
/*! It assumes that the dynamic model given in argument has just been allocated */
void cloneDynamic(DynamicModel &dynamic_model) const;
//! update equations after variable type change in model block
void updateAfterVariableChange(DynamicModel &dynamic_model);
//! Implements the include_eqs/exclude_eqs options
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 model equations with derivatives of Lagrangian w.r.t. endogenous
void computeRamseyPolicyFOCs(const StaticModel &static_model, const bool nopreprocessoroutput);
//! Replaces the model equations in dynamic_model with those in this model
void replaceMyEquations(DynamicModel& dynamic_model) const;
//! 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
size_t staticOnlyEquationsNbr() const;
......@@ -390,22 +480,66 @@ public:
//! Returns number of dynamic only equations
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
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)
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 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
bool
isDynamic() const override
int
getJacobianCol(int deriv_id, bool sparse) 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
void runTrendTest(const eval_context_t& eval_context);
......@@ -427,36 +561,134 @@ public:
//! Transforms the model by removing all UnaryOpcode::expectation
void substituteExpectation(bool partial_information_model);
//! Transforms the model by decreasing the lead/lag of predetermined variables in model equations by one
//! Transforms the model by decreasing the lead/lag of predetermined variables in model equations
//! by one
void transformPredeterminedVariables();
// Performs the transformations associated to variables declared with “var(log)”
void substituteLogTransform();
/* 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
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
void substituteAdl();
//! Creates aux vars for all unary operators
void substituteUnaryOps(StaticModel &static_model);
//! Substitutes out all model-local variables
void substituteModelLocalVariables();
//! Creates aux vars for certain unary operators: originally implemented for support of VARs
void substituteUnaryOps(StaticModel &static_model, set<string> &eq_tags);
/* Creates aux vars for all unary operators in all equations. Also makes the
substitution in growth terms of pac_model/pac_target_info and in
expressions of var_expectation_model. */
pair<lag_equivalence_table_t, ExprNode::subst_table_t>
substituteUnaryOps(VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table);
//! Creates aux vars for certain unary operators: originally implemented for support of VARs
void substituteUnaryOps(StaticModel &static_model, vector<int> &eqnumbers);
/* Creates aux vars for all unary operators in specified equations. Also makes the
substitution in growth terms of pac_model/pac_target_info and in
expressions of var_expectation_model. */
pair<lag_equivalence_table_t, ExprNode::subst_table_t>
substituteUnaryOps(const set<int>& eqnumbers,
VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table);
//! 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
void substituteVarExpectation(const map<string, expr_t>& subst_table);
//! Return max lag of pac equation
int getPacMaxLag(const string &pac_model_name) const;
void analyzePacEquationStructure(const string& name, map<string, string>& pac_eq_name,
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
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
void removeTrendVariableFromEquations();
......@@ -469,198 +701,265 @@ public:
//! Fills eval context with values of model local variables and auxiliary variables
void fillEvalContext(eval_context_t& eval_context) const;
//! Return the number of blocks
unsigned int
getNbBlocks() const override
{
return (block_type_firstequation_size_mfs.size());
};
//! 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())
/*! Checks that all pac_expectation operators have been substituted, error
out otherwise */
void checkNoRemainingPacExpectation() const;
/*! Checks that all pac_target_nonstationary operators have been substituted, error
out otherwise */
void checkNoRemainingPacTargetNonstationary() const;
auto
getStaticOnlyEquationsInfo() const
{
auto it1 = it->second.find(variable_number);
if (it1 != it->second.end())
return it1->second;
else
return -1;
return tuple {static_only_equations, static_only_equations_lineno,
static_only_complementarity_conditions, static_only_equations_equation_tags};
}
else
return (-1);
};
//! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
//! Returns true if a parameter was used in the model block with a lead or lag
bool ParamUsedWithLeadLag() const;
bool isChecksumMatching(const string& basename) const;
//! 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
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);
if (it1 != it->second.end())
return it1->second;
else
return -1;
return mfs;
}
else
return (-1);
};
//! 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())
void
setMFS(int mfs_arg)
{
auto it1 = it->second.find(variable_number);
if (it1 != it->second.end())
return it1->second;
else
return -1;
mfs = mfs_arg;
}
else
return (-1);
};
bool isModelLocalVariableUsed() const;
//! Returns true if a parameter was used in the model block with a lead or lag
bool ParamUsedWithLeadLag() const;
void
setStaticMFS(int static_mfs_arg)
{
static_mfs = static_mfs_arg;
}
bool isChecksumMatching(const string &basename) 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
class derivative
template<bool julia>
void
DynamicModel::writeParamsDerivativesFile(const string& basename) const
{
public:
long unsigned int linear_address;
long unsigned int col_nbr;
unsigned int row_nbr;
expr_t value;
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)
{
};
};
if (!params_derivatives.size())
return;
constexpr ExprNodeOutputType output_type {julia ? ExprNodeOutputType::juliaDynamicModel
: ExprNodeOutputType::matlabDynamicModel};
auto [tt_output, rp_output, gp_output, rpp_output, gpp_output, hp_output,
g3p_output] {writeParamsDerivativesFileHelper<output_type>()};
class derivative_less_than
if constexpr (!julia)
{
public:
bool
operator()(const derivative &d1, const derivative &d2) const
filesystem::path filename {packageDir(basename) / "dynamic_params_derivs.m"};
ofstream paramsDerivsFile {filename, ios::out | ios::binary};
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
Source diff could not be displayed: it is too large. Options to address this: view the blob.
/* -*- C++ -*- */
/*
* Copyright (C) 2003-2018 Dynare Team
* Copyright © 2003-2025 Dynare Team
*
* This file is part of Dynare.
*
......@@ -15,16 +15,15 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
%{
using namespace std;
#include <cstring>
#include "ParsingDriver.hh"
using namespace std;
// Announce to Flex the prototype we want for lexing function
#define YY_DECL \
Dynare::parser::token_type \
......@@ -41,11 +40,10 @@ using token = Dynare::parser::token;
#define yyterminate() return Dynare::parser::token_type(0);
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;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
%}
%option c++
......@@ -61,7 +59,6 @@ string eofbuff;
%x VERBATIM_BLOCK
%x NATIVE
%x NATIVE_COMMENT
%x DATES_STATEMENT
%x LINE1
%x LINE2
%x LINE3
......@@ -71,7 +68,9 @@ string eofbuff;
#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() */
......@@ -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 */
<*>^@#line\ \" { line_caller = YYSTATE; BEGIN(LINE1); }
<LINE1>[^\"]* {
filename = string(yytext);
filename = yytext;
BEGIN(LINE2);
}
<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
}
/* 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,DATES_STATEMENT,LINE1,LINE2,LINE3>[\n]+ { yylloc->step(); }
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,LINE1,LINE2,LINE3>[[:space:]]+ { yylloc->step(); }
/* Comments */
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>%.*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>\/{2}.*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>"/*" {comment_caller = YY_START; BEGIN COMMENT;}
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>%.*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>"//".*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>"/*" {comment_caller = YY_START; BEGIN COMMENT;}
<COMMENT>"*/" {BEGIN comment_caller;}
<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
<INITIAL>predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;}
<INITIAL>parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;}
<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>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>data {BEGIN DYNARE_STATEMENT; return token::DATA;}
<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
<INITIAL>var_expectation_model {BEGIN DYNARE_STATEMENT; return token::VAR_EXPECTATION_MODEL;}
<INITIAL>pac_model {BEGIN DYNARE_STATEMENT; return token::PAC_MODEL;}
<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>ramsey_model {BEGIN DYNARE_STATEMENT; return token::RAMSEY_MODEL;}
<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>identification {BEGIN DYNARE_STATEMENT; return token::IDENTIFICATION;}
<INITIAL>bvar_density {BEGIN DYNARE_STATEMENT; return token::BVAR_DENSITY; }
<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>histval_file {BEGIN DYNARE_STATEMENT; return token::HISTVAL_FILE;}
<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
<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>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>ms_estimation {BEGIN DYNARE_STATEMENT; return token::MS_ESTIMATION;}
<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
<INITIAL>ms_variance_decomposition {BEGIN DYNARE_STATEMENT; return token::MS_VARIANCE_DECOMPOSITION;}
<INITIAL>conditional_forecast {BEGIN DYNARE_STATEMENT; return token::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>smm_estimation {BEGIN DYNARE_STATEMENT; return token::SMM_ESTIMATION;}
<INITIAL>method_of_moments {BEGIN DYNARE_STATEMENT; return token::METHOD_OF_MOMENTS;}
<INITIAL>markov_switching {BEGIN DYNARE_STATEMENT; return token::MARKOV_SWITCHING;}
<INITIAL>svar {BEGIN DYNARE_STATEMENT; return token::SVAR;}
......@@ -186,12 +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>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_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>; {
if (!sigma_e)
BEGIN INITIAL;
return Dynare::parser::token_type (yytext[0]);
}
<DYNARE_STATEMENT>; {BEGIN INITIAL; return Dynare::parser::token_type (yytext[0]);}
/* Begin of a Dynare block */
......@@ -200,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>endval {BEGIN DYNARE_BLOCK; return token::ENDVAL;}
<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>heteroskedastic_shocks {BEGIN DYNARE_BLOCK; return token::HETEROSKEDASTIC_SHOCKS;}
<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>estimated_params {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS;}
<INITIAL>epilogue {BEGIN DYNARE_BLOCK; return token::EPILOGUE;}
......@@ -209,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>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_remove {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_REMOVE;}
<INITIAL>osr_params_bounds {BEGIN DYNARE_BLOCK; return token::OSR_PARAMS_BOUNDS;}
<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>homotopy_setup {BEGIN DYNARE_BLOCK; return token::HOMOTOPY_SETUP;}
<INITIAL>conditional_forecast_paths {BEGIN DYNARE_BLOCK; return token::CONDITIONAL_FORECAST_PATHS;}
......@@ -218,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>irf_calibration {BEGIN DYNARE_BLOCK; return token::IRF_CALIBRATION;}
<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>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 */
<INITIAL>; {return Dynare::parser::token_type (yytext[0]);}
......@@ -230,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>options {return token::OPTIONS;}
<DYNARE_STATEMENT>prior {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::PRIOR;
}
<INITIAL>std {BEGIN DYNARE_STATEMENT; return token::STD;}
......@@ -240,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>posterior_function {BEGIN DYNARE_STATEMENT; return token::POSTERIOR_FUNCTION;}
/* Inside of a Dynare statement */
<DYNARE_STATEMENT>{DATE} {
char *yycopy = strdup(yytext);
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,DYNARE_BLOCK>{DATE} {
yylval->emplace<string>(yytext);
return token::DATE;
}
<DYNARE_STATEMENT>${DATE} { yylloc->step();
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6)
yyout << yytext + 1;
#else
*yyout << yytext + 1;
#endif
}
<DYNARE_STATEMENT>dates {dates_parens_nb=0; BEGIN DATES_STATEMENT; yylval->build<string>("dates");}
/* Inside a Dynare statement */
<DYNARE_STATEMENT>file {return token::FILE;}
<DYNARE_STATEMENT>datafile {return token::DATAFILE;}
<DYNARE_STATEMENT>dirname {return token::DIRNAME;}
......@@ -274,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>stdev {return token::STDEV;}
<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>mode {return token::MODE;}
<DYNARE_STATEMENT>interval {return token::INTERVAL;}
......@@ -285,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>prefilter {return token::PREFILTER;}
<DYNARE_STATEMENT>presample {return token::PRESAMPLE;}
<DYNARE_STATEMENT>lik_algo {return token::LIK_ALGO;}
<DYNARE_STATEMENT>lik_init {return token::LIK_INIT;}
<DYNARE_STATEMENT>taper_steps {return token::TAPER_STEPS;}
<DYNARE_STATEMENT>geweke_interval {return token::GEWEKE_INTERVAL;}
<DYNARE_STATEMENT>raftery_lewis_qrs {return token::RAFTERY_LEWIS_QRS;}
<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>nograph {return token::NOGRAPH;}
<DYNARE_STATEMENT>posterior_graph {return token::POSTERIOR_GRAPH;}
<DYNARE_STATEMENT>posterior_nograph {return token::POSTERIOR_NOGRAPH;}
<DYNARE_STATEMENT>nodisplay {return token::NODISPLAY;}
<DYNARE_STATEMENT>graph_format {return token::GRAPH_FORMAT;}
<DYNARE_STATEMENT>eps {yylval->build<string>(yytext); return token::EPS;}
<DYNARE_STATEMENT>pdf {yylval->build<string>(yytext); return token::PDF;}
<DYNARE_STATEMENT>fig {yylval->build<string>(yytext); return token::FIG;}
<DYNARE_STATEMENT>none {yylval->build<string>(yytext); return token::NONE;}
<DYNARE_STATEMENT>eps {yylval->emplace<string>(yytext); return token::EPS;}
<DYNARE_STATEMENT>pdf {yylval->emplace<string>(yytext); return token::PDF;}
<DYNARE_STATEMENT>fig {yylval->emplace<string>(yytext); return token::FIG;}
<DYNARE_STATEMENT>none {yylval->emplace<string>(yytext); return token::NONE;}
<DYNARE_STATEMENT>print {return token::PRINT;}
<DYNARE_STATEMENT>noprint {return token::NOPRINT;}
<DYNARE_STATEMENT>conf_sig {return token::CONF_SIG;}
......@@ -309,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_jscale {return token::MH_JSCALE;}
<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_guess {return token::MH_TUNE_GUESS;}
<DYNARE_STATEMENT>mode_file {return token::MODE_FILE;}
<DYNARE_STATEMENT>mode_compute {return token::MODE_COMPUTE;}
<DYNARE_STATEMENT>mode_check {return token::MODE_CHECK;}
......@@ -317,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_number_of_points {return token::MODE_CHECK_NUMBER_OF_POINTS;}
<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>load_mh_file {return token::LOAD_MH_FILE;}
<DYNARE_STATEMENT>load_results_after_load_mh {return token::LOAD_RESULTS_AFTER_LOAD_MH;}
......@@ -328,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>fast_kalman_filter {return token::FAST_KALMAN_FILTER;}
<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>forecast {return token::FORECAST;}
<DYNARE_STATEMENT>smoother {return token::SMOOTHER;}
......@@ -343,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>tex {return token::TEX;}
<DYNARE_STATEMENT>nomoments {return token::NOMOMENTS;}
<DYNARE_STATEMENT>nomodelsummary {return token::NOMODELSUMMARY;}
<DYNARE_STATEMENT>std {return token::STD;}
<DYNARE_STATEMENT>corr {return token::CORR;}
<DYNARE_STATEMENT>nocorr {return token::NOCORR;}
<DYNARE_STATEMENT>optim {return token::OPTIM;}
<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>var_model_name {return token::VAR_MODEL_NAME;}
<DYNARE_STATEMENT>auxiliary_model_name {return token::AUXILIARY_MODEL_NAME;}
<DYNARE_STATEMENT>endogenous_terminal_period {return token::ENDOGENOUS_TERMINAL_PERIOD;}
<DYNARE_STATEMENT>sub_draws {return token::SUB_DRAWS;}
......@@ -361,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>noconstant {return token::NOCONSTANT;}
<DYNARE_STATEMENT>filename {return token::FILENAME;}
<DYNARE_STATEMENT>conditional_likelihood {return token::CONDITIONAL_LIKELIHOOD;}
<DYNARE_STATEMENT>diffuse_filter {return token::DIFFUSE_FILTER;}
<DYNARE_STATEMENT>plot_priors {return token::PLOT_PRIORS;}
<DYNARE_STATEMENT>aim_solver {return token::AIM_SOLVER;}
......@@ -384,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>nlags {return token::NLAGS;}
<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>diff {return token::DIFF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>diff {return token::DIFF;}
<DYNARE_STATEMENT>cross_restrictions {return token::CROSS_RESTRICTIONS;}
<DYNARE_STATEMENT>contemp_reduced_form {return token::CONTEMP_REDUCED_FORM;}
<DYNARE_STATEMENT>real_pseudo_forecast {return token::REAL_PSEUDO_FORECAST;}
......@@ -405,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>use_univariate_filters_if_singularity_is_detected {return token::USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED;}
<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>init2shocks {return token::INIT2SHOCKS;}
<DYNARE_STATEMENT>number_of_particles {return token::NUMBER_OF_PARTICLES;}
<DYNARE_STATEMENT>resampling {return token::RESAMPLING;}
......@@ -416,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>smooth {return token::SMOOTH;}
<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>amisanotristani {return token::AMISANOTRISTANI;}
<DYNARE_STATEMENT>murrayjonesparslow {return token::MURRAYJONESPARSLOW;}
......@@ -430,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>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>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 {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::ALPHA;
}
<DYNARE_STATEMENT>beta {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::BETA;
}
<DYNARE_STATEMENT>gamma {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::GAMMA;
}
<DYNARE_STATEMENT>inv_gamma {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::INV_GAMMA;
}
<DYNARE_STATEMENT>inv_gamma1 {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::INV_GAMMA1;
}
<DYNARE_STATEMENT>inv_gamma2 {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::INV_GAMMA2;
}
<DYNARE_STATEMENT>dirichlet {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::DIRICHLET;
}
<DYNARE_STATEMENT>weibull {
yylval->build<string>(yytext);
return token::WEIBULL;
}
<DYNARE_STATEMENT>weibull {return token::WEIBULL;}
<DYNARE_STATEMENT>normal {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::NORMAL;
}
<DYNARE_STATEMENT>uniform {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::UNIFORM;
}
<DYNARE_STATEMENT>gsig2_lmdm {return token::GSIG2_LMDM;}
......@@ -479,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>nstd {return token::NSTD;}
<DYNARE_STATEMENT>ninv {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::NINV;
}
<DYNARE_STATEMENT>indxparr {return token::INDXPARR;}
<DYNARE_STATEMENT>indxovr {return token::INDXOVR;}
<DYNARE_STATEMENT>aband {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::ABAND;
}
<DYNARE_STATEMENT>write_equation_tags {return token::WRITE_EQUATION_TAGS;}
......@@ -502,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>eq_ms {return token::EQ_MS;}
<DYNARE_STATEMENT>cms {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::CMS;
}
<DYNARE_STATEMENT>ncms {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::NCMS;
}
<DYNARE_STATEMENT>eq_cms {return token::EQ_CMS;}
<DYNARE_STATEMENT>tlindx {return token::TLINDX;}
<DYNARE_STATEMENT>tlnumber {return token::TLNUMBER;}
<DYNARE_STATEMENT>cnum {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::CNUM;
}
<DYNARE_STATEMENT>nodecomposition {return token::NODECOMPOSITION;};
......@@ -551,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_repeated_optimization_runs {return token::MAX_REPEATED_OPTIMIZATION_RUNS;}
<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>parameter_convergence_criterion {return token::PARAMETER_CONVERGENCE_CRITERION;}
<DYNARE_STATEMENT>number_of_large_perturbations {return token::NUMBER_OF_LARGE_PERTURBATIONS;}
......@@ -562,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>tolx {return token::TOLX;}
<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>hessian {
yylval->build<string>(yytext);
return token::HESSIAN;
}
<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>hessian {return token::HESSIAN;}
<DYNARE_STATEMENT>prior_variance {return token::PRIOR_VARIANCE;}
<DYNARE_STATEMENT>identity_matrix {return token::IDENTITY_MATRIX;}
<DYNARE_STATEMENT>mcmc_jumping_covariance {return token::MCMC_JUMPING_COVARIANCE;}
/* These four (var, varexo, varexo_det, parameters) are for change_type */
......@@ -596,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_steps {return token::HOMOTOPY_STEPS; }
<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>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>parameter_set {return token::PARAMETER_SET; }
<DYNARE_STATEMENT>init_state {return token::INIT_STATE; }
<DYNARE_STATEMENT>fast_realtime {return token::FAST_REALTIME; }
<DYNARE_STATEMENT>save_realtime {return token::SAVE_REALTIME;}
<DYNARE_STATEMENT>detail_plot {return token::DETAIL_PLOT;}
<DYNARE_STATEMENT>flip {return token::FLIP;}
<DYNARE_STATEMENT>interactive {return token::INTERACTIVE;}
<DYNARE_STATEMENT>screen_shocks {return token::SCREEN_SHOCKS;}
<DYNARE_STATEMENT>steadystate {return token::STEADYSTATE;}
......@@ -611,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>yoy {return token::YOY; }
<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>write_xls {return token::WRITE_XLS;}
<DYNARE_STATEMENT>realtime {return token::REALTIME;}
......@@ -623,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>k_order_solver {return token::K_ORDER_SOLVER; }
<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>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>pruning {return token::PRUNING; }
<DYNARE_STATEMENT>save_draws {return token::SAVE_DRAWS; }
......@@ -633,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>growth_factor {return token::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>discretionary_tol {return token::DISCRETIONARY_TOL;}
<DYNARE_STATEMENT>analytic_derivation {return token::ANALYTIC_DERIVATION;}
......@@ -641,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>endogenous_prior {return token::ENDOGENOUS_PRIOR;}
<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>infile {return token::INFILE;}
<DYNARE_STATEMENT>invars {return token::INVARS;}
......@@ -653,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>silent_optimizer {return token::SILENT_OPTIMIZER;}
<DYNARE_STATEMENT>lmmcp {return token::LMMCP;}
<DYNARE_STATEMENT>occbin {return token::OCCBIN;}
<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>additional_optimizer_steps {return token::ADDITIONAL_OPTIMIZER_STEPS;}
<DYNARE_STATEMENT>bartlett_kernel_lag {return token::BARTLETT_KERNEL_LAG; }
<DYNARE_STATEMENT>optimal {
yylval->build<string>(yytext);
return token::OPTIMAL;
}
<DYNARE_STATEMENT>diagonal {
yylval->build<string>(yytext);
return token::DIAGONAL;
}
<DYNARE_STATEMENT>gmm {return token::GMM;}
<DYNARE_STATEMENT>smm {return token::SMM;}
<DYNARE_STATEMENT>irf_matching {return token::IRF_MATCHING;}
<DYNARE_STATEMENT>stoch_simul {return token::STOCH_SIMUL;}
<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>verbose {return token::VERBOSE; }
<DYNARE_STATEMENT>simulation_multiple {return token::SIMULATION_MULTIPLE; }
<DYNARE_STATEMENT>burnin {return token::BURNIN; }
<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>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>irf_in_percent {return token::IRF_IN_PERCENT; }
<DYNARE_STATEMENT>emas_girf {return token::EMAS_GIRF; }
......@@ -679,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_max_iter {return token::EMAS_MAX_ITER; }
<DYNARE_STATEMENT>variable {return token::VARIABLE;}
<DYNARE_STATEMENT>[\$][^$]*[\$] {
strtok(yytext+1, "$");
yylval->build<string>(yytext + 1);
<DYNARE_STATEMENT>no_identification_strength {return token::NO_IDENTIFICATION_STRENGTH;}
<DYNARE_STATEMENT>no_identification_reducedform {return token::NO_IDENTIFICATION_REDUCEDFORM;}
<DYNARE_STATEMENT>no_identification_moments {return token::NO_IDENTIFICATION_MOMENTS;}
<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;
}
/* Inside a Dynare block */
<DYNARE_BLOCK>var {return token::VAR;}
<DYNARE_BLOCK>varexo {return token::VAREXO;}
<DYNARE_BLOCK>stderr {return token::STDERR;}
<DYNARE_BLOCK>values {return token::VALUES;}
<DYNARE_BLOCK>corr {return token::CORR;}
<DYNARE_BLOCK>periods {return token::PERIODS;}
<DYNARE_BLOCK>cutoff {return token::CUTOFF;}
<DYNARE_BLOCK>mfs {return token::MFS;}
<DYNARE_BLOCK>scales {return token::SCALES;}
<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>beta_pdf {return token::BETA_PDF;}
<DYNARE_BLOCK>normal_pdf {return token::NORMAL_PDF;}
......@@ -703,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>weibull_pdf {return token::WEIBULL_PDF;}
<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>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 */
<DYNARE_STATEMENT>solve_algo {return token::SOLVE_ALGO;}
......@@ -717,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>drop {return token::DROP;}
<DYNARE_STATEMENT>order {return token::ORDER;}
<DYNARE_STATEMENT>sylvester {return token::SYLVESTER;}
<DYNARE_STATEMENT>lyapunov {return token::LYAPUNOV;}
<DYNARE_STATEMENT>dr {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
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_doubling_tol {return token::LYAPUNOV_DOUBLING_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_maxiter {return token::DR_LOGARITHMIC_REDUCTION_MAXITER;}
<DYNARE_STATEMENT>replic {return token::REPLIC;}
......@@ -738,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>bandpass_filter {return token::BANDPASS_FILTER;}
<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>qz_criterium {return token::QZ_CRITERIUM;}
<DYNARE_STATEMENT>qz_zero_threshold {return token::QZ_ZERO_THRESHOLD;}
......@@ -747,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>series {return token::SERIES;}
<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_latex_name {return token::PLANNER_DISCOUNT_LATEX_NAME;}
<DYNARE_STATEMENT>calibration {return token::CALIBRATION;}
<DYNARE_STATEMENT>irf_plot_threshold {return token::IRF_PLOT_THRESHOLD;}
<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>diagonal_only {return token::DIAGONAL_ONLY;}
......@@ -759,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>coeff {return token::COEFF;}
<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>lower_cholesky {return token::LOWER_CHOLESKY;}
<DYNARE_STATEMENT>chain {return token::CHAIN;}
......@@ -768,42 +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>variances {return token::VARIANCES;}
<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>[\\] {return Dynare::parser::token_type (yytext[0]);}
<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_BLOCK>use_dll {return token::USE_DLL;}
<DYNARE_BLOCK>block {return token::BLOCK;}
<DYNARE_BLOCK>bytecode {return token::BYTECODE;}
<DYNARE_STATEMENT,DYNARE_BLOCK>use_dll {return token::USE_DLL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>block {return token::BLOCK;}
<DYNARE_STATEMENT,DYNARE_BLOCK>bytecode {return token::BYTECODE;}
<DYNARE_BLOCK>all_values_required {return token::ALL_VALUES_REQUIRED;}
<DYNARE_BLOCK>no_static {return token::NO_STATIC;}
<DYNARE_BLOCK>differentiate_forward_vars {return token::DIFFERENTIATE_FORWARD_VARS;}
<DYNARE_BLOCK>parallel_local_files {return token::PARALLEL_LOCAL_FILES;}
<DYNARE_STATEMENT,DYNARE_BLOCK>no_static {return token::NO_STATIC;}
<DYNARE_STATEMENT,DYNARE_BLOCK>differentiate_forward_vars {return token::DIFFERENTIATE_FORWARD_VARS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>parallel_local_files {return token::PARALLEL_LOCAL_FILES;}
<DYNARE_STATEMENT,DYNARE_BLOCK>linear {return token::LINEAR;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[,] {return token::COMMA;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[:] {return Dynare::parser::token_type (yytext[0]);}
<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>[\]] {
if (sigma_e)
sigma_e = 0;
return Dynare::parser::token_type (yytext[0]);
}
<DYNARE_STATEMENT,DYNARE_BLOCK>[+] {return token::PLUS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[-] {return token::MINUS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[*] {return token::TIMES;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[/] {return token::DIVIDE;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[=] {return token::EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[<] {return token::LESS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[>] {return token::GREATER;}
<DYNARE_STATEMENT,DYNARE_BLOCK>">=" {return token::GREATER_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>"<=" {return token::LESS_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>"==" {return token::EQUAL_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>"!=" {return token::EXCLAMATION_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[\^] {return token::POWER;}
<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 token::PLUS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>- {return token::MINUS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>\* {return token::TIMES;}
<DYNARE_STATEMENT,DYNARE_BLOCK>\/ {return token::DIVIDE;}
<DYNARE_STATEMENT,DYNARE_BLOCK>= {return token::EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>< {return token::LESS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>> {return token::GREATER;}
<DYNARE_STATEMENT,DYNARE_BLOCK>>= {return token::GREATER_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK><= {return token::LESS_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>== {return token::EQUAL_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>!= {return token::EXCLAMATION_EQUAL;}
<DYNARE_BLOCK>\+= {return token::PLUS_EQUAL;}
<DYNARE_BLOCK>\*= {return token::TIMES_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>\^ {return token::POWER;}
<DYNARE_STATEMENT,DYNARE_BLOCK>exp {return token::EXP;}
<DYNARE_STATEMENT,DYNARE_BLOCK>log {return token::LOG;}
<DYNARE_STATEMENT,DYNARE_BLOCK>log10 {return token::LOG10;}
......@@ -814,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>acos {return token::ACOS;}
<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>cbrt {return token::CBRT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>max {return token::MAX;}
<DYNARE_STATEMENT,DYNARE_BLOCK>min {return token::MIN;}
<DYNARE_STATEMENT,DYNARE_BLOCK>abs {return token::ABS;}
......@@ -822,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>normpdf {return token::NORMPDF;}
<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>expectation {return token::EXPECTATION;}
<DYNARE_BLOCK>var_expectation {return token::VAR_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,DYNARE_BLOCK>varobs {return token::VAROBS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>varexobs {return token::VAREXOBS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>nan {return token::NAN_CONSTANT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>inf {return token::INF_CONSTANT;}
<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 */
<DYNARE_STATEMENT>identification {return token::IDENTIFICATION;}
......@@ -879,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>colormap {return token::COLORMAP;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[A-Za-z_][A-Za-z0-9_]* {
yylval->build<string>(yytext);
<DYNARE_STATEMENT,DYNARE_BLOCK>{NAME} {
yylval->emplace<string>(yytext);
return token::NAME;
}
<DYNARE_STATEMENT,DYNARE_BLOCK>((([0-9]*\.[0-9]+)|([0-9]+\.))([edED][-+]?[0-9]+)?)|([0-9]+[edED][-+]?[0-9]+) {
yylval->build<string>(yytext);
<DYNARE_STATEMENT,DYNARE_BLOCK>{FLOAT_NUMBER} {
yylval->emplace<string>(yytext);
return token::FLOAT_NUMBER;
}
<DYNARE_STATEMENT,DYNARE_BLOCK>[0-9]+ {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::INT_NUMBER;
}
<DATES_STATEMENT>\( { yylval->as<string>().append(yytext); dates_parens_nb++; }
<DATES_STATEMENT>\) {
yylval->as<string>().append(yytext);
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_BLOCK>\|e { return token::PIPE_E; }
<DYNARE_BLOCK>\|x { return token::PIPE_X; }
<DYNARE_BLOCK>\|p { return token::PIPE_P; }
<DYNARE_STATEMENT,DYNARE_BLOCK>\'[^\']+\' {
yylval->build<string>(yytext + 1).pop_back();
<DYNARE_STATEMENT,DYNARE_BLOCK>\'[^\']*\' {
yylval->emplace<string>(yytext + 1).pop_back();
return token::QUOTED_STRING;
}
......@@ -942,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
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))
{
BEGIN DYNARE_STATEMENT;
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::NAME;
}
else
......@@ -957,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
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}\] {
string yytextcpy = string(yytext);
<INITIAL>\[([[:space:]]*{NAME}[[:space:]]*,{1}[[:space:]]*)*([[:space:]]*{NAME}[[:space:]]*){1}\] {
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());
......@@ -984,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)
{
BEGIN DYNARE_STATEMENT;
yylval->build<vector<string>>(val);
yylval->emplace<vector<string>>(val);
return token::SYMBOL_VEC;
}
}
......@@ -999,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]*\" |
\.{1,2} |
"*" |
"/" { yymore(); eofbuff = string(yytext); }
\* |
\/ { yymore(); eofbuff = yytext; }
\.{3,}[[:space:]]*\n { driver.add_native_remove_charset(yytext, "\n"); }
\n {
if (strlen(yytext) > 1)
......@@ -1011,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);
yyterminate();
}
\.{3,}[[:space:]]*"%".*\n |
"%"[^\n]* { driver.add_native_remove_charset(yytext, "%"); }
\.{3,}[[:space:]]*%.*\n |
%[^\n]* { driver.add_native_remove_charset(yytext, "%"); }
\.{3,}[[:space:]]*"//".*\n |
"//"[^\n]* { driver.add_native_remove_charset(yytext, "//"); }
\.{3,}[[:space:]]*"/*" {
......@@ -1029,13 +1196,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
<NATIVE_COMMENT>"*/"[[:space:]]*\n { BEGIN NATIVE; }
<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"); }
%%
#pragma GCC diagnostic pop
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.
*
......@@ -14,59 +14,89 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <fstream>
#include <string>
#include <thread>
#include <vector>
#include <cstdlib>
#include <cstring>
#ifndef PACKAGE_VERSION
# define PACKAGE_VERSION 4.
#endif
#include <unistd.h>
#include "ParsingDriver.hh"
#include "Configuration.hh"
#include "ExtendedPreprocessorTypes.hh"
#include "ConfigFile.hh"
#include "ModFile.hh"
#include "ParsingDriver.hh"
/* Prototype for second part of main function
Splitting main() in two parts was necessary because ParsingDriver.h and MacroDriver.h can't be
/* Prototype for the function that handles the macro-expansion of the .mod file
Splitting this out was necessary because ParsingDriver.hh and macro/Driver.hh can't be
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,
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_arg, bool nostrict, bool stochastic, bool check_model_changes,
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
LanguageOutputType lang, int params_derivs_order, bool transform_unary_ops
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
, 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);
stringstream macroExpandModFile(const filesystem::path& filename, const istream& modfile,
bool debug, bool save_macro, filesystem::path save_macro_file,
bool line_macro, const vector<pair<string, string>>& defines,
vector<filesystem::path> paths);
void
usage()
{
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]"
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=julia]"
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] "
"[savemacro[=macro_file]] [onlymacro] [linemacro] [notmpterms] [nolog] [warn_uninit]"
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] "
"[conffile=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] "
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
<< " [cygwin] [msvc] [mingw]"
#endif
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]"
"[exclude_eqs=<equation_tag_list_or_file>] [include_eqs=<equation_tag_list_or_file>]"
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] "
"[nopathchange] [nopreprocessoroutput]"
<< " [mexext=<extension>] [matlabroot=<path>] [onlymodel] [notime] [use_dll] "
"[nocommutativity]"
<< endl;
exit(EXIT_FAILURE);
}
/* 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
main(int argc, char** argv)
{
......@@ -83,248 +113,270 @@ main(int argc, char **argv)
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_global = false;
bool save_macro = false;
string save_macro_file;
filesystem::path save_macro_file;
bool debug = false;
bool no_tmp_terms = false;
bool only_macro = false;
bool no_line_macro = false;
bool no_empty_line_macro = false;
bool no_log = false;
bool line_macro = false;
bool no_warn = false;
int params_derivs_order = 2;
bool warn_uninit = false;
bool console = false;
bool nograph = false;
bool nointeractive = false;
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
bool cygwin = false;
bool msvc = false;
bool mingw = false;
#endif
string parallel_config_file;
filesystem::path conffile;
bool parallel = false;
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_use_psexec = true; // Must be the same default as in matlab/default_option_values.m
bool nostrict = false;
bool stochastic = false;
bool check_model_changes = false;
bool minimal_workspace = false;
bool compute_xrefs = false;
bool transform_unary_ops = false;
map<string, string> defines;
vector<string> path;
FileOutputType output_mode{FileOutputType::none};
bool gui = false;
string exclude_eqs, include_eqs;
vector<pair<string, string>> defines;
vector<filesystem::path> paths;
OutputType output_mode {OutputType::standard};
JsonOutputPointType json {JsonOutputPointType::nojson};
JsonFileOutputType json_output_mode {JsonFileOutputType::file};
bool onlyjson = false;
bool jsonderivsimple = false;
LanguageOutputType language {LanguageOutputType::matlab};
bool nopreprocessoroutput = false;
string mexext;
filesystem::path matlabroot;
bool onlymodel = false;
bool use_dll = false;
// Parse options
for (int arg = 2; arg < argc; arg++)
for (auto s : options)
{
if (!strcmp(argv[arg], "debug"))
if (s == "debug")
debug = true;
else if (!strcmp(argv[arg], "noclearall"))
else if (s == "notime")
notime = true;
else if (s == "noclearall")
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] != '='
|| !(argv[arg][20] == '0' || argv[arg][20] == '1' || argv[arg][20] == '2'))
if (s.length() > 21 || s.at(19) != '='
|| !(s.at(20) == '0' || s.at(20) == '1' || s.at(20) == '2'))
{
cerr << "Incorrect syntax for params_derivs_order option" << endl;
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_global = true;
}
else if (!strcmp(argv[arg], "onlymacro"))
else if (s == "onlymacro")
only_macro = true;
else if (strlen(argv[arg]) >= 9 && !strncmp(argv[arg], "savemacro", 9))
else if (s.substr(0, 9) == "savemacro")
{
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;
usage();
}
save_macro_file = string(argv[arg] + 10);
save_macro_file = s.substr(10);
}
}
else if (!strcmp(argv[arg], "nolinemacro"))
no_line_macro = true;
else if (!strcmp(argv[arg], "noemptylinemacro"))
no_empty_line_macro = true;
else if (!strcmp(argv[arg], "notmpterms"))
else if (s == "linemacro")
line_macro = true;
else if (s == "notmpterms")
no_tmp_terms = true;
else if (!strcmp(argv[arg], "nolog"))
no_log = true;
else if (!strcmp(argv[arg], "nowarn"))
else if (s == "nolog")
{
// 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;
else if (!strcmp(argv[arg], "warn_uninit"))
else if (s == "warn_uninit")
warn_uninit = true;
else if (!strcmp(argv[arg], "console"))
else if (s == "console")
console = true;
else if (!strcmp(argv[arg], "nograph"))
else if (s == "nograph")
nograph = true;
else if (!strcmp(argv[arg], "nointeractive"))
else if (s == "nointeractive")
nointeractive = true;
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
else if (!strcmp(argv[arg], "cygwin"))
cygwin = true;
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] != '=')
else if (s.substr(0, 8) == "conffile")
{
if (s.length() <= 9 || s.at(8) != '=')
{
cerr << "Incorrect syntax for conffile option" << endl;
usage();
}
parallel_config_file = string(argv[arg] + 9);
conffile = s.substr(9);
}
else if (!strcmp(argv[arg], "parallel_slave_open_mode"))
parallel_slave_open_mode = true;
else if (!strcmp(argv[arg], "parallel_test"))
else if (s == "parallel_follower_open_mode"
|| s == "parallel_slave_open_mode") // Kept for backward compatibility, see #86
parallel_follower_open_mode = true;
else if (s == "parallel_test")
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;
else if (!strcmp(argv[arg], "stochastic"))
else if (s == "stochastic")
stochastic = true;
else if (!strcmp(argv[arg], "fast"))
else if (s == "fast")
check_model_changes = true;
else if (!strcmp(argv[arg], "minimal_workspace"))
else if (s == "minimal_workspace")
minimal_workspace = true;
else if (!strcmp(argv[arg], "compute_xrefs"))
else if (s == "compute_xrefs")
compute_xrefs = true;
else if (!strcmp(argv[arg], "transform_unary_ops"))
else if (s == "transform_unary_ops")
transform_unary_ops = true;
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "parallel", 8))
else if (s.substr(0, 8) == "parallel")
{
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;
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 "
<< "must not be separated from -D by whitespace." << endl;
usage();
}
size_t equal_index = string(argv[arg]).find('=');
if (equal_index != string::npos)
{
string key = string(argv[arg]).erase(equal_index).erase(0, 2);
defines[key] = string(argv[arg]).erase(0, equal_index+1);
}
if (auto equal_index = s.find('='); equal_index != string::npos)
defines.emplace_back(s.substr(2, equal_index - 2), s.substr(equal_index + 1));
else
{
string key = string(argv[arg]).erase(0, 2);
defines[key] = "1";
}
defines.emplace_back(s.substr(2), "true");
}
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 "
<< "must not be separated from -I by whitespace." << endl;
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;
usage();
}
if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 7, "dynamic", 7))
output_mode = FileOutputType::dynamic;
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "first", 5))
output_mode = FileOutputType::first;
else if (strlen(argv[arg]) == 13 && !strncmp(argv[arg] + 7, "second", 6))
output_mode = FileOutputType::second;
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "third", 5))
output_mode = FileOutputType::third;
s.erase(0, 7);
if (s == "first")
output_mode = OutputType::first;
else if (s == "second")
output_mode = OutputType::second;
else if (s == "third")
output_mode = OutputType::third;
else
{
cerr << "Incorrect syntax for output option" << endl;
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;
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;
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
{
cerr << "Incorrect syntax for language option" << endl;
usage();
}
}
}
else if (!strcmp(argv[arg], "jsonstdout"))
else if (s == "jsonstdout")
json_output_mode = JsonFileOutputType::standardout;
else if (!strcmp(argv[arg], "onlyjson"))
else if (s == "onlyjson")
onlyjson = true;
else if (!strcmp(argv[arg], "nopreprocessoroutput"))
nopreprocessoroutput = true;
else if (!strcmp(argv[arg], "jsonderivsimple"))
else if (s == "nopreprocessoroutput")
cout.rdbuf(nullptr);
else if (s == "jsonderivsimple")
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;
usage();
}
if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 5, "parse", 5))
s.erase(0, 5);
if (s == "parse")
json = JsonOutputPointType::parsing;
else if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 5, "check", 5))
else if (s == "check")
json = JsonOutputPointType::checkpass;
else if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 5, "transform", 9))
else if (s == "transform")
json = JsonOutputPointType::transformpass;
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 5, "compute", 7))
else if (s == "compute")
json = JsonOutputPointType::computingpass;
else
{
......@@ -332,80 +384,173 @@ main(int argc, char **argv)
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
{
cerr << "Unknown option: " << argv[arg] << endl;
cerr << "Unknown option: " << s << endl;
usage();
}
}
if (!nopreprocessoroutput)
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)
string basename = argv[1];
string modfile, modfiletxt;
size_t fsc = basename.find_first_of(';');
if (fsc != string::npos)
{
// 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);
/* Calling string() method on filename.stem(): not necessary on GNU/Linux and macOS because there
is an implicit conversion from filesystem:path to string (i.e. basic_string<char>), but needed
on Windows because the implicit conversion is only to wstring (i.e. basic_string<wchar_t>). */
const string basename {filename.stem().string()};
ifstream modfile(argv[1], ios::binary);
if (modfile.fail())
// Forbid some basenames, since they will cause trouble (see preprocessor#62)
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);
}
stringstream buffer;
buffer << modfile.rdbuf();
modfiletxt = buffer.str();
}
WarningConsolidation warnings(no_warn);
// Process config file
ConfigFile config_file(parallel, parallel_test, parallel_slave_open_mode, cluster_name);
config_file.getConfigFileInfo(parallel_config_file);
config_file.checkPass(warnings);
config_file.transformPass();
Configuration config {parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec,
cluster_name};
config.getConfigFileInfo(conffile, warnings);
config.checkPass(warnings);
config.transformPass();
// If Include option was passed to the [paths] block of the config file, add
// it to paths before macroprocessing
vector<string> config_include_paths = config_file.getIncludePaths();
for (vector<string>::const_iterator it = config_include_paths.begin();
it != config_include_paths.end(); it++)
path.push_back(*it);
for (const auto& it : config.getIncludePaths())
paths.emplace_back(it);
// Do macro processing
stringstream macro_output;
main1(modfile, basename, modfiletxt, debug, save_macro, save_macro_file, no_line_macro, no_empty_line_macro,
defines, path, macro_output);
/*
* Macro-expand MOD file
*/
stringstream macro_output
= macroExpandModFile(filename, modfile, debug, save_macro, move(save_macro_file), line_macro,
defines, move(paths));
if (only_macro)
return EXIT_SUCCESS;
// Do the rest
main2(macro_output, basename, debug, clear_all, clear_global,
no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive,
parallel, config_file, warnings, nostrict, stochastic, check_model_changes, minimal_workspace,
compute_xrefs, output_mode, language, params_derivs_order, transform_unary_ops
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
, cygwin, msvc, mingw
#endif
, json, json_output_mode, onlyjson, jsonderivsimple, nopreprocessoroutput
);
if (!exclude_eqs.empty() && !include_eqs.empty())
{
cerr << "You may only pass one of `include_eqs` and `exclude_eqs`" << endl;
exit(EXIT_FAILURE);
}
/*
* Process Macro-expanded MOD file
*/
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;
}
/*
* 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__) || defined(__MINGW32__)
, 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__) || defined(__MINGW32__)
, 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.
*
......@@ -14,26 +14,31 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _EXPR_NODE_HH
#define _EXPR_NODE_HH
#ifndef EXPR_NODE_HH
#define EXPR_NODE_HH
#include <set>
#include <concepts>
#include <functional>
#include <map>
#include <vector>
#include <optional>
#include <ostream>
#include <functional>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
#include "SymbolTable.hh"
#include "CodeInterpreter.hh"
#include "Bytecode.hh"
#include "CommonEnums.hh"
#include "ExternalFunctionsTable.hh"
#include "SymbolList.hh"
class DataTree;
class NumConstNode;
class VariableNode;
class UnaryOpNode;
class BinaryOpNode;
......@@ -48,82 +53,116 @@ struct ExprNodeLess;
see the definition of ExprNodeLess */
using temporary_terms_t = set<expr_t, ExprNodeLess>;
/*! Keeps track of array indices of temporary_terms for writing */
using temporary_terms_idxs_t = 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>;
using temporary_terms_idxs_t = unordered_map<expr_t, int>;
//! Type for evaluation contexts
/*! The key is a symbol id. Lags are assumed to be null */
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>;
//! Type for the substitution map used in the process of substitutitng diff expressions
//! diff_table[static_expr_t][lag] -> [dynamic_expr_t]
using diff_table_t = map<expr_t, map<int, expr_t>>;
//! Possible types of output when writing ExprNode(s)
//! Type for the substitution map used for creating aux. vars for diff and unary_ops
/*! Let ≅ be the equivalence relationship such that two expressions e₁ and e₂
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₄).
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
{
matlabStaticModel, //!< Matlab code, static model
matlabDynamicModel, //!< Matlab code, dynamic model
matlabStaticModelSparse, //!< Matlab code, static block decomposed model
matlabDynamicModelSparse, //!< Matlab code, dynamic block decomposed model
CDynamicModel, //!< C code, dynamic model
CStaticModel, //!< C code, static model
juliaStaticModel, //!< Julia code, static model
juliaDynamicModel, //!< Julia code, dynamic model
matlabStaticModel, //!< Matlab code, static model, legacy representation
matlabDynamicModel, //!< Matlab code, dynamic model, legacy representation
matlabSparseStaticModel, //!< Matlab code, static model, sparse representation
matlabSparseDynamicModel, //!< Matlab code, dynamic model, sparse representation
CDynamicModel, //!< C code, dynamic model, legacy representation
CStaticModel, //!< C code, static model, legacy representation
CSparseDynamicModel, //!< C code, dynamic model, sparse representation
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)
latexStaticModel, //!< LaTeX code, static model
latexDynamicModel, //!< LaTeX code, dynamic model
latexDynamicSteadyStateOperator, //!< LaTeX 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
juliaDynamicSteadyStateOperator, //!< Julia code, dynamic model, inside a steady state operator
steadyStateFile, //!< Matlab code, in the generated steady state file
juliaSteadyStateFile, //!< Julia code, in the generated steady state file
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)
{
return output_type == ExprNodeOutputType::matlabStaticModel
|| output_type == ExprNodeOutputType::matlabDynamicModel
|| output_type == ExprNodeOutputType::matlabSparseStaticModel
|| output_type == ExprNodeOutputType::matlabSparseDynamicModel
|| output_type == ExprNodeOutputType::matlabOutsideModel
|| output_type == ExprNodeOutputType::matlabStaticModelSparse
|| output_type == ExprNodeOutputType::matlabDynamicModelSparse
|| output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::matlabDynamicSparseSteadyStateOperator
|| output_type == ExprNodeOutputType::steadyStateFile
|| output_type == ExprNodeOutputType::matlabDseries
|| output_type == ExprNodeOutputType::epilogueFile;
|| output_type == ExprNodeOutputType::epilogueFile
|| output_type == ExprNodeOutputType::occbinDifferenceFile;
}
inline bool
constexpr bool
isJuliaOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::juliaStaticModel
|| output_type == ExprNodeOutputType::juliaDynamicModel
|| output_type == ExprNodeOutputType::juliaSparseStaticModel
|| output_type == ExprNodeOutputType::juliaSparseDynamicModel
|| output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::juliaSteadyStateFile;
|| output_type == ExprNodeOutputType::juliaSteadyStateFile
|| output_type == ExprNodeOutputType::juliaTimeDataFrame;
}
inline bool
constexpr bool
isCOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::CDynamicModel
|| output_type == ExprNodeOutputType::CStaticModel
|| output_type == ExprNodeOutputType::CSparseDynamicModel
|| output_type == ExprNodeOutputType::CSparseStaticModel
|| output_type == ExprNodeOutputType::CDynamicSteadyStateOperator;
}
inline bool
constexpr bool
isLatexOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::latexStaticModel
......@@ -131,17 +170,66 @@ isLatexOutput(ExprNodeOutputType output_type)
|| 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.
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
#define LEFT_ARRAY_SUBSCRIPT(output_type) (isMatlabOutput(output_type) ? '(' : '[')
#define RIGHT_ARRAY_SUBSCRIPT(output_type) (isMatlabOutput(output_type) ? ')' : ']')
constexpr char
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
#define LEFT_PAR(output_type) (isLatexOutput(output_type) ? "\\left(" : "(")
#define RIGHT_PAR(output_type) (isLatexOutput(output_type) ? "\\right)" : ")")
constexpr string
LEFT_PAR(ExprNodeOutputType output_type)
{
return isLatexOutput(output_type) ? "\\left(" : "(";
}
constexpr string
RIGHT_PAR(ExprNodeOutputType output_type)
{
return isLatexOutput(output_type) ? "\\right)" : ")";
}
//! Base class for expression nodes
class ExprNode
......@@ -159,11 +247,20 @@ class ExprNode
friend class AbstractExternalFunctionNode;
friend class VarExpectationNode;
friend class PacExpectationNode;
private:
//! 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 */
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:
//! Reference to the enclosing DataTree
DataTree& datatree;
......@@ -172,7 +269,7 @@ class ExprNode
const int idx;
//! Is the data member non_null_derivatives initialized ?
bool preparedForDerivation;
bool preparedForDerivation {false};
//! Set of derivation IDs with respect to which the derivative is potentially non-null
set<int> non_null_derivatives;
......@@ -180,23 +277,40 @@ class ExprNode
//! Used for caching of first order derivatives (when non-null)
map<int, expr_t> derivatives;
const static int min_cost_matlab{40*90};
const 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_matlab {40 * 90};
constexpr static int min_cost_c {40 * 4};
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
/*! Nodes included in temporary_terms are considered having a null cost */
virtual int cost(int cost, bool is_matlab) const;
virtual int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const;
virtual int cost(const map<NodeTreeReference, temporary_terms_t> &temp_terms_map, bool is_matlab) const;
[[nodiscard]] virtual int cost(int cost, bool is_matlab) const;
[[nodiscard]] virtual int
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
struct EquationInfo
{
set<pair<int, int>> param;
set<pair<int, int>> endo;
set<pair<int, int>> exo;
set<pair<int, int>> exo_det;
set<pair<int, int>> param, endo, exo, exo_det;
};
//! If this node is a temporary term, writes its temporary term representation
......@@ -205,50 +319,135 @@ class ExprNode
bool checkIfTemporaryTermThenWrite(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
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:
ExprNode(DataTree& datatree_arg, int idx_arg);
virtual
~ExprNode();
virtual ~ExprNode() = default;
//! Initializes data member non_null_derivatives
virtual void prepareForDerivation() = 0;
ExprNode(const ExprNode&) = delete;
ExprNode& operator=(const ExprNode&) = delete;
//! 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)
For an equal node, returns the derivative of lhs minus rhs */
/*! Uses a symbolic a priori to pre-detect null derivatives, and caches the result for other
derivatives (to avoid computing it several times) For an equal node, returns the derivative of
lhs minus rhs */
expr_t getDerivative(int deriv_id);
//! Computes derivatives by applying the chain rule for some variables
/*!
\param deriv_id The derivation ID with respect to which we are derivating
\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
*/
virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) = 0;
/* Computes derivatives by applying the chain rule for some variables.
— “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
— “non_null_chain_rule_derivatives” is used to store the indices of
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
/*! 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
/*! 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,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const;
//! Compute temporary terms in this expression for block decomposed model
/*!
\param[in] blk the block number
\param[in] eq the equation number (within the block)
\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_type the type of output (MATLAB, C, LaTeX...)
\param[in] temporary_terms the nodes that are marked as temporary terms
\param[in] a map from temporary_terms to integers indexes (in the
MATLAB or Julia vector of temporary terms); can be empty
when writing C or MATLAB with block decomposition)
MATLAB, C or Julia vector of temporary terms); can be empty
when writing MATLAB with block decomposition)
\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
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)
void writeOutput(ostream& output) const;
......@@ -257,17 +456,26 @@ class ExprNode
void writeOutput(ostream& output, ExprNodeOutputType output_type) const;
//! 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
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
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,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -278,14 +486,15 @@ class ExprNode
virtual void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_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,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
virtual void writeBytecodeExternalFunctionOutput(
Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
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).
They are added to the set given in argument.
......@@ -294,16 +503,14 @@ class ExprNode
*/
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
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
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.
They are added to the set given in argument.
......@@ -318,92 +525,96 @@ class ExprNode
They are added to the set given in argument.
Note that model local variables are substituted by their expression in the computation.
*/
virtual 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;
void collectEndogenous(set<pair<int, int>>& result) const;
class EvalException
{
};
class EvalExternalFunctionException : public EvalException
{
};
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;
[[nodiscard]] virtual double eval(const eval_context_t& eval_context) const noexcept(false) = 0;
// 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
/*!
This method duplicates the current node by creating a similar node from which all leads/lags have been stripped,
adds the result in the static_datatree argument (and not in the original datatree), and returns it.
This method duplicates the current node by creating a similar node from which all leads/lags
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;
/*!
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;
//! 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 */
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 */
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 */
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 */
virtual int maxExoLag() const = 0;
[[nodiscard]] virtual int maxExoLag() const = 0;
//! Returns the relative period of the most forward term in this expression
/*! A negative value means that the expression contains only lagged variables */
virtual int maxLead() const = 0;
/* Returns the maximum lead of endo/exo/exodet in this expression (including heterogeneous
endo/exo). A negative value means that the expression contains only lagged variables. A value
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
/*! A negative value means that the expression contains only leaded variables */
virtual int maxLag() const = 0;
/* Returns the maximum lag of endo/exo/exodet in this expression (including heterogeneous
endo/exo). A negative value means that the expression contains only leaded variables. A value
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
//! Takes account of undiffed LHS variables in calculating the max lag
virtual int PacMaxLag(int lhs_symb_id) const = 0;
/* Returns the maximum lag of endo/exo/exodet (including heterogeneous endo/exo), as if diffs were
expanded. This function behaves as maxLag(), except that it treats diff() differently. For
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
\param[in] n The number of lags by which to shift
\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*>;
//! Type for the substitution map used in the process of substituting adl expressions
......@@ -411,102 +622,135 @@ class ExprNode
//! 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.
\pre This expression is assumed to have maximum endogenous lead >= 2
\param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\return The new variable node corresponding to the current 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. \pre This
expression is assumed to have maximum endogenous lead >= 2 \param[in,out] subst_table The table
to which new auxiliary variables and their correspondance will be added \param[out] neweqs
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
/*!
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.
\pre This expression is assumed to have maximum exogenous lead >= 1
\param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\return The new variable node corresponding to the current 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. \pre This
expression is assumed to have maximum exogenous lead >= 1 \param[in,out] subst_table The table
to which new auxiliary variables and their correspondance will be added \param[out] neweqs
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[out] neweqs Equations to be added to the model to match the creation of 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[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 this expr is in the table, then it will use the corresponding variable and return the 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
- if this expr is in the table, then it will use the corresponding variable and return the
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[out] neweqs Equations to be added to the model to match the creation of 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[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[out] neweqs Equations to be added to the model to match the creation of 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[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;
//! Constructs a new expression where exogenous variables with a lag have been replaced by auxiliary variables
virtual expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
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[out] neweqs Equations to be added to the model to match the creation of 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[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[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?
\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[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
all fwrd vars if empty
\param[in,out] subst_table Map used to store mapping between a given
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
/*!
\param[in] value of the numerical constante
\param[out] the boolean equal to true if NodeId is a constant equal to value
*/
virtual bool isNumConstNodeEqualTo(double value) const = 0;
//! Returns true if the expression contains one or several endogenous variable
virtual bool containsEndogenous() const = 0;
[[nodiscard]] virtual bool isNumConstNodeEqualTo(double value) const = 0;
//! Returns true if the expression contains one or several exogenous variable
virtual bool containsExogenous() const = 0;
//! Returns the maximum number of nested diffs in the expression
[[nodiscard]] virtual int countDiffs() const = 0;
//! Returns the number of diffs present
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[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
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
/*!
......@@ -518,71 +762,196 @@ class ExprNode
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const = 0;
//! Substitute adl operator
virtual expr_t substituteAdl() const = 0;
[[nodiscard]] virtual expr_t substituteAdl() const = 0;
//! Substitute VarExpectation nodes
virtual expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const = 0;
//! Substitute out model-local variables
[[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
virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const = 0;
virtual void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const = 0;
virtual int findTargetVariable(int lhs_symb_id) const = 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;
virtual expr_t substituteDiff(const lag_equivalence_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
virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) = 0;
//! Add ExprNodes to the provided datatree
virtual expr_t cloneDynamic(DataTree &dynamic_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;
virtual expr_t substitutePacExpectation(const string& name, expr_t subexpr) = 0;
//! Returns true if the expression is in static form (no lead, no lag, no expectation, no STEADY_STATE)
virtual bool isInStaticForm() const = 0;
//! Substitute pac_target_nonstationary operator
virtual expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) = 0;
//! Substitute auxiliary variables by their expression in static model
virtual expr_t substituteStaticAuxiliaryVariable() const = 0;
[[nodiscard]] virtual optional<int> findTargetVariable(int lhs_symb_id) const = 0;
//! Returns true if model_info_name is referenced by a VarExpectationNode
virtual bool isVarModelReferenced(const string &model_info_name) const = 0;
//! Add ExprNodes to the provided datatree
virtual expr_t clone(DataTree& alt_datatree) const = 0;
//! Fills parameter information rerhs_symblated to PAC equation
virtual void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const = 0;
//! Move a trend variable with lag/lead to time t by dividing/multiplying by its growth factor
[[nodiscard]] virtual expr_t removeTrendLeadLag(const 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)
[[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:
//! param * (endog op endog op ...) + param * (endog op endog op ...) + ...
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;
[[nodiscard]] virtual bool isParamTimesEndogExpr() const = 0;
//! Fills the EC matrix structure
virtual void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs,
map<tuple<int, int, int>, expr_t> &EC) const = 0;
void fillErrorCorrectionRow(int eqn, const vector<int>& nontarget_lhs,
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
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
virtual void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const = 0;
/* Match an expression of the form ∏ x(l)ᵏ, where x are endogenous, as used
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)
......@@ -599,195 +968,238 @@ struct ExprNodeLess
};
//! 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
{
private:
public:
//! Id from numerical constants table
const int id;
private:
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:
NumConstNode(DataTree& datatree_arg, int idx_arg, int id_arg);
int
get_id() const
{
return id;
};
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 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 writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
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 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;
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;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) 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;
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;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) 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;
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;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() 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;
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;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) 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 cloneDynamic(DataTree &dynamic_datatree) 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;
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;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
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;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() 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;
};
//! Symbol or variable node
class VariableNode : public ExprNode
{
friend class UnaryOpNode;
private:
public:
//! Id from the symbol table
const int symb_id;
const SymbolType type;
//! A positive value is a lead, a negative is a lag
const int lag;
private:
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:
VariableNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg, int lag_arg);
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;
[[nodiscard]] SymbolType get_type() const;
[[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 writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
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 collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) 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 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;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) 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;
void computeXrefs(EquationInfo& ei) const override;
SymbolType
get_type() const
{
return type;
};
int
get_symb_id() const
{
return symb_id;
};
int
get_lag() const
{
return lag;
};
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 getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) 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;
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;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() 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;
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;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) 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 cloneDynamic(DataTree &dynamic_datatree) 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;
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;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
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;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() 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;
};
//! Unary operator node
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;
//! Stores the information set. Only used for expectation operator
const int expectation_information_set;
......@@ -796,22 +1208,40 @@ private:
const UnaryOpcode op_code;
const string adl_param_name;
const vector<int> adl_lags;
private:
expr_t computeDerivative(int deriv_id) override;
int cost(int cost, bool is_matlab) const override;
int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
int cost(const map<NodeTreeReference, temporary_terms_t> &temp_terms_map, bool is_matlab) const 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;
[[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
expr_t composeDerivatives(expr_t darg, int deriv_id);
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);
void prepareForDerivation() override;
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) 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;
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);
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 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 writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -819,124 +1249,147 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(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,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
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 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);
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;
//! Returns operand
expr_t
get_arg() const
{
return (arg);
};
//! Returns op code
UnaryOpcode
get_op_code() const
{
return (op_code);
};
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) 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;
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;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) 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;
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 argument
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() 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;
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
//! argument
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 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 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;
bool createAuxVarForUnaryOpNode() const;
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;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
[[nodiscard]] bool createAuxVarForUnaryOpNode() const;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) 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 cloneDynamic(DataTree &dynamic_datatree) 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;
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;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
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;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign) 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;
};
//! Binary operator node
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 BinaryOpcode op_code;
const int powerDerivOrder;
const string adlparam;
private:
expr_t computeDerivative(int deriv_id) override;
int cost(int cost, bool is_matlab) const override;
int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
int cost(const map<NodeTreeReference, temporary_terms_t> &temp_terms_map, bool is_matlab) const 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;
[[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
expr_t composeDerivatives(expr_t darg1, expr_t darg2);
const int powerDerivOrder;
const string adlparam;
// 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)...)};
return buildSimilarBinaryOpNode(substarg1, substarg2, datatree);
}
public:
BinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg,
BinaryOpcode op_code_arg, const expr_t arg2_arg, int powerDerivOrder);
void prepareForDerivation() override;
int precedenceJson(const temporary_terms_t &temporary_terms) const override;
int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) 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;
BinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg, BinaryOpcode op_code_arg,
const expr_t arg2_arg, int powerDerivOrder);
[[nodiscard]] int precedenceJson(const temporary_terms_t& temporary_terms) const override;
[[nodiscard]] int precedence(ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms) const override;
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 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 writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -944,156 +1397,198 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(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,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
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 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, int derivOrder) noexcept(false);
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;
virtual expr_t Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const;
//! Returns first operand
expr_t
get_arg1() 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);
static double eval_opcode(double v1, BinaryOpcode op_code, double v2,
int derivOrder) noexcept(false);
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) 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 Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const;
expr_t toStatic(DataTree& static_datatree) 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;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) 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;
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
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
//! Try to normalize an equation with respect to a given dynamic variable.
/*! Should only be called on Equal nodes. The variable must appear in the equation. */
[[nodiscard]] BinaryOpNode* normalizeEquation(int symb_id, int lag) const;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() 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;
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 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 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;
bool findTargetVariableHelper1(int lhs_symb_id, int rhs_symb_id) const;
int findTargetVariableHelper(const expr_t arg1, const expr_t arg2, int lhs_symb_id) const;
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;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
[[nodiscard]] bool findTargetVariableHelper1(int lhs_symb_id, int rhs_symb_id) const;
optional<int> findTargetVariableHelper(const expr_t arg1, const expr_t arg2,
int lhs_symb_id) const;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) 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 cloneDynamic(DataTree &dynamic_datatree) const override;
expr_t removeTrendLeadLag(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
expr_t unpackPowerDeriv() const;
expr_t clone(DataTree& alt_datatree) 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
[[nodiscard]] expr_t unpackPowerDeriv() const;
//! Returns MULT_i*(lhs-rhs) = 0, creating multiplier MULT_i
expr_t addMultipliersToConstraints(int i);
//! Returns the non-zero hand-side of an equation (that must have a hand side equal to zero)
expr_t getNonZeroPartofEquation() const;
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 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,
//! Returns the non-zero hand side of an equation (that must have a hand side equal to zero)
[[nodiscard]] expr_t getNonZeroPartofEquation() const;
[[nodiscard]] bool isInStaticForm() const override;
void fillAutoregressiveRow(int eqn, const vector<int>& lhs,
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;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
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;
//! Substitute auxiliary variables by their expression in static model auxiliary variable definition
virtual expr_t substituteStaticAuxiliaryDefinition() const;
//! Finds equations where a variable is equal to a constant
void findConstantEquations(map<VariableNode*, NumConstNode*>& table) const;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
/*
ec_params_and_vars:
- 1st element = feedback force parameter
- 2nd element = list of terms in the cointegration relationship (symb_id,
is target ?, multiplicative scalar); this form theoretically allows for a
linear combination in the cointegration, though for the time being we allow
less than that
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
class TrinaryOpNode : public ExprNode
{
friend class ModelTree;
private:
public:
const expr_t arg1, arg2, arg3;
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;
int cost(int cost, bool is_matlab) const override;
int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
int cost(const map<NodeTreeReference, temporary_terms_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
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;
[[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);
// 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:
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);
void prepareForDerivation() override;
int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) 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;
[[nodiscard]] int precedence(ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms) const override;
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 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 writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -1101,223 +1596,278 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(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,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
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 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);
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;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) 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;
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;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) 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;
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 arguments
expr_t buildSimilarTrinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, expr_t alt_arg3, DataTree &alt_datatree) const;
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;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() 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;
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
//! arguments
expr_t buildSimilarTrinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, expr_t alt_arg3,
DataTree& alt_datatree) const;
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;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) 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 cloneDynamic(DataTree &dynamic_datatree) 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;
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;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
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;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
[[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
};
//! External function node
class AbstractExternalFunctionNode : public ExprNode
{
public:
const int symb_id;
const vector<expr_t> arguments;
private:
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;
// 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:
//! Thrown when trying to access an unknown entry in external_function_node_map
class UnknownFunctionNameAndArgs
{
};
const int symb_id;
const vector<expr_t> arguments;
void prepareForDerivation() override;
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
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
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
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 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
function which is computed by the same external function call (i.e. it has
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:
AbstractExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg,
vector<expr_t> arguments_arg);
void prepareForDerivation() override;
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) 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;
[[nodiscard]] string getName() const;
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 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 writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const override = 0;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
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,
const temporary_terms_t& temporary_terms,
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,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic = true) const override = 0;
void compileExternalFunctionOutput(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,
deriv_node_temp_terms_t &tef_terms) const override = 0;
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 = 0;
bool isdynamic = true) const override
= 0;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override
= 0;
void collectVARLHSVariable(set<expr_t>& 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;
double eval(const eval_context_t &eval_context) const noexcept(false) override;
unsigned int compileExternalFunctionArguments(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;
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;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) 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
= 0;
expr_t toStatic(DataTree& static_datatree) const override;
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;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) 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;
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;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() 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;
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;
virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const = 0;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
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;
expr_t replaceTrendVar() const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
DataTree& alt_datatree) const
= 0;
[[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 cloneDynamic(DataTree &dynamic_datatree) const override = 0;
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;
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;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
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;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() 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;
};
class ExternalFunctionNode : public AbstractExternalFunctionNode
{
friend class FirstDerivExternalFunctionNode;
friend class SecondDerivExternalFunctionNode;
private:
expr_t composeDerivatives(const vector<expr_t>& dargs) override;
protected:
function<bool (expr_t)> sameTefTermPredicate() const override;
[[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
public:
ExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int symb_id_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 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,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -1325,48 +1875,45 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(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,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
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 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 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;
void computeXrefs(EquationInfo& ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
expr_t cloneDynamic(DataTree &dynamic_datatree) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
DataTree& alt_datatree) const override;
};
class FirstDerivExternalFunctionNode : public AbstractExternalFunctionNode
{
private:
public:
const int inputIndex;
private:
expr_t composeDerivatives(const vector<expr_t>& dargs) override;
protected:
function<bool (expr_t)> sameTefTermPredicate() const override;
[[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
public:
FirstDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg,
int top_level_symb_id_arg,
const vector<expr_t> &arguments_arg,
int inputIndex_arg);
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 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;
FirstDerivExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int top_level_symb_id_arg,
const vector<expr_t>& arguments_arg, int inputIndex_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 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 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,
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) 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;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
......@@ -1375,43 +1922,43 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(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,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
expr_t cloneDynamic(DataTree &dynamic_datatree) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
DataTree& alt_datatree) const override;
};
class SecondDerivExternalFunctionNode : public AbstractExternalFunctionNode
{
private:
public:
const int inputIndex1;
const int inputIndex2;
private:
expr_t composeDerivatives(const vector<expr_t>& dargs) override;
protected:
function<bool (expr_t)> sameTefTermPredicate() const override;
[[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
public:
SecondDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg,
int top_level_symb_id_arg,
const vector<expr_t> &arguments_arg,
int inputIndex1_arg,
SecondDerivExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int top_level_symb_id_arg,
const vector<expr_t>& arguments_arg, int inputIndex1_arg,
int inputIndex2_arg);
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 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 writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) 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,
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) 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;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
......@@ -1420,201 +1967,168 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(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,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
expr_t cloneDynamic(DataTree &dynamic_datatree) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
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:
VarExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name_arg);
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) 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 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;
const string model_name;
SubModelNode(DataTree& datatree_arg, int idx_arg, string model_name_arg);
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 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;
expr_t toStatic(DataTree& static_datatree) const override;
expr_t cloneDynamic(DataTree &dynamic_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;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() 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 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,
[[nodiscard]] bool containsExternalFunction() const override;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void computeXrefs(EquationInfo& ei) const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
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;
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 collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isNumConstNodeEqualTo(double value) const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
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 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;
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;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
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;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) 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;
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
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;
};
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 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:
PacExpectationNode(DataTree& datatree_arg, int idx_arg, string model_name);
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) 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 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 cloneDynamic(DataTree &dynamic_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,
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 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 collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isNumConstNodeEqualTo(double value) const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() 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;
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;
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;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
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;
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 writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
};
class PacTargetNonstationaryNode : public SubModelNode
{
public:
PacTargetNonstationaryNode(DataTree& datatree_arg, int idx_arg, string model_name);
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 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
/*
* Copyright (C) 2014-2017 Dynare Team
* Copyright © 2014-2023 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,27 +14,26 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _EXTENDED_PREPROCESSOR_TYPES_HH
#define _EXTENDED_PREPROCESSOR_TYPES_HH
#ifndef 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
dynamic, // outputs <fname>_dynamic.* and related files
first, // outputs <fname>_first_derivatives.* and related files
second, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.* and related files
third, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.*, <fname>_third_derivatives.* and related files
standard, // Default value, infer the derivation order from .mod file only
first, // Output only 1st dynamic derivatives with no other computations
second, // Output at least 2nd dynamic derivatives
third, // Output at least 3rd dynamic derivatives
};
// Values for the “language” option
enum class LanguageOutputType
{
matlab, // outputs files for Matlab/Octave processing
cuda, // outputs files for CUDA (not yet implemented)
matlab, // outputs files for MATLAB/Octave processing
julia, // outputs files for Julia
python, // outputs files for Python (not yet implemented) (not yet implemented)
};
enum class JsonFileOutputType
......@@ -43,6 +42,7 @@ enum class JsonFileOutputType
standardout, // output JSON files to stdout
};
// Values for the “json” option
enum class JsonOutputPointType
{
nojson, // don't output JSON
......@@ -51,4 +51,5 @@ enum class JsonOutputPointType
transformpass, // output JSON after the transform pass
computingpass // output JSON after the computing pass
};
#endif
/*
* Copyright (C) 2010-2015 Dynare Team
* Copyright © 2010-2015 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,37 +14,34 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cassert>
#include <cerrno>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include "ExternalFunctionsTable.hh"
#include "SymbolTable.hh"
ExternalFunctionsTable::ExternalFunctionsTable()
= default;
void
ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs)
ExternalFunctionsTable::addExternalFunction(
int symb_id, const external_function_options& external_function_options_arg, bool track_nargs)
{
assert(symb_id >= 0);
assert(external_function_options_arg.nargs > 0);
// Change options to be saved so the table is consistent
external_function_options external_function_options_chng = external_function_options_arg;
if (external_function_options_arg.firstDerivSymbID == eExtFunSetButNoNameProvided)
if (external_function_options_arg.firstDerivSymbID == IDSetButNoNameProvided)
external_function_options_chng.firstDerivSymbID = symb_id;
if (external_function_options_arg.secondDerivSymbID == eExtFunSetButNoNameProvided)
if (external_function_options_arg.secondDerivSymbID == IDSetButNoNameProvided)
external_function_options_chng.secondDerivSymbID = symb_id;
if (!track_nargs)
external_function_options_chng.nargs = eExtFunNotSet;
external_function_options_chng.nargs = IDNotSet;
// Ensure 1st & 2nd deriv option consistency
if (external_function_options_chng.secondDerivSymbID == symb_id
......@@ -57,23 +54,26 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function
if ((external_function_options_chng.secondDerivSymbID != symb_id
&& external_function_options_chng.firstDerivSymbID == symb_id)
&& external_function_options_chng.secondDerivSymbID != eExtFunNotSet)
&& external_function_options_chng.secondDerivSymbID != IDNotSet)
{
cerr << "ERROR: If the first derivative is provided by the top-level function, the "
<< "second derivative cannot be provided by any other external function." << endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID != eExtFunNotSet
&& external_function_options_chng.firstDerivSymbID == eExtFunNotSet)
if (external_function_options_chng.secondDerivSymbID != IDNotSet
&& external_function_options_chng.firstDerivSymbID == IDNotSet)
{
cerr << "ERROR: If the second derivative is provided, the first derivative must also be provided." << endl;
cerr << "ERROR: If the second derivative is provided, the first derivative must also be "
"provided."
<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID == external_function_options_chng.firstDerivSymbID
if (external_function_options_chng.secondDerivSymbID
== external_function_options_chng.firstDerivSymbID
&& external_function_options_chng.firstDerivSymbID != symb_id
&& external_function_options_chng.firstDerivSymbID != eExtFunNotSet)
&& external_function_options_chng.firstDerivSymbID != IDNotSet)
{
cerr << "ERROR: If the Jacobian and Hessian are provided by the same function, that "
<< "function must be the top-level function." << endl;
......@@ -84,29 +84,40 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function
if (exists(symb_id))
{
bool ok_to_overwrite = false;
if (getNargs(symb_id) == eExtFunNotSet) // implies that the information stored about this function is not important
if (getNargs(symb_id)
== IDNotSet) // implies that the information stored about this function is not important
ok_to_overwrite = true;
if (!ok_to_overwrite) // prevents multiple non-compatible calls to external_function(name=funcname)
if (!ok_to_overwrite) // prevents multiple non-compatible calls to
// external_function(name=funcname)
{ // e.g. e_f(name=a,nargs=1,fd,sd) and e_f(name=a,nargs=2,fd=b,sd=c) should cause an error
if (external_function_options_chng.nargs != getNargs(symb_id))
{
cerr << "ERROR: The number of arguments passed to the external_function() statement do not "
<< "match the number of arguments passed to a previous call or declaration of the top-level function."<< endl;
cerr << "ERROR: The number of arguments passed to the external_function() statement "
"do not "
<< "match the number of arguments passed to a previous call or declaration of "
"the top-level function."
<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.firstDerivSymbID != getFirstDerivSymbID(symb_id))
{
cerr << "ERROR: The first derivative function passed to the external_function() statement does not "
<< "match the first derivative function passed to a previous call or declaration of the top-level function."<< endl;
cerr << "ERROR: The first derivative function passed to the external_function() "
"statement does not "
<< "match the first derivative function passed to a previous call or "
"declaration of the top-level function."
<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID != getSecondDerivSymbID(symb_id))
{
cerr << "ERROR: The second derivative function passed to the external_function() statement does not "
<< "match the second derivative function passed to a previous call or declaration of the top-level function."<< endl;
cerr << "ERROR: The second derivative function passed to the external_function() "
"statement does not "
<< "match the second derivative function passed to a previous call or "
"declaration of the top-level function."
<< endl;
exit(EXIT_FAILURE);
}
}
......
/*
* Copyright (C) 2010-2015 Dynare Team
* Copyright © 2010-2023 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,39 +14,29 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _EXTERNALFUNCTIONSTABLE_HH
#define _EXTERNALFUNCTIONSTABLE_HH
using namespace std;
#ifndef EXTERNAL_FUNCTIONS_TABLE_HH
#define EXTERNAL_FUNCTIONS_TABLE_HH
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <map>
enum ExternalFunctionSetOrNot
{
eExtFunSetButNoNameProvided = -2, //! Signifies that the derivative is obtained from the top-level function
eExtFunNotSet = -1, //! Signifies that no external function exists that calculates the derivative
eExtFunSetDefaultNargs = 1 //! This is the default number of arguments when nargs is not specified
};
using namespace std;
//! Handles external functions
class ExternalFunctionsTable
{
public:
//! Thrown when trying to access an unknown symbol (by id)
class UnknownExternalFunctionSymbolIDException
struct UnknownExternalFunctionSymbolIDException
{
public:
//! Symbol ID
int id;
UnknownExternalFunctionSymbolIDException(int id_arg) : id(id_arg)
{
}
};
/* For all arguments, -2 means not set
......@@ -59,68 +49,63 @@ public:
int nargs, firstDerivSymbID, secondDerivSymbID;
};
using external_function_table_type = map<int, external_function_options>;
//! Symbol ID used when no external function exists that calculates the derivative
constexpr static int IDNotSet = -1;
//! Symbol ID used when the derivative is obtained from the top-level function
constexpr static int IDSetButNoNameProvided = -2;
//! Default number of arguments when nargs is not specified
constexpr static int defaultNargs = 1;
private:
//! Map containing options provided to external_functions()
external_function_table_type externalFunctionTable;
public:
ExternalFunctionsTable();
//! Adds an external function to the table as well as its derivative functions
void addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs);
void addExternalFunction(int symb_id,
const external_function_options& external_function_options_arg,
bool track_nargs);
//! See if the function exists in the External Functions Table
inline bool exists(int symb_id) const;
[[nodiscard]] inline bool exists(int symb_id) const;
//! 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
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
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;
[[nodiscard]] inline int getSecondDerivSymbID(int symb_id) const noexcept(false);
};
inline bool
ExternalFunctionsTable::exists(int symb_id) const
{
auto iter = externalFunctionTable.find(symb_id);
return (iter != externalFunctionTable.end());
return externalFunctionTable.contains(symb_id);
}
inline int
ExternalFunctionsTable::getNargs(int symb_id) const noexcept(false)
{
if (exists(symb_id))
return externalFunctionTable.find(symb_id)->second.nargs;
if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return it->second.nargs;
else
throw UnknownExternalFunctionSymbolIDException(symb_id);
throw UnknownExternalFunctionSymbolIDException {symb_id};
}
inline int
ExternalFunctionsTable::getFirstDerivSymbID(int symb_id) const noexcept(false)
{
if (exists(symb_id))
return externalFunctionTable.find(symb_id)->second.firstDerivSymbID;
if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return it->second.firstDerivSymbID;
else
throw UnknownExternalFunctionSymbolIDException(symb_id);
throw UnknownExternalFunctionSymbolIDException {symb_id};
}
inline int
ExternalFunctionsTable::getSecondDerivSymbID(int symb_id) const noexcept(false)
{
if (exists(symb_id))
return externalFunctionTable.find(symb_id)->second.secondDerivSymbID;
if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return it->second.secondDerivSymbID;
else
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;
throw UnknownExternalFunctionSymbolIDException {symb_id};
}
#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
/*
* Copyright (C) 2015-2017 Dynare Team
* Copyright © 2015-2025 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,41 +14,56 @@
* 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/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <sstream>
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <regex>
#include <sstream>
#include "macro/MacroDriver.hh"
bool compareNewline (int i, int j) {
return i == '\n' && j == '\n';
}
#include "macro/Driver.hh"
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)
stringstream
macroExpandModFile(const filesystem::path& filename, const istream& modfile, bool debug,
bool save_macro, filesystem::path save_macro_file, bool line_macro,
const vector<pair<string, string>>& defines, vector<filesystem::path> paths)
{
// Do macro processing
MacroDriver m;
m.parse(modfile, basename, modfiletxt, macro_output, debug, no_line_macro, defines, path);
stringstream macro_output;
macro::Environment env = macro::Environment();
macro::Driver m;
/* Calling string() method on filename: not necessary on GNU/Linux and macOS because there is an
implicit conversion from filesystem:path to string (i.e. basic_string<char>), but needed on
Windows because the implicit conversion is only to wstring (i.e. basic_string<wchar_t>). */
m.parse(filename.string(), modfile, debug, defines, env, paths, macro_output);
if (save_macro)
{
if (save_macro_file.empty())
save_macro_file = basename + "-macroexp.mod";
ofstream macro_output_file(save_macro_file);
save_macro_file = filename.stem().string() + "_macroexp.mod";
ofstream macro_output_file {save_macro_file};
if (macro_output_file.fail())
{
cerr << "Cannot open " << save_macro_file << " for macro output" << endl;
cerr << "Cannot open " << save_macro_file.string() << " 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());
if (!line_macro)
{
// Remove the @#line directives.
str = regex_replace(str, regex(R"(^@#line.*$)", std::regex::multiline), "");
/* Remove the EOLs at the beginning of the output, the first one
being a remnant of the first @#line directive. */
str = regex_replace(str, regex(R"(^(\r?\n)+)"), "");
/* Replace sequences of several newlines by a single newline (in
both LF and CR+LF conventions). */
str = regex_replace(str, regex(R"(\n{2,})"), "\n");
str = regex_replace(str, regex(R"((\r\n){2,})"), "\r\n");
}
macro_output_file << str;
macro_output_file.close();
}
return macro_output;
}