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

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
Show changes
Commits on Source (67)
Showing with 1287 additions and 450 deletions
...@@ -11,9 +11,12 @@ BreakInheritanceList: AfterColon ...@@ -11,9 +11,12 @@ BreakInheritanceList: AfterColon
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
DeriveLineEnding: false DeriveLineEnding: false
IndentPPDirectives: AfterHash IndentPPDirectives: AfterHash
InsertNewlineAtEOF: true
PackConstructorInitializers: NextLine PackConstructorInitializers: NextLine
PPIndentWidth: 1 PPIndentWidth: 1
PointerAlignment: Left PointerAlignment: Left
# RemoveParentheses: ReturnStatement
# RemoveSemicolon: true
SpaceAfterTemplateKeyword: false SpaceAfterTemplateKeyword: false
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
SpaceBeforeCpp11BracedList: true SpaceBeforeCpp11BracedList: true
variables: variables:
TERM: linux TERM: linux
MINGW64_BOOST_VERSION: 1.85.0-2 MINGW64_BOOST_VERSION: 1.86.0-7
WGET_OPTIONS: '--no-verbose --no-use-server-timestamps --retry-connrefused --retry-on-host-error' WGET_OPTIONS: '--no-verbose --no-use-server-timestamps --retry-connrefused --retry-on-host-error'
# To ensure that "false && true" fails, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394#note_412609647 # To ensure that "false && true" fails, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394#note_412609647
FF_ENABLE_BASH_EXIT_CODE_CHECK: 'true' FF_ENABLE_BASH_EXIT_CODE_CHECK: 'true'
...@@ -77,3 +77,16 @@ test_clang_format: ...@@ -77,3 +77,16 @@ test_clang_format:
- meson setup build-clang-format - meson setup build-clang-format
- ninja -C build-clang-format clang-format-check - ninja -C build-clang-format clang-format-check
needs: [] needs: []
test_clang_tidy:
stage: test
script:
# Hack needed for meson < 1.6.0 which only looks for unversioned clang-tidy
- mkdir -p ~/.local/bin && ln -s /usr/bin/clang-tidy-19 ~/.local/bin/clang-tidy
- export PATH="$HOME/.local/bin:$PATH"
- meson setup build-clang-tidy
# Generate Flex and Bison files
- meson compile -C build-clang-tidy
- ninja -C build-clang-tidy clang-tidy
needs: []
when: manual
# Meson cross file for creating a WebAssembly version of the preprocessor.
#
# Requires emscripten to be installed.
# Was successfully tested with emscripten 3.1.69 installed through emsdk
# tool, as described on: https://emscripten.org/docs/getting_started/downloads.html
# Don’t forget to source script snippet in current shell before running meson.
#
# Compilation creates a .wasm and .js wrapper under <builddir>/src/
#
# Can be run locally with node.js using:
# node dynare-preprocessor.js file.mod
# NB: a version of node.js is shipped with emscripten (under the node/
# subdirectory), but another version should also work.
[binaries]
cpp = 'em++'
[host_machine]
system = 'emscripten'
# Could be changed to wasm64 if 4GB memory constraint is hit
# Some background: https://v8.dev/blog/4gb-wasm-memory
cpu_family = 'wasm32'
cpu = 'wasm32'
endian = 'little'
[built-in options]
# Never do a debug build, because otherwise the lack of optimisations can
# overflow the memory capacities.
buildtype = 'release'
# The -fexceptions flag (for both compilation and linking) is needed for an
# unknown reason (C++ compilers are supposed to always add exception support).
# The -Wno-unqualified-std-cast-call flag removes many warnings about “move”
# not being qualified with “std::” namespace.
# The -fexperimental-library flag is needed to get std::jthread support (it was
# supposed to no longer be necessary for LLVM 20, but for some reason we still
# need it).
cpp_args = [ '-fexceptions', '-Wno-unqualified-std-cast-call', '-fexperimental-library' ]
# NODERAWFS=1 is needed for accessing the local filesystem
cpp_link_args = [ '-s', 'NODERAWFS=1', '-fexceptions' ]
[properties]
# It’s necessary to use a different copy of Boost than the one under
# /usr/include, because otherwise GCC headers confuse Clang
boost_root = '/tmp/boost_1_86_0'
/* /*
* Copyright © 2007-2023 Dynare Team * Copyright © 2007-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -25,14 +25,17 @@ ...@@ -25,14 +25,17 @@
* command */ * command */
enum class SymbolType enum class SymbolType
{ {
endogenous = 0, //!< Endogenous endogenous = 0, // Endogenous (non-heterogeneous)
exogenous = 1, //!< Exogenous exogenous = 1, // Exogenous (non-heterogeneous)
exogenousDet = 2, //!< Exogenous deterministic exogenousDet = 2, // Exogenous deterministic (non-heterogeneous)
parameter = 4, //!< Parameter parameter = 4, // Parameter (non-heterogeneous)
modelLocalVariable = 10, //!< Local variable whose scope is model (pound expression) heterogeneousEndogenous = 5, // Endogenous that is heterogeneous across some dimension
modFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded) heterogeneousExogenous = 6, // Exogenous that is heterogeneous across some dimension
externalFunction = 12, //!< External (user-defined) function heterogeneousParameter = 7, // Parameter that is heterogeneous across some dimension
trend = 13, //!< Trend variable modelLocalVariable = 10, // Local variable whose scope is model (pound expression)
modFileLocalVariable = 11, // Local variable whose scope is mod file (model excluded)
externalFunction = 12, // External (user-defined) function
trend = 13, // Trend variable
statementDeclaredVariable statementDeclaredVariable
= 14, //!< Local variable assigned within a Statement (see subsample statement for example) = 14, //!< Local variable assigned within a Statement (see subsample statement for example)
logTrend = 15, //!< Log-trend variable logTrend = 15, //!< Log-trend variable
...@@ -45,6 +48,13 @@ enum class SymbolType ...@@ -45,6 +48,13 @@ enum class SymbolType
excludedVariable = 19 //!< Variable excluded via model_remove/var_remove/include_eqs/exclude_eqs excludedVariable = 19 //!< Variable excluded via model_remove/var_remove/include_eqs/exclude_eqs
}; };
constexpr bool
isHeterogeneous(SymbolType type)
{
return type == SymbolType::heterogeneousEndogenous || type == SymbolType::heterogeneousExogenous
|| type == SymbolType::heterogeneousParameter;
}
enum class UnaryOpcode enum class UnaryOpcode
{ {
uminus, uminus,
...@@ -75,7 +85,8 @@ enum class UnaryOpcode ...@@ -75,7 +85,8 @@ enum class UnaryOpcode
erf, erf,
erfc, erfc,
diff, diff,
adl adl,
sum
}; };
enum class BinaryOpcode enum class BinaryOpcode
......
...@@ -283,7 +283,9 @@ PerfectForesightWithExpectationErrorsSolverStatement::writeOutput( ...@@ -283,7 +283,9 @@ PerfectForesightWithExpectationErrorsSolverStatement::writeOutput(
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
output << "oo_ = perfect_foresight_with_expectation_errors_solver(M_, options_, oo_);" << endl; output << "[oo_, Simulated_time_series] = perfect_foresight_with_expectation_errors_solver(M_, "
"options_, oo_);"
<< endl;
} }
void void
...@@ -3713,8 +3715,7 @@ SvarGlobalIdentificationCheckStatement::writeJsonOutput(ostream& output) const ...@@ -3713,8 +3715,7 @@ SvarGlobalIdentificationCheckStatement::writeJsonOutput(ostream& output) const
output << R"({"statementName": "svar_global_identification"})"; output << R"({"statementName": "svar_global_identification"})";
} }
SetTimeStatement::SetTimeStatement(OptionsList options_list_arg) : SetTimeStatement::SetTimeStatement(string period_arg) : period {move(period_arg)}
options_list {move(options_list_arg)}
{ {
} }
...@@ -3722,19 +3723,13 @@ void ...@@ -3722,19 +3723,13 @@ void
SetTimeStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename, SetTimeStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); output << "options_.initial_period = " << period << endl;
} }
void void
SetTimeStatement::writeJsonOutput(ostream& output) const SetTimeStatement::writeJsonOutput(ostream& output) const
{ {
output << R"({"statementName": "set_time")"; output << R"({"statementName": "set_time", "period": ")" << period << R"("})";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
} }
EstimationDataStatement::EstimationDataStatement(OptionsList options_list_arg) : EstimationDataStatement::EstimationDataStatement(OptionsList options_list_arg) :
...@@ -5347,8 +5342,8 @@ void ...@@ -5347,8 +5342,8 @@ void
ResidStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename, ResidStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output, "options_resid_"); options_list.writeOutput(output);
output << "display_static_residuals(M_, options_, oo_, options_resid_);" << endl; output << "display_static_residuals(M_, options_, oo_);" << endl;
} }
void void
......
...@@ -524,7 +524,7 @@ public: ...@@ -524,7 +524,7 @@ public:
blockName() const override blockName() const override
{ {
return "estimated_params"; return "estimated_params";
}; }
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -542,7 +542,7 @@ public: ...@@ -542,7 +542,7 @@ public:
blockName() const override blockName() const override
{ {
return "estimated_params_init"; return "estimated_params_init";
}; }
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -557,7 +557,7 @@ public: ...@@ -557,7 +557,7 @@ public:
blockName() const override blockName() const override
{ {
return "estimated_params_bounds"; return "estimated_params_bounds";
}; }
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
...@@ -1007,10 +1007,10 @@ public: ...@@ -1007,10 +1007,10 @@ public:
class SetTimeStatement : public Statement class SetTimeStatement : public Statement
{ {
private: private:
const OptionsList options_list; const string period;
public: public:
explicit SetTimeStatement(OptionsList options_list_arg); explicit SetTimeStatement(string period_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
......
/* /*
* Copyright © 2010-2023 Dynare Team * Copyright © 2010-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -666,15 +666,14 @@ Configuration::transformPass() ...@@ -666,15 +666,14 @@ Configuration::transformPass()
} }
#endif #endif
auto cluster_it auto& cluster = cluster_name.empty() ? clusters.at(firstClusterName) : clusters.at(cluster_name);
= cluster_name.empty() ? clusters.find(firstClusterName) : clusters.find(cluster_name);
double weight_denominator {0.0}; double weight_denominator {0.0};
for (const auto& it : cluster_it->second.member_nodes) for (const auto& [name, weight] : cluster.member_nodes)
weight_denominator += it.second; weight_denominator += weight;
for (auto& member_node : cluster_it->second.member_nodes) for (auto& [name, weight] : cluster.member_nodes)
member_node.second /= weight_denominator; weight /= weight_denominator;
} }
vector<filesystem::path> vector<filesystem::path>
...@@ -701,51 +700,35 @@ Configuration::writeCluster(ostream& output) const ...@@ -701,51 +700,35 @@ Configuration::writeCluster(ostream& output) const
if (!parallel && !parallel_test) if (!parallel && !parallel_test)
return; return;
auto cluster_it const auto& cluster
= cluster_name.empty() ? clusters.find(firstClusterName) : clusters.find(cluster_name); = cluster_name.empty() ? clusters.at(firstClusterName) : clusters.at(cluster_name);
for (int i {1}; const auto& follower_node : follower_nodes) for (int i {1}; const auto& [name, node] : follower_nodes)
{ {
bool follower_node_in_member_nodes = false; if (!cluster.member_nodes.contains(name))
for (const auto& itmn : cluster_it->second.member_nodes) continue; // Skip nodes not in the selected cluster
if (follower_node.first == itmn.first)
follower_node_in_member_nodes = true;
if (!follower_node_in_member_nodes)
continue;
output << "options_.parallel"; output << "options_.parallel";
if (i > 1) if (i > 1)
output << "(" << i << ")"; output << "(" << i << ")";
i++; i++;
output << " = struct('Local', "; output << " = struct('Local', " << noboolalpha << (node.computerName == "localhost") << ", "
if (follower_node.second.computerName == "localhost") << "'ComputerName', '" << node.computerName << "', "
output << "1, "; << "'Port', '" << node.port << "', "
else << "'CPUnbr', [" << node.minCpuNbr << ":" << node.maxCpuNbr << "], "
output << "0, "; << "'UserName', '" << node.userName << "', "
<< "'Password', '" << node.password << "', "
output << "'ComputerName', '" << follower_node.second.computerName << "', " << "'RemoteDrive', '" << node.remoteDrive << "', "
<< "'Port', '" << follower_node.second.port << "', " << "'RemoteDirectory', '" << node.remoteDirectory
<< "'CPUnbr', [" << follower_node.second.minCpuNbr << ":"
<< follower_node.second.maxCpuNbr << "], "
<< "'UserName', '" << follower_node.second.userName << "', "
<< "'Password', '" << follower_node.second.password << "', "
<< "'RemoteDrive', '" << follower_node.second.remoteDrive << "', "
<< "'RemoteDirectory', '" << follower_node.second.remoteDirectory
<< "', " << "', "
// The following should be switched back to “ProgramPath” once we move to Dragonfly // The following should be switched back to “ProgramPath” once we move to Dragonfly
<< "'DynarePath', '" << follower_node.second.programPath << "', " << "'DynarePath', '" << node.programPath << "', "
<< "'ProgramConfig', '" << follower_node.second.programConfig << "', " << "'ProgramConfig', '" << node.programConfig << "', "
<< "'MatlabOctavePath', '" << follower_node.second.matlabOctavePath << "', " << "'MatlabOctavePath', '" << node.matlabOctavePath << "', "
<< "'OperatingSystem', '" << follower_node.second.operatingSystem << "', " << "'OperatingSystem', '" << node.operatingSystem << "', "
<< "'NodeWeight', '" << cluster_it->second.member_nodes.at(follower_node.first) << "'NodeWeight', '" << cluster.member_nodes.at(name) << "', "
<< "', " << "'NumberOfThreadsPerJob', " << node.numberOfThreadsPerJob << ", "
<< "'NumberOfThreadsPerJob', " << follower_node.second.numberOfThreadsPerJob << ", "; << "'SingleCompThread', '" << boolalpha << node.singleCompThread << "');" << endl;
if (follower_node.second.singleCompThread)
output << "'SingleCompThread', 'true');" << endl;
else
output << "'SingleCompThread', 'false');" << endl;
} }
// Default values for the following two are both in DynareMain.cc and // Default values for the following two are both in DynareMain.cc and
......
...@@ -47,7 +47,7 @@ private: ...@@ -47,7 +47,7 @@ private:
get_paths() const get_paths() const
{ {
return paths; return paths;
}; }
private: private:
map<string, vector<string>> paths; map<string, vector<string>> paths;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <iterator> #include <iterator>
#include <ranges>
#include "DataTree.hh" #include "DataTree.hh"
...@@ -47,10 +48,12 @@ DataTree::initConstants() ...@@ -47,10 +48,12 @@ DataTree::initConstants()
} }
DataTree::DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg, DataTree::DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, bool is_dynamic_arg) : ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg, bool is_dynamic_arg) :
symbol_table {symbol_table_arg}, symbol_table {symbol_table_arg},
num_constants {num_constants_arg}, num_constants {num_constants_arg},
external_functions_table {external_functions_table_arg}, external_functions_table {external_functions_table_arg},
heterogeneity_table {heterogeneity_table_arg},
is_dynamic {is_dynamic_arg} is_dynamic {is_dynamic_arg}
{ {
initConstants(); initConstants();
...@@ -60,19 +63,21 @@ DataTree::DataTree(const DataTree& d) : ...@@ -60,19 +63,21 @@ DataTree::DataTree(const DataTree& d) :
symbol_table {d.symbol_table}, symbol_table {d.symbol_table},
num_constants {d.num_constants}, num_constants {d.num_constants},
external_functions_table {d.external_functions_table}, external_functions_table {d.external_functions_table},
heterogeneity_table {d.heterogeneity_table},
is_dynamic {d.is_dynamic}, is_dynamic {d.is_dynamic},
local_variables_vector {d.local_variables_vector} local_variables_vector {d.local_variables_vector}
{ {
// Constants must be initialized first because they are used in some Add* methods // Constants must be initialized first because they are used in some Add* methods
initConstants(); initConstants();
// See commment in DataTree::operator=() for the rationale
for (int symb_id : d.local_variables_vector)
local_variables_table[symb_id] = d.local_variables_table.at(symb_id)->clone(*this);
for (const auto& it : d.node_list) for (const auto& it : d.node_list)
it->clone(*this); it->clone(*this);
assert(node_list.size() == d.node_list.size()); assert(node_list.size() == d.node_list.size());
for (const auto& [symb_id, value] : d.local_variables_table)
local_variables_table[symb_id] = value->clone(*this);
} }
DataTree& DataTree&
...@@ -81,6 +86,7 @@ DataTree::operator=(const DataTree& d) ...@@ -81,6 +86,7 @@ DataTree::operator=(const DataTree& d)
assert(&symbol_table == &d.symbol_table); assert(&symbol_table == &d.symbol_table);
assert(&num_constants == &d.num_constants); assert(&num_constants == &d.num_constants);
assert(&external_functions_table == &d.external_functions_table); assert(&external_functions_table == &d.external_functions_table);
assert(&heterogeneity_table == &d.heterogeneity_table);
assert(is_dynamic == d.is_dynamic); assert(is_dynamic == d.is_dynamic);
num_const_node_map.clear(); num_const_node_map.clear();
...@@ -791,12 +797,18 @@ DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<exp ...@@ -791,12 +797,18 @@ DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<exp
return p; return p;
} }
expr_t
DataTree::AddSum(expr_t arg)
{
return AddUnaryOp(UnaryOpcode::sum, arg);
}
bool bool
DataTree::isSymbolUsed(int symb_id) const DataTree::isSymbolUsed(int symb_id) const
{ {
for (const auto& [symb_lag, expr] : variable_node_map) if (ranges::any_of(views::keys(variable_node_map),
if (symb_lag.first == symb_id) [=](const auto& symb_lag) { return symb_lag.first == symb_id; }))
return true; return true;
if (local_variables_table.contains(symb_id)) if (local_variables_table.contains(symb_id))
return true; return true;
...@@ -842,18 +854,18 @@ DataTree::addAllParamDerivId([[maybe_unused]] set<int>& deriv_id_set) ...@@ -842,18 +854,18 @@ DataTree::addAllParamDerivId([[maybe_unused]] set<int>& deriv_id_set)
bool bool
DataTree::isUnaryOpUsed(UnaryOpcode opcode) const DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
{ {
return ranges::any_of(unary_op_node_map, return ranges::any_of(views::keys(unary_op_node_map),
[=](const auto& it) { return get<1>(it.first) == opcode; }); [=](const auto& key) { return get<1>(key) == opcode; });
} }
bool bool
DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const
{ {
set<int> var; set<int> var;
for (const auto& it : unary_op_node_map) for (const auto& [key, value] : unary_op_node_map)
if (get<1>(it.first) == opcode) if (get<1>(key) == opcode)
{ {
it.second->collectVariables(type, var); value->collectVariables(type, var);
if (!var.empty()) if (!var.empty())
return true; return true;
} }
...@@ -863,18 +875,18 @@ DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const ...@@ -863,18 +875,18 @@ DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const
bool bool
DataTree::isBinaryOpUsed(BinaryOpcode opcode) const DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
{ {
return ranges::any_of(binary_op_node_map, return ranges::any_of(views::keys(binary_op_node_map),
[=](const auto& it) { return get<2>(it.first) == opcode; }); [=](const auto& key) { return get<2>(key) == opcode; });
} }
bool bool
DataTree::isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const DataTree::isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const
{ {
set<int> var; set<int> var;
for (const auto& it : binary_op_node_map) for (const auto& [key, value] : binary_op_node_map)
if (get<2>(it.first) == opcode) if (get<2>(key) == opcode)
{ {
it.second->collectVariables(type, var); value->collectVariables(type, var);
if (!var.empty()) if (!var.empty())
return true; return true;
} }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "ExprNode.hh" #include "ExprNode.hh"
#include "ExternalFunctionsTable.hh" #include "ExternalFunctionsTable.hh"
#include "HeterogeneityTable.hh"
#include "NumericalConstants.hh" #include "NumericalConstants.hh"
#include "SubModel.hh" #include "SubModel.hh"
#include "SymbolTable.hh" #include "SymbolTable.hh"
...@@ -48,6 +49,8 @@ public: ...@@ -48,6 +49,8 @@ public:
NumericalConstants& num_constants; NumericalConstants& num_constants;
//! A reference to the external functions table //! A reference to the external functions table
ExternalFunctionsTable& external_functions_table; ExternalFunctionsTable& external_functions_table;
// A reference to the heterogeneity table
HeterogeneityTable& heterogeneity_table;
//! Is it possible to use leads/lags on variable nodes? //! Is it possible to use leads/lags on variable nodes?
/* NB: This data member cannot be replaced by a virtual method, because this information is needed /* 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. */ in AddVariable(), which itself can be called from the copy constructor. */
...@@ -139,7 +142,8 @@ private: ...@@ -139,7 +142,8 @@ private:
public: public:
DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg, DataTree(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, bool is_dynamic_arg = false); ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg, bool is_dynamic_arg = false);
virtual ~DataTree() = default; virtual ~DataTree() = default;
...@@ -275,6 +279,9 @@ public: ...@@ -275,6 +279,9 @@ public:
//! Adds an external function node for the second derivative of an external function //! Adds an external function node for the second derivative of an external function
expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments, expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t>& arguments,
int input_index1, int input_index2); int input_index1, int input_index2);
// Adds "SUM(arg)" to model tree
expr_t AddSum(expr_t arg);
//! Checks if a given symbol is used somewhere in the data tree //! Checks if a given symbol is used somewhere in the data tree
[[nodiscard]] bool isSymbolUsed(int symb_id) const; [[nodiscard]] bool isSymbolUsed(int symb_id) const;
//! Checks if a given unary op is used somewhere in the data tree //! Checks if a given unary op is used somewhere in the data tree
...@@ -360,7 +367,13 @@ public: ...@@ -360,7 +367,13 @@ public:
if (it == local_variables_table.end()) if (it == local_variables_table.end())
throw UnknownLocalVariableException {symb_id}; throw UnknownLocalVariableException {symb_id};
return it->second->decreaseLeadsLags(-lead_lag); /* 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 static void
...@@ -389,7 +402,7 @@ DataTree::AddPossiblyNegativeConstant(double v) ...@@ -389,7 +402,7 @@ DataTree::AddPossiblyNegativeConstant(double v)
if (isnan(v)) if (isnan(v))
return NaN; return NaN;
if (isinf(v)) if (isinf(v))
return (v < 0 ? MinusInfinity : Infinity); return v < 0 ? MinusInfinity : Infinity;
bool neg = false; bool neg = false;
if (v < 0) if (v < 0)
......
/* /*
* Copyright © 2003-2024 Dynare Team * Copyright © 2003-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -50,9 +50,11 @@ DynamicModel::copyHelper(const DynamicModel& m) ...@@ -50,9 +50,11 @@ DynamicModel::copyHelper(const DynamicModel& m)
DynamicModel::DynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg, DynamicModel::DynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg,
TrendComponentModelTable& trend_component_model_table_arg, TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg) : VarModelTable& var_model_table_arg) :
ModelTree {symbol_table_arg, num_constants_arg, external_functions_table_arg, true}, ModelTree {symbol_table_arg, num_constants_arg, external_functions_table_arg,
heterogeneity_table_arg, true},
trend_component_model_table {trend_component_model_table_arg}, trend_component_model_table {trend_component_model_table_arg},
var_model_table {var_model_table_arg} var_model_table {var_model_table_arg}
{ {
...@@ -180,32 +182,29 @@ DynamicModel::writeDynamicBytecode(const string& basename) const ...@@ -180,32 +182,29 @@ DynamicModel::writeDynamicBytecode(const string& basename) const
+ temporary_terms_derivatives[1].size())}; + temporary_terms_derivatives[1].size())};
// Declare the (single) block // Declare the (single) block
vector<int> exo(symbol_table.exo_nbr()), exo_det(symbol_table.exo_det_nbr()); auto exo = views::iota(0, symbol_table.exo_nbr());
iota(exo.begin(), exo.end(), 0); auto exo_det = views::iota(0, symbol_table.exo_det_nbr());
iota(exo_det.begin(), exo_det.end(), 0); auto eq_idx = views::iota(0, static_cast<int>(equations.size()));
auto endo_idx = views::iota(0, symbol_table.endo_nbr());
int jacobian_ncols_endo { int jacobian_ncols_endo {
static_cast<int>(ranges::count_if(dyn_jacobian_cols_table, [this](const auto& v) { static_cast<int>(ranges::count_if(dyn_jacobian_cols_table, [this](const auto& v) {
return getTypeByDerivID(v.first) == SymbolType::endogenous; return getTypeByDerivID(v.first) == SymbolType::endogenous;
}))}; }))};
vector<int> eq_idx(equations.size());
iota(eq_idx.begin(), eq_idx.end(), 0);
vector<int> endo_idx(symbol_table.endo_nbr());
iota(endo_idx.begin(), endo_idx.end(), 0);
code_file << Bytecode::FBEGINBLOCK {symbol_table.endo_nbr(), code_file << Bytecode::FBEGINBLOCK {symbol_table.endo_nbr(),
simulation_type, simulation_type,
0, 0,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
endo_idx, {endo_idx.begin(), endo_idx.end()},
eq_idx, {eq_idx.begin(), eq_idx.end()},
false, false,
u_count_int, u_count_int,
jacobian_ncols_endo, jacobian_ncols_endo,
symbol_table.exo_det_nbr(), symbol_table.exo_det_nbr(),
symbol_table.exo_nbr(), symbol_table.exo_nbr(),
exo_det, {exo_det.begin(), exo_det.end()},
exo}; {exo.begin(), exo.end()}};
writeBytecodeHelper<true>(code_file); writeBytecodeHelper<true>(code_file);
} }
...@@ -732,9 +731,9 @@ DynamicModel::removeEquationsHelper( ...@@ -732,9 +731,9 @@ DynamicModel::removeEquationsHelper(
} }
int n_excl = all_equations.size() - new_equations.size(); int n_excl = all_equations.size() - new_equations.size();
all_equations = new_equations; all_equations = move(new_equations);
all_equations_lineno = new_equations_lineno; all_equations_lineno = move(new_equations_lineno);
all_complementarity_conditions = new_complementarity_conditions; all_complementarity_conditions = move(new_complementarity_conditions);
all_equation_tags.erase(eqs_to_delete_by_number, old_eqn_num_2_new); all_equation_tags.erase(eqs_to_delete_by_number, old_eqn_num_2_new);
...@@ -1044,14 +1043,8 @@ DynamicModel::writeDriverOutput(ostream& output, bool compute_xrefs) const ...@@ -1044,14 +1043,8 @@ DynamicModel::writeDriverOutput(ostream& output, bool compute_xrefs) const
<< (static_only_equations.size() > 0) << ";" << endl; << (static_only_equations.size() > 0) << ";" << endl;
// Say if model contains an external function call // Say if model contains an external function call
bool has_external_function = false; output << "M_.has_external_function = " << boolalpha
for (auto equation : equations) << ranges::any_of(equations, &ExprNode::containsExternalFunction) << ';' << endl;
if (equation->containsExternalFunction())
{
has_external_function = true;
break;
}
output << "M_.has_external_function = " << boolalpha << has_external_function << ';' << endl;
// Compute list of state variables, ordered in block-order // Compute list of state variables, ordered in block-order
vector<int> state_var; vector<int> state_var;
...@@ -1136,7 +1129,7 @@ DynamicModel::writeDriverOutput(ostream& output, bool compute_xrefs) const ...@@ -1136,7 +1129,7 @@ DynamicModel::writeDriverOutput(ostream& output, bool compute_xrefs) const
output << (i > computed_derivs_order ? -1 : NNZDerivatives[i]) << "; "; output << (i > computed_derivs_order ? -1 : NNZDerivatives[i]) << "; ";
output << "];" << endl; output << "];" << endl;
writeDriverSparseIndicesHelper<true, false>(output); writeDriverSparseIndicesHelper("dynamic", output);
// Write LHS of each equation in text form // Write LHS of each equation in text form
output << "M_.lhs = {" << endl; output << "M_.lhs = {" << endl;
...@@ -1360,8 +1353,7 @@ DynamicModel::fillVarModelTableFromOrigModel() const ...@@ -1360,8 +1353,7 @@ DynamicModel::fillVarModelTableFromOrigModel() const
// save lhs variables // save lhs variables
equations[eqn]->arg1->collectVARLHSVariable(lhs); equations[eqn]->arg1->collectVARLHSVariable(lhs);
equations[eqn]->arg1->countDiffs() > 0 ? diff_vec.push_back(true) diff_vec.push_back(equations[eqn]->arg1->countDiffs() > 0);
: diff_vec.push_back(false);
if (diff_vec.back()) if (diff_vec.back())
{ {
set<pair<int, int>> diff_set; set<pair<int, int>> diff_set;
...@@ -1705,10 +1697,7 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const ...@@ -1705,10 +1697,7 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel() const
// save lhs variables // save lhs variables
equations[eqn]->arg1->collectVARLHSVariable(lhs); equations[eqn]->arg1->collectVARLHSVariable(lhs);
if (equations[eqn]->arg1->countDiffs() > 0) diff_vec.push_back(equations[eqn]->arg1->countDiffs() > 0);
diff_vec.push_back(true);
else
diff_vec.push_back(false);
if (diff_vec.back()) if (diff_vec.back())
{ {
set<pair<int, int>> diff_set; set<pair<int, int>> diff_set;
...@@ -1781,7 +1770,7 @@ DynamicModel::getUndiffLHSForPac(const string& aux_model_name, ...@@ -1781,7 +1770,7 @@ DynamicModel::getUndiffLHSForPac(const string& aux_model_name,
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (diff.at(i) != true) if (!diff.at(i))
{ {
cerr << "ERROR: the variable on the LHS of equation #" << eqn cerr << "ERROR: the variable on the LHS of equation #" << eqn
<< " does not have the diff operator applied to it yet you are trying to undiff it." << " does not have the diff operator applied to it yet you are trying to undiff it."
...@@ -1789,7 +1778,6 @@ DynamicModel::getUndiffLHSForPac(const string& aux_model_name, ...@@ -1789,7 +1778,6 @@ DynamicModel::getUndiffLHSForPac(const string& aux_model_name,
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
bool printerr = false;
expr_t node = nullptr; expr_t node = nullptr;
expr_t aux_var = lhs_expr_t.at(i); expr_t aux_var = lhs_expr_t.at(i);
for (const auto& it : diff_subst_table) for (const auto& it : diff_subst_table)
...@@ -1806,11 +1794,8 @@ DynamicModel::getUndiffLHSForPac(const string& aux_model_name, ...@@ -1806,11 +1794,8 @@ DynamicModel::getUndiffLHSForPac(const string& aux_model_name,
} }
node = node->undiff(); node = node->undiff();
auto it1 = diff_subst_table.find(node);
if (it1 == diff_subst_table.end())
printerr = true;
if (printerr) if (auto it1 = diff_subst_table.find(node); it1 == diff_subst_table.end())
{ // we have undiffed something like diff(x), hence x is not in diff_subst_table { // we have undiffed something like diff(x), hence x is not in diff_subst_table
lhs_expr_t.at(i) = node; lhs_expr_t.at(i) = node;
lhs.at(i) = dynamic_cast<VariableNode*>(node)->symb_id; lhs.at(i) = dynamic_cast<VariableNode*>(node)->symb_id;
...@@ -1831,7 +1816,7 @@ DynamicModel::analyzePacEquationStructure(const string& name, map<string, string ...@@ -1831,7 +1816,7 @@ DynamicModel::analyzePacEquationStructure(const string& name, map<string, string
for (auto& equation : equations) for (auto& equation : equations)
if (equation->containsPacExpectation(name)) if (equation->containsPacExpectation(name))
{ {
if (!pac_eq_name[name].empty()) if (pac_eq_name.contains(name))
{ {
cerr << "It is not possible to use 'pac_expectation(" << name cerr << "It is not possible to use 'pac_expectation(" << name
<< ")' in several equations." << endl; << ")' in several equations." << endl;
...@@ -1930,6 +1915,13 @@ DynamicModel::analyzePacEquationStructure(const string& name, map<string, string ...@@ -1930,6 +1915,13 @@ DynamicModel::analyzePacEquationStructure(const string& name, map<string, string
move(additive_vars_params_and_constants), move(additive_vars_params_and_constants),
move(optim_additive_vars_params_and_constants)}; move(optim_additive_vars_params_and_constants)};
} }
if (!pac_eq_name.contains(name))
{
cerr << "ERROR: the model does not contain the 'pac_expectation(" << name << ")' operator."
<< endl;
exit(EXIT_FAILURE);
}
} }
int int
...@@ -3040,8 +3032,7 @@ DynamicModel::findUnusedEndogenous() ...@@ -3040,8 +3032,7 @@ DynamicModel::findUnusedEndogenous()
for (auto& equation : static_only_equations) for (auto& equation : static_only_equations)
equation->collectVariables(SymbolType::endogenous, usedEndo); equation->collectVariables(SymbolType::endogenous, usedEndo);
set<int> allEndo = symbol_table.getEndogenous(); set<int> allEndo = symbol_table.getEndogenous();
set_difference(allEndo.begin(), allEndo.end(), usedEndo.begin(), usedEndo.end(), ranges::set_difference(allEndo, usedEndo, inserter(unusedEndo, unusedEndo.begin()));
inserter(unusedEndo, unusedEndo.begin()));
return unusedEndo; return unusedEndo;
} }
...@@ -3055,10 +3046,8 @@ DynamicModel::findUnusedExogenous() ...@@ -3055,10 +3046,8 @@ DynamicModel::findUnusedExogenous()
equation->collectVariables(SymbolType::exogenous, usedExo); equation->collectVariables(SymbolType::exogenous, usedExo);
set<int> observedExo = symbol_table.getObservedExogenous(); set<int> observedExo = symbol_table.getObservedExogenous();
set<int> allExo = symbol_table.getExogenous(); set<int> allExo = symbol_table.getExogenous();
set_difference(allExo.begin(), allExo.end(), observedExo.begin(), observedExo.end(), ranges::set_difference(allExo, observedExo, inserter(unobservedExo, unobservedExo.begin()));
inserter(unobservedExo, unobservedExo.begin())); ranges::set_difference(unobservedExo, usedExo, inserter(unusedExo, unusedExo.begin()));
set_difference(unobservedExo.begin(), unobservedExo.end(), usedExo.begin(), usedExo.end(),
inserter(unusedExo, unusedExo.begin()));
return unusedExo; return unusedExo;
} }
...@@ -3498,10 +3487,8 @@ pair<lag_equivalence_table_t, ExprNode::subst_table_t> ...@@ -3498,10 +3487,8 @@ pair<lag_equivalence_table_t, ExprNode::subst_table_t>
DynamicModel::substituteUnaryOps(VarExpectationModelTable& var_expectation_model_table, DynamicModel::substituteUnaryOps(VarExpectationModelTable& var_expectation_model_table,
PacModelTable& pac_model_table) PacModelTable& pac_model_table)
{ {
vector<int> eqnumbers(equations.size()); auto v = views::iota(0, static_cast<int>(equations.size()));
iota(eqnumbers.begin(), eqnumbers.end(), 0); return substituteUnaryOps({v.begin(), v.end()}, var_expectation_model_table, pac_model_table);
return substituteUnaryOps({eqnumbers.begin(), eqnumbers.end()}, var_expectation_model_table,
pac_model_table);
} }
pair<lag_equivalence_table_t, ExprNode::subst_table_t> pair<lag_equivalence_table_t, ExprNode::subst_table_t>
...@@ -3705,6 +3692,36 @@ DynamicModel::substituteLogTransform() ...@@ -3705,6 +3692,36 @@ DynamicModel::substituteLogTransform()
} }
} }
void
DynamicModel::substituteAggregationOperators()
{
ExprNode::subst_table_t subst_table;
vector<BinaryOpNode*> neweqs;
for (auto& [symb_id, expr] : local_variables_table)
expr = expr->substituteAggregationOperators(subst_table, neweqs);
for (auto& equation : equations)
{
equation = dynamic_cast<BinaryOpNode*>(
equation->substituteAggregationOperators(subst_table, neweqs));
assert(equation);
}
for (auto& equation : static_only_equations)
{
equation = dynamic_cast<BinaryOpNode*>(
equation->substituteAggregationOperators(subst_table, neweqs));
assert(equation);
}
for (auto neweq : neweqs)
{
addEquation(neweq, nullopt);
addAuxEquation(neweq);
}
}
void void
DynamicModel::checkNoWithLogTransform(const set<int>& eqnumbers) DynamicModel::checkNoWithLogTransform(const set<int>& eqnumbers)
{ {
...@@ -3731,18 +3748,18 @@ void ...@@ -3731,18 +3748,18 @@ void
DynamicModel::detrendEquations() DynamicModel::detrendEquations()
{ {
// We go backwards in the list of trend_vars, to deal correctly with I(2) processes // We go backwards in the list of trend_vars, to deal correctly with I(2) processes
for (const auto& it : std::ranges::reverse_view(nonstationary_symbols_map)) for (const auto& [symb_id, deflator] : std::ranges::reverse_view(nonstationary_symbols_map))
{ {
for (auto& equation : equations) for (auto& equation : equations)
{ {
equation = dynamic_cast<BinaryOpNode*>( equation = dynamic_cast<BinaryOpNode*>(
equation->detrend(it.first, it.second.first, it.second.second)); equation->detrend(symb_id, deflator.first, deflator.second));
assert(equation); assert(equation);
} }
for (auto& equation : static_only_equations) for (auto& equation : static_only_equations)
{ {
equation = dynamic_cast<BinaryOpNode*>( equation = dynamic_cast<BinaryOpNode*>(
equation->detrend(it.first, it.second.first, it.second.second)); equation->detrend(symb_id, deflator.first, deflator.second));
assert(equation); assert(equation);
} }
} }
......
...@@ -73,7 +73,8 @@ public: ...@@ -73,7 +73,8 @@ public:
void checkAllRegimesPresent() const noexcept(false); void checkAllRegimesPresent() const noexcept(false);
private: private:
pair<vector<string>, vector<string>> convertBitVectorToRegimes(const vector<bool>& r) const; [[nodiscard]] pair<vector<string>, vector<string>>
convertBitVectorToRegimes(const vector<bool>& r) const;
}; };
private: private:
...@@ -325,6 +326,7 @@ protected: ...@@ -325,6 +326,7 @@ protected:
public: public:
DynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg, DynamicModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg, ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg,
TrendComponentModelTable& trend_component_model_table_arg, TrendComponentModelTable& trend_component_model_table_arg,
VarModelTable& var_model_table_arg); VarModelTable& var_model_table_arg);
...@@ -566,6 +568,10 @@ public: ...@@ -566,6 +568,10 @@ public:
// Performs the transformations associated to variables declared with “var(log)” // Performs the transformations associated to variables declared with “var(log)”
void substituteLogTransform(); 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 // Check that no variable was declared with “var(log)” in the given equations
void checkNoWithLogTransform(const set<int>& eqnumbers); void checkNoWithLogTransform(const set<int>& eqnumbers);
...@@ -708,7 +714,7 @@ public: ...@@ -708,7 +714,7 @@ public:
{ {
return tuple {static_only_equations, static_only_equations_lineno, return tuple {static_only_equations, static_only_equations_lineno,
static_only_complementarity_conditions, static_only_equations_equation_tags}; static_only_complementarity_conditions, static_only_equations_equation_tags};
}; }
//! Returns true if a parameter was used in the model block with a lead or lag //! Returns true if a parameter was used in the model block with a lead or lag
bool ParamUsedWithLeadLag() const; bool ParamUsedWithLeadLag() const;
......
// -*- C++ -*- // -*- C++ -*-
/* /*
* Copyright © 2003-2024 Dynare Team * Copyright © 2003-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -28,20 +28,20 @@ ...@@ -28,20 +28,20 @@
%define parse.error verbose %define parse.error verbose
%define parse.trace %define parse.trace
%code top {
class ParsingDriver;
}
%code requires { %code requires {
// Only headers needed for the value and location types go here
// Headers needed by the Bison file itself go in the unqualified %code section
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <utility>
#include <tuple> #include <tuple>
#include <variant> #include <variant>
#include "CommonEnums.hh" #include "CommonEnums.hh"
#include "ExprNode.hh" #include "ExprNode.hh"
#include "Shocks.hh"
class ParsingDriver;
} }
%param { ParsingDriver &driver } %param { ParsingDriver &driver }
...@@ -54,6 +54,9 @@ class ParsingDriver; ...@@ -54,6 +54,9 @@ class ParsingDriver;
} }
%code { %code {
#include <ranges>
#include <utility>
/* Little hack: we redefine the macro which computes the locations, because /* Little hack: we redefine the macro which computes the locations, because
we need to access the location from within the parsing driver for error we need to access the location from within the parsing driver for error
and warning messages. */ and warning messages. */
...@@ -87,7 +90,7 @@ string ...@@ -87,7 +90,7 @@ string
str_tolower(string s) str_tolower(string s)
{ {
// Converting to unsigned char is needed, see https://en.cppreference.com/w/cpp/string/byte/tolower // Converting to unsigned char is needed, see https://en.cppreference.com/w/cpp/string/byte/tolower
transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); }); ranges::transform(s, s.begin(), [](unsigned char c){ return std::tolower(c); });
return s; return s;
} }
} }
...@@ -104,11 +107,11 @@ str_tolower(string s) ...@@ -104,11 +107,11 @@ str_tolower(string s)
%token END ENDVAL EQUAL ESTIMATION ESTIMATED_PARAMS ESTIMATED_PARAMS_BOUNDS ESTIMATED_PARAMS_INIT EXTENDED_PATH ENDOGENOUS_PRIOR EXPRESSION %token END ENDVAL EQUAL ESTIMATION ESTIMATED_PARAMS ESTIMATED_PARAMS_BOUNDS ESTIMATED_PARAMS_INIT EXTENDED_PATH ENDOGENOUS_PRIOR EXPRESSION
%token FILENAME DIRNAME FILTER_STEP_AHEAD FILTERED_VARS FIRST_OBS FIRST_SIMULATION_PERIOD LAST_SIMULATION_PERIOD LAST_OBS %token FILENAME DIRNAME FILTER_STEP_AHEAD FILTERED_VARS FIRST_OBS FIRST_SIMULATION_PERIOD LAST_SIMULATION_PERIOD LAST_OBS
%token SET_TIME OSR_PARAMS_BOUNDS KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED %token SET_TIME OSR_PARAMS_BOUNDS KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED
%token <string> FALSE FLOAT_NUMBER DATES %token <string> FALSE FLOAT_NUMBER DATE
%token DEFAULT FIXED_POINT FLIP OPT_ALGO COMPILATION_SETUP COMPILER ADD_FLAGS SUBSTITUTE_FLAGS ADD_LIBS SUBSTITUTE_LIBS %token DEFAULT FIXED_POINT FLIP OPT_ALGO COMPILATION_SETUP COMPILER ADD_FLAGS SUBSTITUTE_FLAGS ADD_LIBS SUBSTITUTE_LIBS
%token FORECAST K_ORDER_SOLVER INSTRUMENTS SHIFT MEAN STDEV VARIANCE MODE INTERVAL SHAPE DOMAINN %token FORECAST K_ORDER_SOLVER INSTRUMENTS SHIFT MEAN STDEV VARIANCE MODE INTERVAL SHAPE DOMAINN
%token GAMMA_PDF GRAPH GRAPH_FORMAT CONDITIONAL_VARIANCE_DECOMPOSITION NOCHECK STD %token GAMMA_PDF GRAPH GRAPH_FORMAT CONDITIONAL_VARIANCE_DECOMPOSITION NOCHECK STD
%token HISTVAL HISTVAL_FILE HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS HOMOTOPY_FORCE_CONTINUE HP_FILTER HP_NGRID FILTERED_THEORETICAL_MOMENTS_GRID HYBRID ONE_SIDED_HP_FILTER %token HISTVAL HISTVAL_FILE HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS HOMOTOPY_FORCE_CONTINUE HP_FILTER HP_NGRID FILTERED_THEORETICAL_MOMENTS_GRID HYBRID USE_FIRST_ORDER_SOLUTION ONE_SIDED_HP_FILTER
%token IDENTIFICATION INF_CONSTANT INITVAL INITVAL_FILE BOUNDS JSCALE INIT INFILE INVARS %token IDENTIFICATION INF_CONSTANT INITVAL INITVAL_FILE BOUNDS JSCALE INIT INFILE INVARS
%token <string> INT_NUMBER %token <string> INT_NUMBER
%token CONDITIONAL_LIKELIHOOD %token CONDITIONAL_LIKELIHOOD
...@@ -170,7 +173,8 @@ str_tolower(string s) ...@@ -170,7 +173,8 @@ str_tolower(string s)
%token VLISTLOG VLISTPER SPECTRAL_DENSITY INIT2SHOCKS %token VLISTLOG VLISTPER SPECTRAL_DENSITY INIT2SHOCKS
%token RESTRICTION RESTRICTION_FNAME CROSS_RESTRICTIONS NLAGS CONTEMP_REDUCED_FORM REAL_PSEUDO_FORECAST %token RESTRICTION RESTRICTION_FNAME CROSS_RESTRICTIONS NLAGS CONTEMP_REDUCED_FORM REAL_PSEUDO_FORECAST
%token DUMMY_OBS NSTATES INDXSCALESSTATES NO_BAYESIAN_PRIOR SPECIFICATION SIMS_ZHA %token DUMMY_OBS NSTATES INDXSCALESSTATES NO_BAYESIAN_PRIOR SPECIFICATION SIMS_ZHA
%token <string> ALPHA BETA ABAND NINV CMS NCMS CNUM GAMMA INV_GAMMA INV_GAMMA1 INV_GAMMA2 NORMAL UNIFORM EPS PDF FIG DR NONE PRIOR PRIOR_VARIANCE HESSIAN IDENTITY_MATRIX DIRICHLET DIAGONAL OPTIMAL MFS %token <string> ALPHA BETA ABAND NINV CMS NCMS CNUM GAMMA INV_GAMMA INV_GAMMA1 INV_GAMMA2 NORMAL UNIFORM EPS PDF FIG DR NONE PRIOR DIRICHLET MFS RESIDUAL
%token PRIOR_VARIANCE HESSIAN IDENTITY_MATRIX
%token GSIG2_LMDM Q_DIAG FLAT_PRIOR NCSK NSTD WEIBULL WEIBULL_PDF %token GSIG2_LMDM Q_DIAG FLAT_PRIOR NCSK NSTD WEIBULL WEIBULL_PDF
%token INDXPARR INDXOVR INDXAP APBAND INDXIMF INDXFORE FOREBAND INDXGFOREHAT INDXGIMFHAT %token INDXPARR INDXOVR INDXAP APBAND INDXIMF INDXFORE FOREBAND INDXGFOREHAT INDXGIMFHAT
%token INDXESTIMA INDXGDLS EQ_MS FILTER_COVARIANCE UPDATED_COVARIANCE FILTER_DECOMPOSITION SMOOTHED_STATE_UNCERTAINTY SMOOTHER_REDUX %token INDXESTIMA INDXGDLS EQ_MS FILTER_COVARIANCE UPDATED_COVARIANCE FILTER_DECOMPOSITION SMOOTHED_STATE_UNCERTAINTY SMOOTHER_REDUX
...@@ -216,12 +220,13 @@ str_tolower(string s) ...@@ -216,12 +220,13 @@ str_tolower(string s)
%token HOMOTOPY_MAX_COMPLETION_SHARE HOMOTOPY_MIN_STEP_SIZE HOMOTOPY_INITIAL_STEP_SIZE HOMOTOPY_STEP_SIZE_INCREASE_SUCCESS_COUNT %token HOMOTOPY_MAX_COMPLETION_SHARE HOMOTOPY_MIN_STEP_SIZE HOMOTOPY_INITIAL_STEP_SIZE HOMOTOPY_STEP_SIZE_INCREASE_SUCCESS_COUNT
%token HOMOTOPY_LINEARIZATION_FALLBACK HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK HOMOTOPY_EXCLUDE_VAREXO FROM_INITVAL_TO_ENDVAL %token HOMOTOPY_LINEARIZATION_FALLBACK HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK HOMOTOPY_EXCLUDE_VAREXO FROM_INITVAL_TO_ENDVAL
%token STATIC_MFS RELATIVE_TO_INITVAL MATCHED_IRFS MATCHED_IRFS_WEIGHTS WEIGHTS PERPENDICULAR %token STATIC_MFS RELATIVE_TO_INITVAL MATCHED_IRFS MATCHED_IRFS_WEIGHTS WEIGHTS PERPENDICULAR
%token HETEROGENEITY HETEROGENEITY_DIMENSION SUM PERFECT_FORESIGHT_CONTROLLED_PATHS EXOGENIZE ENDOGENIZE
%token <vector<string>> SYMBOL_VEC %token <vector<string>> SYMBOL_VEC
%type <expr_t> expression expression_or_empty %type <expr_t> expression expression_or_empty
%type <expr_t> equation hand_side %type <expr_t> equation hand_side
%type <string> non_negative_number signed_number signed_integer date_str %type <string> non_negative_number signed_number signed_integer
%type <string> filename symbol namespace_qualified_filename namespace_qualified_symbol %type <string> filename symbol namespace_qualified_filename namespace_qualified_symbol
%type <string> date_expr signed_inf signed_number_w_inf range %type <string> date_expr signed_inf signed_number_w_inf range
%type <string> integer_range signed_integer_range boolean %type <string> integer_range signed_integer_range boolean
...@@ -241,22 +246,26 @@ str_tolower(string s) ...@@ -241,22 +246,26 @@ str_tolower(string s)
%type <vector<map<string, string>>> tag_pair_list_for_selection %type <vector<map<string, string>>> tag_pair_list_for_selection
%type <map<string, string>> tag_pair_list %type <map<string, string>> tag_pair_list
%type <tuple<string,string,string,string>> prior_eq_opt options_eq_opt %type <tuple<string,string,string,string>> prior_eq_opt options_eq_opt
%type <vector<pair<int, int>>> period_list %type <AbstractShocksStatement::period_range_t> period_range
%type <vector<AbstractShocksStatement::period_range_t>> period_list
%type <vector<expr_t>> matched_moments_list value_list ramsey_constraints_list %type <vector<expr_t>> matched_moments_list value_list ramsey_constraints_list
%type <tuple<string, BinaryOpNode *, BinaryOpNode *, expr_t, expr_t>> occbin_constraints_regime %type <tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> occbin_constraints_regime
%type <vector<tuple<string, BinaryOpNode *, BinaryOpNode *, expr_t, expr_t>>> occbin_constraints_regimes_list %type <vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>>> occbin_constraints_regimes_list
%type <map<string, expr_t>> occbin_constraints_regime_options_list %type <map<string, expr_t>> occbin_constraints_regime_options_list
%type <pair<string, expr_t>> occbin_constraints_regime_option %type <pair<string, expr_t>> occbin_constraints_regime_option
%type <PacTargetKind> pac_target_kind %type <PacTargetKind> pac_target_kind
%type <vector<tuple<string, string, vector<pair<string, string>>>>> symbol_list_with_tex_and_partition %type <vector<tuple<string, string, vector<pair<string, string>>>>> symbol_list_with_tex_and_partition
%type <map<string, variant<bool, string>>> mshocks_options_list %type <variant<int, string>> integer_or_date
%type <pair<string, variant<bool, string>>> mshocks_option %type <map<string, variant<bool, variant<int, string>>>> mshocks_options_list
%type <pair<string, variant<bool, variant<int, string>>>> mshocks_option
%type <pair<vector<expr_t>, vector<expr_t>>> matched_irfs_elem_values_weights %type <pair<vector<expr_t>, vector<expr_t>>> matched_irfs_elem_values_weights
%type <pair<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>> matched_irfs_elem %type <pair<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>> matched_irfs_elem
%type <map<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>> matched_irfs_list %type <map<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>> matched_irfs_list
%type <tuple<string, string, string>> matched_irfs_weights_elem_var_varexo %type <tuple<string, string, string>> matched_irfs_weights_elem_var_varexo
%type <pair<tuple<string, string, string, string, string, string>, expr_t>> matched_irfs_weights_elem %type <pair<tuple<string, string, string, string, string, string>, expr_t>> matched_irfs_weights_elem
%type <map<tuple<string, string, string, string, string, string>, expr_t>> matched_irfs_weights_list %type <map<tuple<string, string, string, string, string, string>, expr_t>> matched_irfs_weights_list
%type <tuple<string, vector<AbstractShocksStatement::period_range_t>, vector<expr_t>, string>> perfect_foresight_controlled_paths_elem
%type <vector<tuple<string, vector<AbstractShocksStatement::period_range_t>, vector<expr_t>, string>>> perfect_foresight_controlled_paths_list
%% %%
%start statement_list; %start statement_list;
...@@ -272,6 +281,7 @@ statement : parameters ...@@ -272,6 +281,7 @@ statement : parameters
| predetermined_variables | predetermined_variables
| model_local_variable | model_local_variable
| change_type | change_type
| heterogeneity_dimension
| model | model
| initval | initval
| initval_file | initval_file
...@@ -377,6 +387,7 @@ statement : parameters ...@@ -377,6 +387,7 @@ statement : parameters
| perfect_foresight_solver | perfect_foresight_solver
| perfect_foresight_with_expectation_errors_setup | perfect_foresight_with_expectation_errors_setup
| perfect_foresight_with_expectation_errors_solver | perfect_foresight_with_expectation_errors_solver
| perfect_foresight_controlled_paths
| prior_function | prior_function
| posterior_function | posterior_function
| method_of_moments | method_of_moments
...@@ -531,9 +542,9 @@ log_trend_var : LOG_TREND_VAR '(' LOG_GROWTH_FACTOR EQUAL { driver.begin_model() ...@@ -531,9 +542,9 @@ log_trend_var : LOG_TREND_VAR '(' LOG_GROWTH_FACTOR EQUAL { driver.begin_model()
; ;
var : VAR symbol_list_with_tex_and_partition ';' var : VAR symbol_list_with_tex_and_partition ';'
{ driver.var($2, false); } { driver.var($2, {}, false); }
| VAR '(' LOG ')' symbol_list_with_tex_and_partition ';' | VAR '(' LOG ')' symbol_list_with_tex_and_partition ';'
{ driver.var($5, true); } { driver.var($5, {}, true); }
| VAR '(' DEFLATOR EQUAL { driver.begin_model(); } hand_side ')' symbol_list_with_tex_and_partition ';' | VAR '(' DEFLATOR EQUAL { driver.begin_model(); } hand_side ')' symbol_list_with_tex_and_partition ';'
{ driver.end_nonstationary_var(false, $6, $8, false); } { driver.end_nonstationary_var(false, $6, $8, false); }
| VAR '(' LOG COMMA DEFLATOR EQUAL { driver.begin_model(); } hand_side ')' symbol_list_with_tex_and_partition ';' | VAR '(' LOG COMMA DEFLATOR EQUAL { driver.begin_model(); } hand_side ')' symbol_list_with_tex_and_partition ';'
...@@ -542,6 +553,8 @@ var : VAR symbol_list_with_tex_and_partition ';' ...@@ -542,6 +553,8 @@ var : VAR symbol_list_with_tex_and_partition ';'
{ driver.end_nonstationary_var(true, $6, $8, false); } { driver.end_nonstationary_var(true, $6, $8, false); }
/* The case LOG + LOG_DEFLATOR is omitted, because it does not make much sense /* The case LOG + LOG_DEFLATOR is omitted, because it does not make much sense
from an economic point of view (amounts to taking the log two times) */ from an economic point of view (amounts to taking the log two times) */
| VAR '(' HETEROGENEITY EQUAL symbol ')' symbol_list_with_tex_and_partition ';'
{ driver.var($7, $5, false); }
; ;
var_remove : VAR_REMOVE symbol_list ';' { driver.var_remove($2); }; var_remove : VAR_REMOVE symbol_list ';' { driver.var_remove($2); };
...@@ -615,7 +628,9 @@ var_expectation_model_option : VARIABLE EQUAL symbol ...@@ -615,7 +628,9 @@ var_expectation_model_option : VARIABLE EQUAL symbol
; ;
varexo : VAREXO symbol_list_with_tex_and_partition ';' varexo : VAREXO symbol_list_with_tex_and_partition ';'
{ driver.varexo($2); } { driver.varexo($2, {}); }
| VAREXO '(' HETEROGENEITY EQUAL symbol ')' symbol_list_with_tex_and_partition ';'
{ driver.varexo($7, $5); }
; ;
varexo_det : VAREXO_DET symbol_list_with_tex_and_partition ';' varexo_det : VAREXO_DET symbol_list_with_tex_and_partition ';'
...@@ -627,7 +642,9 @@ predetermined_variables : PREDETERMINED_VARIABLES symbol_list ';' ...@@ -627,7 +642,9 @@ predetermined_variables : PREDETERMINED_VARIABLES symbol_list ';'
; ;
parameters : PARAMETERS symbol_list_with_tex_and_partition ';' parameters : PARAMETERS symbol_list_with_tex_and_partition ';'
{ driver.parameters($2); } { driver.parameters($2, {}); }
| PARAMETERS '(' HETEROGENEITY EQUAL symbol ')' symbol_list_with_tex_and_partition ';'
{ driver.parameters($7, $5); }
; ;
model_local_variable : MODEL_LOCAL_VARIABLE symbol_list_with_tex ';' model_local_variable : MODEL_LOCAL_VARIABLE symbol_list_with_tex ';'
...@@ -648,6 +665,10 @@ change_type_arg : PARAMETERS ...@@ -648,6 +665,10 @@ change_type_arg : PARAMETERS
{ $$ = SymbolType::exogenousDet; } { $$ = SymbolType::exogenousDet; }
; ;
heterogeneity_dimension : HETEROGENEITY_DIMENSION symbol_list ';'
{ driver.heterogeneity_dimension($2); }
;
init_param : symbol EQUAL expression ';' { driver.init_param($1, $3); }; init_param : symbol EQUAL expression ';' { driver.init_param($1, $3); };
expression : '(' expression ')' expression : '(' expression ')'
...@@ -784,20 +805,24 @@ h_options: o_filename ...@@ -784,20 +805,24 @@ h_options: o_filename
| o_first_obs | o_first_obs
| o_data_first_obs | o_data_first_obs
| o_first_simulation_period | o_first_simulation_period
| o_date_first_simulation_period
| o_last_simulation_period | o_last_simulation_period
| o_date_last_simulation_period
| o_last_obs | o_last_obs
| o_data_last_obs | o_data_last_obs
| o_nobs | o_nobs
| o_series | o_series
; ;
integer_or_date : INT_NUMBER
{ $$.emplace<int>(stoi($1)); }
| date_expr
{ $$.emplace<string>($1); }
;
endval : ENDVAL ';' endval_list END ';' endval : ENDVAL ';' endval_list END ';'
{ driver.end_endval(false); } { driver.end_endval(false); }
| ENDVAL '(' ALL_VALUES_REQUIRED ')' ';' endval_list END ';' | ENDVAL '(' ALL_VALUES_REQUIRED ')' ';' endval_list END ';'
{ driver.end_endval(true); } { driver.end_endval(true); }
| ENDVAL '(' LEARNT_IN EQUAL INT_NUMBER ')' ';' endval_list END ';' | ENDVAL '(' LEARNT_IN EQUAL integer_or_date ')' ';' endval_list END ';'
{ driver.end_endval_learnt_in($5); } { driver.end_endval_learnt_in($5); }
; ;
...@@ -995,6 +1020,8 @@ model : MODEL ';' { driver.begin_model(); } ...@@ -995,6 +1020,8 @@ model : MODEL ';' { driver.begin_model(); }
equation_list END ';' { driver.end_model(); } equation_list END ';' { driver.end_model(); }
| MODEL '(' model_options_list ')' ';' { driver.begin_model(); } | MODEL '(' model_options_list ')' ';' { driver.begin_model(); }
equation_list END ';' { driver.end_model(); } equation_list END ';' { driver.end_model(); }
| MODEL '(' HETEROGENEITY EQUAL symbol ')' { driver.begin_heterogeneous_model($5); }';'
equation_list END ';' { driver.end_model(); }
; ;
equation_list : equation_list equation equation_list : equation_list equation
...@@ -1152,6 +1179,8 @@ hand_side : '(' hand_side ')' ...@@ -1152,6 +1179,8 @@ hand_side : '(' hand_side ')'
{ $$ = driver.add_erfc($3); } { $$ = driver.add_erfc($3); }
| STEADY_STATE '(' hand_side ')' | STEADY_STATE '(' hand_side ')'
{ $$ = driver.add_steady_state($3); } { $$ = driver.add_steady_state($3); }
| SUM '(' hand_side ')'
{ $$ = driver.add_sum($3); }
; ;
comma_hand_side : hand_side comma_hand_side : hand_side
...@@ -1202,9 +1231,15 @@ shocks : SHOCKS ';' shock_list END ';' { driver.end_shocks(false); } ...@@ -1202,9 +1231,15 @@ shocks : SHOCKS ';' shock_list END ';' { driver.end_shocks(false); }
| SHOCKS '(' SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(false); } | SHOCKS '(' SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(false); }
| SHOCKS '(' SURPRISE COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); } | SHOCKS '(' SURPRISE COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); }
| SHOCKS '(' OVERWRITE COMMA SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); } | SHOCKS '(' OVERWRITE COMMA SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); }
| SHOCKS '(' LEARNT_IN EQUAL INT_NUMBER ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, false); } | SHOCKS '(' LEARNT_IN EQUAL integer_or_date ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, false); }
| SHOCKS '(' LEARNT_IN EQUAL INT_NUMBER COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, true); } | SHOCKS '(' LEARNT_IN EQUAL integer_or_date COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, true); }
| SHOCKS '(' OVERWRITE COMMA LEARNT_IN EQUAL INT_NUMBER ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($7, true); } | SHOCKS '(' OVERWRITE COMMA LEARNT_IN EQUAL integer_or_date ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($7, true); }
| SHOCKS '(' HETEROGENEITY EQUAL symbol ')' ';' stoch_shock_list END ';'
{ driver.end_heterogeneous_shocks($5, false); }
| SHOCKS '(' HETEROGENEITY EQUAL symbol COMMA OVERWRITE ')' ';' stoch_shock_list END ';'
{ driver.end_heterogeneous_shocks($5, true); }
| SHOCKS '(' OVERWRITE COMMA HETEROGENEITY EQUAL symbol ')' ';' stoch_shock_list END ';'
{ driver.end_heterogeneous_shocks($7, true); }
; ;
shock_list : shock_list shock_elem shock_list : shock_list shock_elem
...@@ -1212,16 +1247,23 @@ shock_list : shock_list shock_elem ...@@ -1212,16 +1247,23 @@ shock_list : shock_list shock_elem
; ;
shock_elem : det_shock_elem shock_elem : det_shock_elem
| VAR symbol ';' STDERR expression ';' | stoch_shock_elem
{ driver.add_stderr_shock($2, $5); }
| VAR symbol EQUAL expression ';'
{ driver.add_var_shock($2, $4); }
| VAR symbol COMMA symbol EQUAL expression ';'
{ driver.add_covar_shock($2, $4, $6); }
| CORR symbol COMMA symbol EQUAL expression ';'
{ driver.add_correl_shock($2, $4, $6); }
; ;
stoch_shock_elem : VAR symbol ';' STDERR expression ';'
{ driver.add_stderr_shock($2, $5); }
| VAR symbol EQUAL expression ';'
{ driver.add_var_shock($2, $4); }
| VAR symbol COMMA symbol EQUAL expression ';'
{ driver.add_covar_shock($2, $4, $6); }
| CORR symbol COMMA symbol EQUAL expression ';'
{ driver.add_correl_shock($2, $4, $6); }
;
stoch_shock_list : stoch_shock_list stoch_shock_elem
| stoch_shock_elem
;
det_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';' det_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';'
{ driver.add_det_shock($2, $5, $8, ParsingDriver::DetShockType::standard); } { driver.add_det_shock($2, $5, $8, ParsingDriver::DetShockType::standard); }
| VAR symbol ';' PERIODS period_list ';' ADD value_list ';' | VAR symbol ';' PERIODS period_list ';' ADD value_list ';'
...@@ -1337,11 +1379,11 @@ mshocks : MSHOCKS ';' mshock_list END ';' ...@@ -1337,11 +1379,11 @@ mshocks : MSHOCKS ';' mshock_list END ';'
{ driver.end_mshocks(false, false); } { driver.end_mshocks(false, false); }
| MSHOCKS '(' mshocks_options_list ')' ';' mshock_list END ';' | MSHOCKS '(' mshocks_options_list ')' ';' mshock_list END ';'
{ {
/* NB: the following relies of the fact that bool is the first /* NB: the following relies on the fact that bool is the first
alternative in the variant, so that default initialization of the alternative in the variant, so that default initialization of the
variant by the [] operator will give false */ variant by the [] operator will give false */
if ($3.contains("learnt_in")) if ($3.contains("learnt_in"))
driver.end_mshocks_learnt_in(get<string>($3.at("learnt_in")), driver.end_mshocks_learnt_in(get<variant<int, string>>($3.at("learnt_in")),
get<bool>($3["overwrite"]), get<bool>($3["overwrite"]),
get<bool>($3["relative_to_initval"])); get<bool>($3["relative_to_initval"]));
else else
...@@ -1362,7 +1404,7 @@ mshocks_options_list : mshocks_option ...@@ -1362,7 +1404,7 @@ mshocks_options_list : mshocks_option
mshocks_option : OVERWRITE mshocks_option : OVERWRITE
{ $$ = {"overwrite", true}; } { $$ = {"overwrite", true}; }
| LEARNT_IN EQUAL INT_NUMBER | LEARNT_IN EQUAL integer_or_date
{ $$ = {"learnt_in", $3}; } { $$ = {"learnt_in", $3}; }
| RELATIVE_TO_INITVAL | RELATIVE_TO_INITVAL
{ $$ = {"relative_to_initval", true}; } { $$ = {"relative_to_initval", true}; }
...@@ -1372,48 +1414,38 @@ mshock_list : mshock_list det_shock_elem ...@@ -1372,48 +1414,38 @@ mshock_list : mshock_list det_shock_elem
| det_shock_elem | det_shock_elem
; ;
period_list : period_list COMMA INT_NUMBER period_list : period_range
{ { $$ = { $1 }; }
$$ = $1; | period_list period_range
int p = stoi($3);
$$.emplace_back(p, p);
}
| period_list INT_NUMBER
{
$$ = $1;
int p = stoi($2);
$$.emplace_back(p, p);
}
| period_list COMMA INT_NUMBER ':' INT_NUMBER
{ {
$$ = $1; $$ = $1;
int p1 = stoi($3), p2 = stoi($5); $$.emplace_back($2);
if (p1 > p2)
driver.error("Can't have first period index greater than second index in range specification");
$$.emplace_back(p1, p2);
} }
| period_list INT_NUMBER ':' INT_NUMBER | period_list COMMA period_range
{ {
$$ = $1; $$ = $1;
int p1 = stoi($2), p2 = stoi($4); $$.emplace_back($3);
if (p1 > p2)
driver.error("Can't have first period index greater than second index in range specification");
$$.emplace_back(p1, p2);
}
| INT_NUMBER ':' INT_NUMBER
{
int p1 = stoi($1), p2 = stoi($3);
if (p1 > p2)
driver.error("Can't have first period index greater than second index in range specification");
$$ = {{p1, p2}};
}
| INT_NUMBER
{
int p = stoi($1);
$$ = {{p, p}};
} }
; ;
period_range : INT_NUMBER
{
int p = stoi($1);
$$.emplace<pair<int, int>>(p, p);
}
| INT_NUMBER ':' INT_NUMBER
{
int p1 = stoi($1), p2 = stoi($3);
if (p1 > p2)
driver.error("Can't have first period index greater than second index in range specification");
$$.emplace<pair<int, int>>(p1, p2);
}
| date_expr
{ $$.emplace<pair<string, string>>($1, $1); }
| date_expr ':' date_expr
{ $$.emplace<pair<string, string>>($1, $3); }
;
value_list : value_list COMMA '(' expression ')' value_list : value_list COMMA '(' expression ')'
{ {
$$ = $1; $$ = $1;
...@@ -1465,9 +1497,11 @@ steady_options : o_solve_algo ...@@ -1465,9 +1497,11 @@ steady_options : o_solve_algo
| o_markowitz | o_markowitz
| o_steady_maxit | o_steady_maxit
| o_nocheck | o_nocheck
| o_noprint
| o_steady_tolf | o_steady_tolf
| o_steady_tolx | o_steady_tolx
| o_fsolve_options | o_fsolve_options
| o_non_zero
; ;
check : CHECK ';' check : CHECK ';'
...@@ -1512,6 +1546,8 @@ perfect_foresight_setup_options_list : perfect_foresight_setup_options_list COMM ...@@ -1512,6 +1546,8 @@ perfect_foresight_setup_options_list : perfect_foresight_setup_options_list COMM
perfect_foresight_setup_options : o_periods perfect_foresight_setup_options : o_periods
| o_datafile | o_datafile
| o_endval_steady | o_endval_steady
| o_pf_first_simulation_period
| o_pf_last_simulation_period
; ;
perfect_foresight_solver : PERFECT_FORESIGHT_SOLVER ';' perfect_foresight_solver : PERFECT_FORESIGHT_SOLVER ';'
...@@ -1564,6 +1600,8 @@ perfect_foresight_with_expectation_errors_setup_options_list : perfect_foresight ...@@ -1564,6 +1600,8 @@ perfect_foresight_with_expectation_errors_setup_options_list : perfect_foresight
perfect_foresight_with_expectation_errors_setup_options : o_periods perfect_foresight_with_expectation_errors_setup_options : o_periods
| o_datafile | o_datafile
| o_pf_first_simulation_period
| o_pf_last_simulation_period
; ;
perfect_foresight_with_expectation_errors_solver : PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SOLVER ';' perfect_foresight_with_expectation_errors_solver : PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SOLVER ';'
...@@ -1580,6 +1618,31 @@ perfect_foresight_with_expectation_errors_solver_options : o_pfwee_constant_simu ...@@ -1580,6 +1618,31 @@ perfect_foresight_with_expectation_errors_solver_options : o_pfwee_constant_simu
| perfect_foresight_solver_options | perfect_foresight_solver_options
; ;
perfect_foresight_controlled_paths : PERFECT_FORESIGHT_CONTROLLED_PATHS ';' perfect_foresight_controlled_paths_list END ';'
{ driver.perfect_foresight_controlled_paths($3, 1); }
| PERFECT_FORESIGHT_CONTROLLED_PATHS '(' LEARNT_IN EQUAL integer_or_date ')' ';' perfect_foresight_controlled_paths_list END ';'
{ driver.perfect_foresight_controlled_paths($8, $5); }
;
perfect_foresight_controlled_paths_list : perfect_foresight_controlled_paths_list perfect_foresight_controlled_paths_elem
{
$$ = $1;
$$.push_back($2);
}
| perfect_foresight_controlled_paths_elem
{ $$ = { $1 }; }
;
perfect_foresight_controlled_paths_elem : EXOGENIZE symbol ';' PERIODS period_list ';' VALUES value_list ';' ENDOGENIZE symbol ';'
{
driver.check_symbol_is_endogenous($2);
driver.check_symbol_is_exogenous($11, false);
if ($5.size() != $8.size())
driver.error("The number of periods is different from the number of values");
$$ = { $2, $5, $8, $11};
}
;
method_of_moments : METHOD_OF_MOMENTS ';' method_of_moments : METHOD_OF_MOMENTS ';'
{ driver.method_of_moments(); } { driver.method_of_moments(); }
| METHOD_OF_MOMENTS '(' method_of_moments_options_list ')' ';' | METHOD_OF_MOMENTS '(' method_of_moments_options_list ')' ';'
...@@ -2063,9 +2126,8 @@ prior_pdf : BETA_PDF ...@@ -2063,9 +2126,8 @@ prior_pdf : BETA_PDF
{ $$ = PriorDistributions::weibull; } { $$ = PriorDistributions::weibull; }
; ;
date_str : DATES date_expr : DATE
{ $$ = "dates('" + $1 + "')"; }
date_expr : date_str
| date_expr PLUS INT_NUMBER | date_expr PLUS INT_NUMBER
{ $$ = $1 + '+' + $3; } { $$ = $1 + '+' + $3; }
; ;
...@@ -3465,7 +3527,8 @@ extended_path_option : o_periods ...@@ -3465,7 +3527,8 @@ extended_path_option : o_periods
| o_solver_periods | o_solver_periods
| o_extended_path_order | o_extended_path_order
| o_hybrid | o_hybrid
| o_lmmcp | o_use_first_order_solution
| o_lmmcp
; ;
model_diagnostics : MODEL_DIAGNOSTICS ';' model_diagnostics : MODEL_DIAGNOSTICS ';'
...@@ -3593,7 +3656,15 @@ matched_irfs_elem : matched_irfs_elem_var_varexo ...@@ -3593,7 +3656,15 @@ matched_irfs_elem : matched_irfs_elem_var_varexo
vector<tuple<int, int, expr_t, expr_t>> v; vector<tuple<int, int, expr_t, expr_t>> v;
v.reserve($3.size()); v.reserve($3.size());
for (size_t i {0}; i < $3.size(); i++) for (size_t i {0}; i < $3.size(); i++)
v.emplace_back($3[i].first, $3[i].second, $5.first[i], $5.second[i]); try
{
auto [p1, p2] = get<pair<int, int>>($3[i]);
v.emplace_back(p1, p2, $5.first[i], $5.second[i]);
}
catch (bad_variant_access&)
{
driver.error("matched_irfs: dates are not allowed in the 'periods' keyword");
}
$$ = {$1, v}; $$ = {$1, v};
} }
; ;
...@@ -3692,6 +3763,7 @@ o_periods : PERIODS EQUAL INT_NUMBER { driver.option_num("periods", $3); }; ...@@ -3692,6 +3763,7 @@ o_periods : PERIODS EQUAL INT_NUMBER { driver.option_num("periods", $3); };
o_solver_periods : SOLVER_PERIODS EQUAL INT_NUMBER { driver.option_num("ep.periods", $3); }; o_solver_periods : SOLVER_PERIODS EQUAL INT_NUMBER { driver.option_num("ep.periods", $3); };
o_extended_path_order : ORDER EQUAL INT_NUMBER { driver.option_num("ep.stochastic.order", $3); }; o_extended_path_order : ORDER EQUAL INT_NUMBER { driver.option_num("ep.stochastic.order", $3); };
o_hybrid : HYBRID { driver.option_num("ep.stochastic.hybrid_order", "2"); }; o_hybrid : HYBRID { driver.option_num("ep.stochastic.hybrid_order", "2"); };
o_use_first_order_solution : USE_FIRST_ORDER_SOLUTION { driver.option_num("ep.use_first_order_solution_as_initial_guess", "true"); };
o_steady_maxit : MAXIT EQUAL INT_NUMBER { driver.option_num("steady.maxit", $3); }; o_steady_maxit : MAXIT EQUAL INT_NUMBER { driver.option_num("steady.maxit", $3); };
o_simul_maxit : MAXIT EQUAL INT_NUMBER { driver.option_num("simul.maxit", $3); }; o_simul_maxit : MAXIT EQUAL INT_NUMBER { driver.option_num("simul.maxit", $3); };
o_bandpass_filter : BANDPASS_FILTER { driver.option_num("bandpass.indicator", "true"); } o_bandpass_filter : BANDPASS_FILTER { driver.option_num("bandpass.indicator", "true"); }
...@@ -3760,13 +3832,17 @@ o_est_first_obs : FIRST_OBS EQUAL vec_int ...@@ -3760,13 +3832,17 @@ o_est_first_obs : FIRST_OBS EQUAL vec_int
o_posterior_sampling_method : POSTERIOR_SAMPLING_METHOD EQUAL QUOTED_STRING o_posterior_sampling_method : POSTERIOR_SAMPLING_METHOD EQUAL QUOTED_STRING
{ driver.option_str("posterior_sampler_options.posterior_sampling_method", $3); } ; { driver.option_str("posterior_sampler_options.posterior_sampling_method", $3); } ;
o_first_obs : FIRST_OBS EQUAL INT_NUMBER { driver.option_num("first_obs", $3); }; o_first_obs : FIRST_OBS EQUAL INT_NUMBER { driver.option_num("first_obs", $3); };
o_data_first_obs : FIRST_OBS EQUAL date_expr { driver.option_date("firstobs", $3); } ; o_data_first_obs : FIRST_OBS EQUAL date_expr { driver.option_date("first_obs", $3); } ;
o_first_simulation_period : FIRST_SIMULATION_PERIOD EQUAL INT_NUMBER { driver.option_num("first_simulation_period", $3); }; o_first_simulation_period : FIRST_SIMULATION_PERIOD EQUAL INT_NUMBER { driver.option_num("first_simulation_period", $3); }
o_date_first_simulation_period : FIRST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("firstsimulationperiod", $3); } ; | FIRST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("first_simulation_period", $3); }
o_last_simulation_period : LAST_SIMULATION_PERIOD EQUAL INT_NUMBER { driver.option_num("last_simulation_period", $3); }; ;
o_date_last_simulation_period : LAST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("lastsimulationperiod", $3); } ; o_last_simulation_period : LAST_SIMULATION_PERIOD EQUAL INT_NUMBER { driver.option_num("last_simulation_period", $3); }
| LAST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("last_simulation_period", $3); }
;
o_pf_first_simulation_period : FIRST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("simul.first_simulation_period", $3); };
o_pf_last_simulation_period : LAST_SIMULATION_PERIOD EQUAL date_expr { driver.option_date("simul.last_simulation_period", $3); };
o_last_obs : LAST_OBS EQUAL INT_NUMBER { driver.option_num("last_obs", $3); }; o_last_obs : LAST_OBS EQUAL INT_NUMBER { driver.option_num("last_obs", $3); };
o_data_last_obs : LAST_OBS EQUAL date_expr { driver.option_date("lastobs", $3); } ; o_data_last_obs : LAST_OBS EQUAL date_expr { driver.option_date("last_obs", $3); } ;
o_keep_kalman_algo_if_singularity_is_detected : KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED { driver.option_num("kalman.keep_kalman_algo_if_singularity_is_detected", "true"); } ; o_keep_kalman_algo_if_singularity_is_detected : KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED { driver.option_num("kalman.keep_kalman_algo_if_singularity_is_detected", "true"); } ;
o_data_nobs : NOBS EQUAL INT_NUMBER { driver.option_num("nobs", $3); }; o_data_nobs : NOBS EQUAL INT_NUMBER { driver.option_num("nobs", $3); };
o_shift : SHIFT EQUAL signed_number { driver.option_num("shift", $3); }; o_shift : SHIFT EQUAL signed_number { driver.option_num("shift", $3); };
...@@ -4005,11 +4081,12 @@ o_resampling : RESAMPLING EQUAL SYSTEMATIC ...@@ -4005,11 +4081,12 @@ o_resampling : RESAMPLING EQUAL SYSTEMATIC
| RESAMPLING EQUAL NONE { driver.option_num("particle.resampling.status.systematic", "false"); driver.option_num("particle.resampling.status.none", "true"); } | RESAMPLING EQUAL NONE { driver.option_num("particle.resampling.status.systematic", "false"); driver.option_num("particle.resampling.status.none", "true"); }
| RESAMPLING EQUAL GENERIC { driver.option_num("particle.resampling.status.systematic", "false"); driver.option_num("particle.resampling.status.generic", "true"); }; | RESAMPLING EQUAL GENERIC { driver.option_num("particle.resampling.status.systematic", "false"); driver.option_num("particle.resampling.status.generic", "true"); };
o_resampling_threshold : RESAMPLING_THRESHOLD EQUAL non_negative_number { driver.option_num("particle.resampling.threshold", $3); }; o_resampling_threshold : RESAMPLING_THRESHOLD EQUAL non_negative_number { driver.option_num("particle.resampling.threshold", $3); };
o_resampling_method : RESAMPLING_METHOD EQUAL KITAGAWA { driver.option_num("particle.resampling.method.kitagawa", "true"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.smethod.stratified", "false"); } o_resampling_method : RESAMPLING_METHOD EQUAL KITAGAWA { driver.option_num("particle.resampling.method.kitagawa", "true"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.method.stratified", "false"); driver.option_num("particle.resampling.method.residual", "false");}
| RESAMPLING_METHOD EQUAL SMOOTH { driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "true"); driver.option_num("particle.resampling.smethod.stratified", "false"); } | RESAMPLING_METHOD EQUAL SMOOTH { driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "true"); driver.option_num("particle.resampling.method.stratified", "false"); driver.option_num("particle.resampling.method.residual", "false"); }
| RESAMPLING_METHOD EQUAL STRATIFIED { driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.method.stratified", "true"); }; | RESAMPLING_METHOD EQUAL STRATIFIED { driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.method.stratified", "true"); driver.option_num("particle.resampling.method.residual", "false"); };
| RESAMPLING_METHOD EQUAL RESIDUAL { driver.option_num("particle.resampling.method.kitagawa", "false"); driver.option_num("particle.resampling.method.smooth", "false"); driver.option_num("particle.resampling.method.stratified", "false"); driver.option_num("particle.resampling.method.residual", "true"); };
o_cpf_weights : CPF_WEIGHTS EQUAL AMISANOTRISTANI { driver.option_num("particle.cpf_weights_method.amisanotristani", "true"); driver.option_num("particle.cpf_weights_method.murrayjonesparslow", "false"); } o_cpf_weights : CPF_WEIGHTS EQUAL AMISANOTRISTANI { driver.option_num("particle.cpf_weights_method.amisanotristani", "true"); driver.option_num("particle.cpf_weights_method.murrayjonesparslow", "false"); }
| CPF_WEIGHTS EQUAL MURRAYJONESPARSLOW { driver.option_num("particle.cpf_weights_method.amisanotristani", "false"); driver.option_num("particle.cpf_weights_method.murrayjonesparslow", "true"); }; | CPF_WEIGHTS EQUAL MURRAYJONESPARSLOW { driver.option_num("particle.cpf_weights_method.amisanotristani", "false"); driver.option_num("particle.cpf_weights_method.murrayjonesparslow", "true"); };
o_filter_algorithm : FILTER_ALGORITHM EQUAL symbol { driver.option_str("particle.filter_algorithm", $3); }; o_filter_algorithm : FILTER_ALGORITHM EQUAL symbol { driver.option_str("particle.filter_algorithm", $3); };
o_nonlinear_filter_initialization : NONLINEAR_FILTER_INITIALIZATION EQUAL INT_NUMBER { driver.option_num("particle.initialization", $3); }; o_nonlinear_filter_initialization : NONLINEAR_FILTER_INITIALIZATION EQUAL INT_NUMBER { driver.option_num("particle.initialization", $3); };
o_proposal_approximation : PROPOSAL_APPROXIMATION EQUAL CUBATURE { driver.option_num("particle.proposal_approximation.cubature", "true"); driver.option_num("particle.proposal_approximation.unscented", "false"); driver.option_num("particle.proposal_approximation.montecarlo", "false"); } o_proposal_approximation : PROPOSAL_APPROXIMATION EQUAL CUBATURE { driver.option_num("particle.proposal_approximation.cubature", "true"); driver.option_num("particle.proposal_approximation.unscented", "false"); driver.option_num("particle.proposal_approximation.montecarlo", "false"); }
...@@ -4278,10 +4355,11 @@ o_analytic_derivation_mode : ANALYTIC_DERIVATION_MODE EQUAL signed_number { driv ...@@ -4278,10 +4355,11 @@ o_analytic_derivation_mode : ANALYTIC_DERIVATION_MODE EQUAL signed_number { driv
o_endogenous_prior : ENDOGENOUS_PRIOR { driver.option_num("endogenous_prior", "true"); } o_endogenous_prior : ENDOGENOUS_PRIOR { driver.option_num("endogenous_prior", "true"); }
o_use_univariate_filters_if_singularity_is_detected : USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED EQUAL INT_NUMBER { driver.option_num("use_univariate_filters_if_singularity_is_detected", $3); } o_use_univariate_filters_if_singularity_is_detected : USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED EQUAL INT_NUMBER { driver.option_num("use_univariate_filters_if_singularity_is_detected", $3); }
o_mcmc_jumping_covariance : MCMC_JUMPING_COVARIANCE EQUAL HESSIAN o_mcmc_jumping_covariance : MCMC_JUMPING_COVARIANCE EQUAL HESSIAN
{ driver.option_str("MCMC_jumping_covariance", $3); } | MCMC_JUMPING_COVARIANCE EQUAL PRIOR_VARIANCE { driver.option_str("MCMC_jumping_covariance", "hessian"); }
{ driver.option_str("MCMC_jumping_covariance", $3); } | MCMC_JUMPING_COVARIANCE EQUAL PRIOR_VARIANCE
{ driver.option_str("MCMC_jumping_covariance", "prior_variance"); }
| MCMC_JUMPING_COVARIANCE EQUAL IDENTITY_MATRIX | MCMC_JUMPING_COVARIANCE EQUAL IDENTITY_MATRIX
{ driver.option_str("MCMC_jumping_covariance", $3); } { driver.option_str("MCMC_jumping_covariance", "identity_matrix"); }
| MCMC_JUMPING_COVARIANCE EQUAL filename | MCMC_JUMPING_COVARIANCE EQUAL filename
{ driver.option_str("MCMC_jumping_covariance", $3); } { driver.option_str("MCMC_jumping_covariance", $3); }
; ;
...@@ -4352,7 +4430,7 @@ o_emas_girf : EMAS_GIRF { driver.option_num("irf_opt.ergodic_mean_irf", "true"); ...@@ -4352,7 +4430,7 @@ o_emas_girf : EMAS_GIRF { driver.option_num("irf_opt.ergodic_mean_irf", "true");
o_emas_drop : EMAS_DROP EQUAL INT_NUMBER { driver.option_num("irf_opt.EM.drop", $3); }; o_emas_drop : EMAS_DROP EQUAL INT_NUMBER { driver.option_num("irf_opt.EM.drop", $3); };
o_emas_tolf : EMAS_TOLF EQUAL non_negative_number { driver.option_num("irf_opt.EM.tolf", $3); }; o_emas_tolf : EMAS_TOLF EQUAL non_negative_number { driver.option_num("irf_opt.EM.tolf", $3); };
o_emas_max_iter : EMAS_MAX_ITER EQUAL INT_NUMBER { driver.option_num("irf_opt.EM.iter", $3); }; o_emas_max_iter : EMAS_MAX_ITER EQUAL INT_NUMBER { driver.option_num("irf_opt.EM.iter", $3); };
o_non_zero : NON_ZERO { driver.option_num("non_zero", "true"); }; o_non_zero : NON_ZERO { driver.option_num("steady.non_zero", "true"); };
// Some options to "identification" // Some options to "identification"
o_no_identification_strength : NO_IDENTIFICATION_STRENGTH { driver.option_num("no_identification_strength", "true"); }; o_no_identification_strength : NO_IDENTIFICATION_STRENGTH { driver.option_num("no_identification_strength", "true"); };
...@@ -4442,9 +4520,8 @@ vec_int_number : INT_NUMBER ...@@ -4442,9 +4520,8 @@ vec_int_number : INT_NUMBER
vec_int_elem : vec_int_number vec_int_elem : vec_int_number
| INT_NUMBER ':' INT_NUMBER | INT_NUMBER ':' INT_NUMBER
{ {
$$ = {}; auto v = views::iota(stoi($1), stoi($3) + 1);
for (int i = stoi($1); i <= stoi($3); i++) $$ = {v.begin(), v.end()};
$$.push_back(i);
} }
; ;
...@@ -4572,6 +4649,7 @@ symbol : NAME ...@@ -4572,6 +4649,7 @@ symbol : NAME
| ADD | ADD
| MULTIPLY | MULTIPLY
| MFS | MFS
| RESIDUAL
; ;
%% %%
......
/* -*- C++ -*- */ /* -*- C++ -*- */
/* /*
* Copyright © 2003-2024 Dynare Team * Copyright © 2003-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
%{ %{
#include <cstring>
#include "ParsingDriver.hh" #include "ParsingDriver.hh"
using namespace std; using namespace std;
...@@ -60,7 +59,6 @@ string eofbuff; ...@@ -60,7 +59,6 @@ string eofbuff;
%x VERBATIM_BLOCK %x VERBATIM_BLOCK
%x NATIVE %x NATIVE
%x NATIVE_COMMENT %x NATIVE_COMMENT
%x DATES_STATEMENT
%x LINE1 %x LINE1
%x LINE2 %x LINE2
%x LINE3 %x LINE3
...@@ -70,7 +68,9 @@ string eofbuff; ...@@ -70,7 +68,9 @@ string eofbuff;
#define YY_USER_ACTION location_increment(yylloc, yytext); #define YY_USER_ACTION location_increment(yylloc, yytext);
%} %}
DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) NAME [a-z_][a-z0-9_]*
FLOAT_NUMBER ((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+[ed][-+]?[0-9]+)
DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|[sh][12])
%% %%
/* Code put at the beginning of yylex() */ /* Code put at the beginning of yylex() */
...@@ -92,12 +92,12 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -92,12 +92,12 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
} }
/* spaces, tabs and carriage returns are ignored */ /* spaces, tabs and carriage returns are ignored */
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,DATES_STATEMENT,LINE1,LINE2,LINE3>[[:space:]]+ { yylloc->step(); } <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,LINE1,LINE2,LINE3>[[:space:]]+ { yylloc->step(); }
/* Comments */ /* Comments */
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>%.* <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>%.*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>"//".* <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>"//".*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>"/*" {comment_caller = YY_START; BEGIN COMMENT;} <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>"/*" {comment_caller = YY_START; BEGIN COMMENT;}
<COMMENT>"*/" {BEGIN comment_caller;} <COMMENT>"*/" {BEGIN comment_caller;}
<COMMENT>. <COMMENT>.
...@@ -111,6 +111,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -111,6 +111,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<INITIAL>predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;} <INITIAL>predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;}
<INITIAL>parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;} <INITIAL>parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;}
<INITIAL>model_local_variable {BEGIN DYNARE_STATEMENT; return token::MODEL_LOCAL_VARIABLE;} <INITIAL>model_local_variable {BEGIN DYNARE_STATEMENT; return token::MODEL_LOCAL_VARIABLE;}
<INITIAL>heterogeneity_dimension {BEGIN DYNARE_STATEMENT; return token::HETEROGENEITY_DIMENSION;}
<INITIAL>model_info {BEGIN DYNARE_STATEMENT; return token::MODEL_INFO;} <INITIAL>model_info {BEGIN DYNARE_STATEMENT; return token::MODEL_INFO;}
<INITIAL>estimation {BEGIN DYNARE_STATEMENT; return token::ESTIMATION;} <INITIAL>estimation {BEGIN DYNARE_STATEMENT; return token::ESTIMATION;}
<INITIAL>set_time {BEGIN DYNARE_STATEMENT; return token::SET_TIME;} <INITIAL>set_time {BEGIN DYNARE_STATEMENT; return token::SET_TIME;}
...@@ -235,6 +236,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -235,6 +236,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<INITIAL>pac_target_info {BEGIN DYNARE_BLOCK; return token::PAC_TARGET_INFO;} <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 {BEGIN DYNARE_BLOCK; return token::MATCHED_IRFS;}
<INITIAL>matched_irfs_weights {BEGIN DYNARE_BLOCK; return token::MATCHED_IRFS_WEIGHTS;} <INITIAL>matched_irfs_weights {BEGIN DYNARE_BLOCK; return token::MATCHED_IRFS_WEIGHTS;}
<INITIAL>perfect_foresight_controlled_paths {BEGIN DYNARE_BLOCK; return token::PERFECT_FORESIGHT_CONTROLLED_PATHS;}
/* For the semicolon after an "end" keyword */ /* For the semicolon after an "end" keyword */
<INITIAL>; {return Dynare::parser::token_type (yytext[0]);} <INITIAL>; {return Dynare::parser::token_type (yytext[0]);}
...@@ -245,7 +247,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -245,7 +247,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>subsamples {return token::SUBSAMPLES;} <DYNARE_STATEMENT>subsamples {return token::SUBSAMPLES;}
<DYNARE_STATEMENT>options {return token::OPTIONS;} <DYNARE_STATEMENT>options {return token::OPTIONS;}
<DYNARE_STATEMENT>prior { <DYNARE_STATEMENT>prior {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::PRIOR; return token::PRIOR;
} }
<INITIAL>std {BEGIN DYNARE_STATEMENT; return token::STD;} <INITIAL>std {BEGIN DYNARE_STATEMENT; return token::STD;}
...@@ -255,31 +257,12 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -255,31 +257,12 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<INITIAL>prior_function {BEGIN DYNARE_STATEMENT; return token::PRIOR_FUNCTION;} <INITIAL>prior_function {BEGIN DYNARE_STATEMENT; return token::PRIOR_FUNCTION;}
<INITIAL>posterior_function {BEGIN DYNARE_STATEMENT; return token::POSTERIOR_FUNCTION;} <INITIAL>posterior_function {BEGIN DYNARE_STATEMENT; return token::POSTERIOR_FUNCTION;}
/* Inside of a Dynare statement */ <DYNARE_STATEMENT,DYNARE_BLOCK>{DATE} {
<DYNARE_STATEMENT>{DATE} { yylval->emplace<string>(yytext);
char* yycopy = strdup(yytext); return token::DATE;
char* uput = yycopy + yyleng; }
unput(')');
unput('\''); /* Inside a Dynare statement */
while (uput > yycopy)
unput(*--uput);
unput('\'');
unput('(');
unput('s');
unput('e');
unput('t');
unput('a');
unput('d');
free( yycopy );
}
<DYNARE_STATEMENT>${DATE} { yylloc->step();
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6)
yyout << yytext + 1;
#else
*yyout << yytext + 1;
#endif
}
<DYNARE_STATEMENT>dates {dates_parens_nb=0; BEGIN DATES_STATEMENT; yylval->build<string>("dates");}
<DYNARE_STATEMENT>file {return token::FILE;} <DYNARE_STATEMENT>file {return token::FILE;}
<DYNARE_STATEMENT>datafile {return token::DATAFILE;} <DYNARE_STATEMENT>datafile {return token::DATAFILE;}
<DYNARE_STATEMENT>dirname {return token::DIRNAME;} <DYNARE_STATEMENT>dirname {return token::DIRNAME;}
...@@ -312,10 +295,10 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -312,10 +295,10 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>posterior_nograph {return token::POSTERIOR_NOGRAPH;} <DYNARE_STATEMENT>posterior_nograph {return token::POSTERIOR_NOGRAPH;}
<DYNARE_STATEMENT>nodisplay {return token::NODISPLAY;} <DYNARE_STATEMENT>nodisplay {return token::NODISPLAY;}
<DYNARE_STATEMENT>graph_format {return token::GRAPH_FORMAT;} <DYNARE_STATEMENT>graph_format {return token::GRAPH_FORMAT;}
<DYNARE_STATEMENT>eps {yylval->build<string>(yytext); return token::EPS;} <DYNARE_STATEMENT>eps {yylval->emplace<string>(yytext); return token::EPS;}
<DYNARE_STATEMENT>pdf {yylval->build<string>(yytext); return token::PDF;} <DYNARE_STATEMENT>pdf {yylval->emplace<string>(yytext); return token::PDF;}
<DYNARE_STATEMENT>fig {yylval->build<string>(yytext); return token::FIG;} <DYNARE_STATEMENT>fig {yylval->emplace<string>(yytext); return token::FIG;}
<DYNARE_STATEMENT>none {yylval->build<string>(yytext); return token::NONE;} <DYNARE_STATEMENT>none {yylval->emplace<string>(yytext); return token::NONE;}
<DYNARE_STATEMENT>print {return token::PRINT;} <DYNARE_STATEMENT>print {return token::PRINT;}
<DYNARE_STATEMENT>noprint {return token::NOPRINT;} <DYNARE_STATEMENT>noprint {return token::NOPRINT;}
<DYNARE_STATEMENT>conf_sig {return token::CONF_SIG;} <DYNARE_STATEMENT>conf_sig {return token::CONF_SIG;}
...@@ -423,6 +406,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -423,6 +406,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>logarithmic_reduction {return token::LOGARITHMIC_REDUCTION;} <DYNARE_STATEMENT>logarithmic_reduction {return token::LOGARITHMIC_REDUCTION;}
<DYNARE_STATEMENT>use_univariate_filters_if_singularity_is_detected {return token::USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED;} <DYNARE_STATEMENT>use_univariate_filters_if_singularity_is_detected {return token::USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED;}
<DYNARE_STATEMENT>hybrid {return token::HYBRID;} <DYNARE_STATEMENT>hybrid {return token::HYBRID;}
<DYNARE_STATEMENT>use_first_order_solution {return token::USE_FIRST_ORDER_SOLUTION;}
<DYNARE_STATEMENT>default {return token::DEFAULT;} <DYNARE_STATEMENT>default {return token::DEFAULT;}
<DYNARE_STATEMENT>init2shocks {return token::INIT2SHOCKS;} <DYNARE_STATEMENT>init2shocks {return token::INIT2SHOCKS;}
...@@ -435,6 +419,10 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -435,6 +419,10 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>kitagawa {return token::KITAGAWA;} <DYNARE_STATEMENT>kitagawa {return token::KITAGAWA;}
<DYNARE_STATEMENT>smooth {return token::SMOOTH;} <DYNARE_STATEMENT>smooth {return token::SMOOTH;}
<DYNARE_STATEMENT>stratified {return token::STRATIFIED;} <DYNARE_STATEMENT>stratified {return token::STRATIFIED;}
<DYNARE_STATEMENT>residual {
yylval->emplace<string>(yytext);
return token::RESIDUAL;
}
<DYNARE_STATEMENT>cpf_weights {return token::CPF_WEIGHTS;} <DYNARE_STATEMENT>cpf_weights {return token::CPF_WEIGHTS;}
<DYNARE_STATEMENT>amisanotristani {return token::AMISANOTRISTANI;} <DYNARE_STATEMENT>amisanotristani {return token::AMISANOTRISTANI;}
<DYNARE_STATEMENT>murrayjonesparslow {return token::MURRAYJONESPARSLOW;} <DYNARE_STATEMENT>murrayjonesparslow {return token::MURRAYJONESPARSLOW;}
...@@ -456,43 +444,40 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -456,43 +444,40 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>fsolve_options {return token::FSOLVE_OPTIONS;} <DYNARE_STATEMENT>fsolve_options {return token::FSOLVE_OPTIONS;}
<DYNARE_STATEMENT>alpha { <DYNARE_STATEMENT>alpha {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::ALPHA; return token::ALPHA;
} }
<DYNARE_STATEMENT>beta { <DYNARE_STATEMENT>beta {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::BETA; return token::BETA;
} }
<DYNARE_STATEMENT>gamma { <DYNARE_STATEMENT>gamma {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::GAMMA; return token::GAMMA;
} }
<DYNARE_STATEMENT>inv_gamma { <DYNARE_STATEMENT>inv_gamma {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::INV_GAMMA; return token::INV_GAMMA;
} }
<DYNARE_STATEMENT>inv_gamma1 { <DYNARE_STATEMENT>inv_gamma1 {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::INV_GAMMA1; return token::INV_GAMMA1;
} }
<DYNARE_STATEMENT>inv_gamma2 { <DYNARE_STATEMENT>inv_gamma2 {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::INV_GAMMA2; return token::INV_GAMMA2;
} }
<DYNARE_STATEMENT>dirichlet { <DYNARE_STATEMENT>dirichlet {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::DIRICHLET; return token::DIRICHLET;
} }
<DYNARE_STATEMENT>weibull { <DYNARE_STATEMENT>weibull {return token::WEIBULL;}
yylval->build<string>(yytext);
return token::WEIBULL;
}
<DYNARE_STATEMENT>normal { <DYNARE_STATEMENT>normal {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NORMAL; return token::NORMAL;
} }
<DYNARE_STATEMENT>uniform { <DYNARE_STATEMENT>uniform {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::UNIFORM; return token::UNIFORM;
} }
<DYNARE_STATEMENT>gsig2_lmdm {return token::GSIG2_LMDM;} <DYNARE_STATEMENT>gsig2_lmdm {return token::GSIG2_LMDM;}
...@@ -503,13 +488,13 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -503,13 +488,13 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>ncsk {return token::NCSK;} <DYNARE_STATEMENT>ncsk {return token::NCSK;}
<DYNARE_STATEMENT>nstd {return token::NSTD;} <DYNARE_STATEMENT>nstd {return token::NSTD;}
<DYNARE_STATEMENT>ninv { <DYNARE_STATEMENT>ninv {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NINV; return token::NINV;
} }
<DYNARE_STATEMENT>indxparr {return token::INDXPARR;} <DYNARE_STATEMENT>indxparr {return token::INDXPARR;}
<DYNARE_STATEMENT>indxovr {return token::INDXOVR;} <DYNARE_STATEMENT>indxovr {return token::INDXOVR;}
<DYNARE_STATEMENT>aband { <DYNARE_STATEMENT>aband {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::ABAND; return token::ABAND;
} }
<DYNARE_STATEMENT>write_equation_tags {return token::WRITE_EQUATION_TAGS;} <DYNARE_STATEMENT>write_equation_tags {return token::WRITE_EQUATION_TAGS;}
...@@ -526,18 +511,18 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -526,18 +511,18 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>indxgdls {return token::INDXGDLS;} <DYNARE_STATEMENT>indxgdls {return token::INDXGDLS;}
<DYNARE_STATEMENT>eq_ms {return token::EQ_MS;} <DYNARE_STATEMENT>eq_ms {return token::EQ_MS;}
<DYNARE_STATEMENT>cms { <DYNARE_STATEMENT>cms {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::CMS; return token::CMS;
} }
<DYNARE_STATEMENT>ncms { <DYNARE_STATEMENT>ncms {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NCMS; return token::NCMS;
} }
<DYNARE_STATEMENT>eq_cms {return token::EQ_CMS;} <DYNARE_STATEMENT>eq_cms {return token::EQ_CMS;}
<DYNARE_STATEMENT>tlindx {return token::TLINDX;} <DYNARE_STATEMENT>tlindx {return token::TLINDX;}
<DYNARE_STATEMENT>tlnumber {return token::TLNUMBER;} <DYNARE_STATEMENT>tlnumber {return token::TLNUMBER;}
<DYNARE_STATEMENT>cnum { <DYNARE_STATEMENT>cnum {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::CNUM; return token::CNUM;
} }
<DYNARE_STATEMENT>nodecomposition {return token::NODECOMPOSITION;}; <DYNARE_STATEMENT>nodecomposition {return token::NODECOMPOSITION;};
...@@ -619,18 +604,9 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -619,18 +604,9 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>substitute_libs {return token::SUBSTITUTE_LIBS;} <DYNARE_STATEMENT>substitute_libs {return token::SUBSTITUTE_LIBS;}
<DYNARE_STATEMENT>compiler {return token::COMPILER;} <DYNARE_STATEMENT>compiler {return token::COMPILER;}
<DYNARE_STATEMENT>instruments {return token::INSTRUMENTS;} <DYNARE_STATEMENT>instruments {return token::INSTRUMENTS;}
<DYNARE_STATEMENT>hessian { <DYNARE_STATEMENT>hessian {return token::HESSIAN;}
yylval->build<string>(yytext); <DYNARE_STATEMENT>prior_variance {return token::PRIOR_VARIANCE;}
return token::HESSIAN; <DYNARE_STATEMENT>identity_matrix {return token::IDENTITY_MATRIX;}
}
<DYNARE_STATEMENT>prior_variance {
yylval->build<string>(yytext);
return token::PRIOR_VARIANCE;
}
<DYNARE_STATEMENT>identity_matrix {
yylval->build<string>(yytext);
return token::IDENTITY_MATRIX;
}
<DYNARE_STATEMENT>mcmc_jumping_covariance {return token::MCMC_JUMPING_COVARIANCE;} <DYNARE_STATEMENT>mcmc_jumping_covariance {return token::MCMC_JUMPING_COVARIANCE;}
/* These four (var, varexo, varexo_det, parameters) are for change_type */ /* These four (var, varexo, varexo_det, parameters) are for change_type */
...@@ -730,14 +706,6 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -730,14 +706,6 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>lmmcp {return token::LMMCP;} <DYNARE_STATEMENT>lmmcp {return token::LMMCP;}
<DYNARE_STATEMENT>additional_optimizer_steps {return token::ADDITIONAL_OPTIMIZER_STEPS;} <DYNARE_STATEMENT>additional_optimizer_steps {return token::ADDITIONAL_OPTIMIZER_STEPS;}
<DYNARE_STATEMENT>bartlett_kernel_lag {return token::BARTLETT_KERNEL_LAG; } <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>gmm {return token::GMM;}
<DYNARE_STATEMENT>smm {return token::SMM;} <DYNARE_STATEMENT>smm {return token::SMM;}
<DYNARE_STATEMENT>irf_matching {return token::IRF_MATCHING;} <DYNARE_STATEMENT>irf_matching {return token::IRF_MATCHING;}
...@@ -783,8 +751,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -783,8 +751,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>non_zero {return token::NON_ZERO;} <DYNARE_STATEMENT>non_zero {return token::NON_ZERO;}
<DYNARE_STATEMENT>\$[^$]*\$ { <DYNARE_STATEMENT>\$[^$]*\$ {
strtok(yytext + 1, "$"); yylval->emplace<string>(yytext + 1).pop_back();
yylval->build<string>(yytext + 1);
return token::TEX_NAME; return token::TEX_NAME;
} }
...@@ -797,20 +764,21 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -797,20 +764,21 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_BLOCK>periods {return token::PERIODS;} <DYNARE_BLOCK>periods {return token::PERIODS;}
<DYNARE_BLOCK>scales {return token::SCALES;} <DYNARE_BLOCK>scales {return token::SCALES;}
<DYNARE_BLOCK>add { <DYNARE_BLOCK>add {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::ADD; return token::ADD;
} }
<DYNARE_BLOCK>multiply { <DYNARE_BLOCK>multiply {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::MULTIPLY; return token::MULTIPLY;
} }
<DYNARE_STATEMENT,DYNARE_BLOCK>cutoff {return token::CUTOFF;} <DYNARE_STATEMENT,DYNARE_BLOCK>cutoff {return token::CUTOFF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>mfs { <DYNARE_STATEMENT,DYNARE_BLOCK>mfs {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::MFS; return token::MFS;
} }
<DYNARE_STATEMENT,DYNARE_BLOCK>static_mfs {return token::STATIC_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>balanced_growth_test_tol {return token::BALANCED_GROWTH_TEST_TOL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>heterogeneity {return token::HETEROGENEITY;}
<DYNARE_BLOCK>gamma_pdf {return token::GAMMA_PDF;} <DYNARE_BLOCK>gamma_pdf {return token::GAMMA_PDF;}
<DYNARE_BLOCK>beta_pdf {return token::BETA_PDF;} <DYNARE_BLOCK>beta_pdf {return token::BETA_PDF;}
<DYNARE_BLOCK>normal_pdf {return token::NORMAL_PDF;} <DYNARE_BLOCK>normal_pdf {return token::NORMAL_PDF;}
...@@ -822,19 +790,19 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -822,19 +790,19 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_BLOCK>dsge_prior_weight {return token::DSGE_PRIOR_WEIGHT;} <DYNARE_BLOCK>dsge_prior_weight {return token::DSGE_PRIOR_WEIGHT;}
<DYNARE_BLOCK>surprise {return token::SURPRISE;} <DYNARE_BLOCK>surprise {return token::SURPRISE;}
<DYNARE_BLOCK>bind { <DYNARE_BLOCK>bind {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::BIND; return token::BIND;
} }
<DYNARE_BLOCK>relax { <DYNARE_BLOCK>relax {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::RELAX; return token::RELAX;
} }
<DYNARE_BLOCK>error_bind { <DYNARE_BLOCK>error_bind {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::ERROR_BIND; return token::ERROR_BIND;
} }
<DYNARE_BLOCK>error_relax { <DYNARE_BLOCK>error_relax {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::ERROR_RELAX; return token::ERROR_RELAX;
} }
<DYNARE_BLOCK>relative_to_initval {return token::RELATIVE_TO_INITVAL;} <DYNARE_BLOCK>relative_to_initval {return token::RELATIVE_TO_INITVAL;}
...@@ -848,22 +816,24 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -848,22 +816,24 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_BLOCK,DYNARE_STATEMENT>auxname {return token::AUXNAME;} <DYNARE_BLOCK,DYNARE_STATEMENT>auxname {return token::AUXNAME;}
<DYNARE_BLOCK>auxname_target_nonstationary {return token::AUXNAME_TARGET_NONSTATIONARY;} <DYNARE_BLOCK>auxname_target_nonstationary {return token::AUXNAME_TARGET_NONSTATIONARY;}
<DYNARE_BLOCK,DYNARE_STATEMENT>kind { <DYNARE_BLOCK,DYNARE_STATEMENT>kind {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::KIND; return token::KIND;
} }
<DYNARE_BLOCK,DYNARE_STATEMENT>ll { <DYNARE_BLOCK,DYNARE_STATEMENT>ll {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::LL; return token::LL;
} }
<DYNARE_BLOCK,DYNARE_STATEMENT>dl { <DYNARE_BLOCK,DYNARE_STATEMENT>dl {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::DL; return token::DL;
} }
<DYNARE_BLOCK,DYNARE_STATEMENT>dd { <DYNARE_BLOCK,DYNARE_STATEMENT>dd {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::DD; return token::DD;
} }
<DYNARE_BLOCK>weights {return token::WEIGHTS;} <DYNARE_BLOCK>weights {return token::WEIGHTS;}
<DYNARE_BLOCK>exogenize {return token::EXOGENIZE;}
<DYNARE_BLOCK>endogenize {return token::ENDOGENIZE;}
/* Inside Dynare statement */ /* Inside Dynare statement */
<DYNARE_STATEMENT>solve_algo {return token::SOLVE_ALGO;} <DYNARE_STATEMENT>solve_algo {return token::SOLVE_ALGO;}
...@@ -875,7 +845,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -875,7 +845,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>order {return token::ORDER;} <DYNARE_STATEMENT>order {return token::ORDER;}
<DYNARE_STATEMENT>lyapunov {return token::LYAPUNOV;} <DYNARE_STATEMENT>lyapunov {return token::LYAPUNOV;}
<DYNARE_STATEMENT>dr { <DYNARE_STATEMENT>dr {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::DR; return token::DR;
} }
<DYNARE_STATEMENT>lyapunov_complex_threshold {return token::LYAPUNOV_COMPLEX_THRESHOLD;} <DYNARE_STATEMENT>lyapunov_complex_threshold {return token::LYAPUNOV_COMPLEX_THRESHOLD;}
...@@ -939,11 +909,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -939,11 +909,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>time_shift {return token::TIME_SHIFT;} <DYNARE_STATEMENT>time_shift {return token::TIME_SHIFT;}
<DYNARE_STATEMENT>structural {return token::STRUCTURAL;} <DYNARE_STATEMENT>structural {return token::STRUCTURAL;}
<DYNARE_STATEMENT>true { <DYNARE_STATEMENT>true {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::TRUE; return token::TRUE;
} }
<DYNARE_STATEMENT>false { <DYNARE_STATEMENT>false {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::FALSE; return token::FALSE;
} }
...@@ -1011,6 +981,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -1011,6 +981,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_BLOCK>var_expectation {return token::VAR_EXPECTATION;} <DYNARE_BLOCK>var_expectation {return token::VAR_EXPECTATION;}
<DYNARE_BLOCK>pac_expectation {return token::PAC_EXPECTATION;} <DYNARE_BLOCK>pac_expectation {return token::PAC_EXPECTATION;}
<DYNARE_BLOCK>pac_target_nonstationary {return token::PAC_TARGET_NONSTATIONARY;} <DYNARE_BLOCK>pac_target_nonstationary {return token::PAC_TARGET_NONSTATIONARY;}
<DYNARE_BLOCK>sum {return token::SUM;}
<DYNARE_STATEMENT>discount {return token::DISCOUNT;} <DYNARE_STATEMENT>discount {return token::DISCOUNT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>varobs {return token::VAROBS;} <DYNARE_STATEMENT,DYNARE_BLOCK>varobs {return token::VAROBS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>varexobs {return token::VAREXOBS;} <DYNARE_STATEMENT,DYNARE_BLOCK>varexobs {return token::VAREXOBS;}
...@@ -1066,38 +1037,27 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -1066,38 +1037,27 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>use_shock_groups {return token::USE_SHOCK_GROUPS;} <DYNARE_STATEMENT>use_shock_groups {return token::USE_SHOCK_GROUPS;}
<DYNARE_STATEMENT>colormap {return token::COLORMAP;} <DYNARE_STATEMENT>colormap {return token::COLORMAP;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[a-z_][a-z0-9_]* { <DYNARE_STATEMENT,DYNARE_BLOCK>{NAME} {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NAME; return token::NAME;
} }
<DYNARE_STATEMENT,DYNARE_BLOCK>((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+[ed][-+]?[0-9]+) { <DYNARE_STATEMENT,DYNARE_BLOCK>{FLOAT_NUMBER} {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::FLOAT_NUMBER; return token::FLOAT_NUMBER;
} }
<DYNARE_STATEMENT,DYNARE_BLOCK>[0-9]+ { <DYNARE_STATEMENT,DYNARE_BLOCK>[0-9]+ {
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::INT_NUMBER; return token::INT_NUMBER;
} }
<DATES_STATEMENT>\( { yylval->as<string>().append(yytext); dates_parens_nb++; }
<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>\|e { return token::PIPE_E; } <DYNARE_BLOCK>\|e { return token::PIPE_E; }
<DYNARE_BLOCK>\|x { return token::PIPE_X; } <DYNARE_BLOCK>\|x { return token::PIPE_X; }
<DYNARE_BLOCK>\|p { return token::PIPE_P; } <DYNARE_BLOCK>\|p { return token::PIPE_P; }
<DYNARE_STATEMENT,DYNARE_BLOCK>\'[^\']*\' { <DYNARE_STATEMENT,DYNARE_BLOCK>\'[^\']*\' {
yylval->build<string>(yytext + 1).pop_back(); yylval->emplace<string>(yytext + 1).pop_back();
return token::QUOTED_STRING; return token::QUOTED_STRING;
} }
...@@ -1129,11 +1089,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -1129,11 +1089,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
element in initval (in which case Dynare recognizes the matrix name as an external element in initval (in which case Dynare recognizes the matrix name as an external
function symbol), and may want to modify the matrix later with Matlab statements. function symbol), and may want to modify the matrix later with Matlab statements.
*/ */
<INITIAL>[a-z_][a-z0-9_]* { <INITIAL>{NAME} {
if (driver.symbol_exists_and_is_not_modfile_local_or_external_function(yytext)) if (driver.symbol_exists_and_is_not_modfile_local_or_external_function(yytext))
{ {
BEGIN DYNARE_STATEMENT; BEGIN DYNARE_STATEMENT;
yylval->build<string>(yytext); yylval->emplace<string>(yytext);
return token::NAME; return token::NAME;
} }
else else
...@@ -1154,7 +1114,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -1154,7 +1114,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
be able to back out of the statement if we realize it's a native statement be able to back out of the statement if we realize it's a native statement
and move to the NATIVE context and move to the NATIVE context
*/ */
<INITIAL>\[([[:space:]]*[a-z_][a-z0-9_]*[[:space:]]*,{1}[[:space:]]*)*([[:space:]]*[a-z_][a-z0-9_]*[[:space:]]*){1}\] { <INITIAL>\[([[:space:]]*{NAME}[[:space:]]*,{1}[[:space:]]*)*([[:space:]]*{NAME}[[:space:]]*){1}\] {
string yytextcpy{yytext}; string yytextcpy{yytext};
yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), '['), yytextcpy.end()); yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), '['), yytextcpy.end());
yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), ']'), yytextcpy.end()); yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), ']'), yytextcpy.end());
...@@ -1178,7 +1138,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -1178,7 +1138,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
if (dynare_statement) if (dynare_statement)
{ {
BEGIN DYNARE_STATEMENT; BEGIN DYNARE_STATEMENT;
yylval->build<vector<string>>(val); yylval->emplace<vector<string>>(val);
return token::SYMBOL_VEC; return token::SYMBOL_VEC;
} }
} }
...@@ -1223,7 +1183,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) ...@@ -1223,7 +1183,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<NATIVE_COMMENT>"*/"[[:space:]]*\n { BEGIN NATIVE; } <NATIVE_COMMENT>"*/"[[:space:]]*\n { BEGIN NATIVE; }
<NATIVE_COMMENT>. <NATIVE_COMMENT>.
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,DATES_STATEMENT,LINE1,LINE2,LINE3,NATIVE_COMMENT><<EOF>> { yyterminate(); } <INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,LINE1,LINE2,LINE3,NATIVE_COMMENT><<EOF>> { yyterminate(); }
<*>. { driver.error(*yylloc, "character unrecognized by lexer"); } <*>. { driver.error(*yylloc, "character unrecognized by lexer"); }
%% %%
......
/* /*
* Copyright © 2020-2023 Dynare Team * Copyright © 2020-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -74,13 +74,12 @@ EquationTags::erase(const set<int>& eqns, const map<int, int>& old_eqn_num_2_new ...@@ -74,13 +74,12 @@ EquationTags::erase(const set<int>& eqns, const map<int, int>& old_eqn_num_2_new
eqn_tags.erase(eqn); eqn_tags.erase(eqn);
for (const auto& [oldeqn, neweqn] : old_eqn_num_2_new) for (const auto& [oldeqn, neweqn] : old_eqn_num_2_new)
for (auto& [eqn, tags] : eqn_tags) if (eqn_tags.contains(oldeqn))
if (eqn == oldeqn) {
{ auto tmp = eqn_tags.extract(oldeqn);
auto tmp = eqn_tags.extract(eqn); tmp.key() = neweqn;
tmp.key() = neweqn; eqn_tags.insert(move(tmp));
eqn_tags.insert(move(tmp)); }
}
} }
void void
......
/* /*
* Copyright © 2007-2024 Dynare Team * Copyright © 2007-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <limits> #include <limits>
#include <numbers> #include <numbers>
#include <numeric> #include <numeric>
#include <ranges>
#include <utility> #include <utility>
#include "DataTree.hh" #include "DataTree.hh"
...@@ -194,8 +195,7 @@ ExprNode::collectVariables(SymbolType type, set<int>& result) const ...@@ -194,8 +195,7 @@ ExprNode::collectVariables(SymbolType type, set<int>& result) const
{ {
set<pair<int, int>> symbs_lags; set<pair<int, int>> symbs_lags;
collectDynamicVariables(type, symbs_lags); collectDynamicVariables(type, symbs_lags);
transform(symbs_lags.begin(), symbs_lags.end(), inserter(result, result.begin()), ranges::copy(views::keys(symbs_lags), inserter(result, result.begin()));
[](const auto& x) { return x.first; });
} }
void void
...@@ -870,6 +870,13 @@ NumConstNode::substituteLogTransform([[maybe_unused]] int orig_symb_id, ...@@ -870,6 +870,13 @@ NumConstNode::substituteLogTransform([[maybe_unused]] int orig_symb_id,
return const_cast<NumConstNode*>(this); return const_cast<NumConstNode*>(this);
} }
expr_t
NumConstNode::substituteAggregationOperators([[maybe_unused]] subst_table_t& subst_table,
[[maybe_unused]] vector<BinaryOpNode*>& neweqs) const
{
return const_cast<NumConstNode*>(this);
}
VariableNode::VariableNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg, int lag_arg) : VariableNode::VariableNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg, int lag_arg) :
ExprNode {datatree_arg, idx_arg}, symb_id {symb_id_arg}, lag {lag_arg} ExprNode {datatree_arg, idx_arg}, symb_id {symb_id_arg}, lag {lag_arg}
{ {
...@@ -900,6 +907,7 @@ VariableNode::prepareForDerivation() ...@@ -900,6 +907,7 @@ VariableNode::prepareForDerivation()
[[fallthrough]]; [[fallthrough]];
case SymbolType::endogenous: case SymbolType::endogenous:
case SymbolType::parameter: case SymbolType::parameter:
case SymbolType::heterogeneousEndogenous:
non_null_derivatives.insert(getDerivID()); non_null_derivatives.insert(getDerivID());
break; break;
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
...@@ -907,6 +915,8 @@ VariableNode::prepareForDerivation() ...@@ -907,6 +915,8 @@ VariableNode::prepareForDerivation()
// Non null derivatives are those of the value of the local parameter // Non null derivatives are those of the value of the local parameter
non_null_derivatives = datatree.getLocalVariable(symb_id, lag)->non_null_derivatives; non_null_derivatives = datatree.getLocalVariable(symb_id, lag)->non_null_derivatives;
break; break;
case SymbolType::heterogeneousExogenous:
case SymbolType::heterogeneousParameter:
case SymbolType::modFileLocalVariable: case SymbolType::modFileLocalVariable:
case SymbolType::statementDeclaredVariable: case SymbolType::statementDeclaredVariable:
case SymbolType::unusedEndogenous: case SymbolType::unusedEndogenous:
...@@ -955,6 +965,9 @@ VariableNode::prepareForChainRuleDerivation( ...@@ -955,6 +965,9 @@ VariableNode::prepareForChainRuleDerivation(
case SymbolType::modFileLocalVariable: case SymbolType::modFileLocalVariable:
case SymbolType::statementDeclaredVariable: case SymbolType::statementDeclaredVariable:
case SymbolType::unusedEndogenous: case SymbolType::unusedEndogenous:
case SymbolType::heterogeneousEndogenous:
case SymbolType::heterogeneousExogenous:
case SymbolType::heterogeneousParameter:
// Those variables are never derived using chain rule // Those variables are never derived using chain rule
non_null_chain_rule_derivatives.try_emplace(const_cast<VariableNode*>(this)); non_null_chain_rule_derivatives.try_emplace(const_cast<VariableNode*>(this));
break; break;
...@@ -990,10 +1003,14 @@ VariableNode::computeDerivative(int deriv_id) ...@@ -990,10 +1003,14 @@ VariableNode::computeDerivative(int deriv_id)
[[fallthrough]]; [[fallthrough]];
case SymbolType::endogenous: case SymbolType::endogenous:
case SymbolType::parameter: case SymbolType::parameter:
case SymbolType::heterogeneousEndogenous:
if (deriv_id == getDerivID()) if (deriv_id == getDerivID())
return datatree.One; return datatree.One;
else else
return datatree.Zero; return datatree.Zero;
case SymbolType::heterogeneousExogenous:
case SymbolType::heterogeneousParameter:
return datatree.Zero;
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
return datatree.getLocalVariable(symb_id, lag)->getDerivative(deriv_id); return datatree.getLocalVariable(symb_id, lag)->getDerivative(deriv_id);
case SymbolType::modFileLocalVariable: case SymbolType::modFileLocalVariable:
...@@ -1069,8 +1086,23 @@ VariableNode::writeJsonAST(ostream& output) const ...@@ -1069,8 +1086,23 @@ VariableNode::writeJsonAST(ostream& output) const
case SymbolType::excludedVariable: case SymbolType::excludedVariable:
cerr << "VariableNode::computeDerivative: Impossible case!" << endl; cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
case SymbolType::heterogeneousEndogenous:
output << "heterogeneousEndogenous";
break;
case SymbolType::heterogeneousExogenous:
output << "heterogeneousExogenous";
break;
case SymbolType::heterogeneousParameter:
output << "heterogeneousParameter";
break;
} }
output << R"(", "lag" : )" << lag << "}"; output << '"';
if (isHeterogeneous(get_type()))
output << R"(, "heterogeneity_dimension" : ")"
<< datatree.heterogeneity_table.getName(
datatree.symbol_table.getHeterogeneityDimension(symb_id))
<< '"';
output << R"(, "lag" : )" << lag << "}";
} }
void void
...@@ -1168,12 +1200,18 @@ VariableNode::writeOutput(ostream& output, ExprNodeOutputType output_type, ...@@ -1168,12 +1200,18 @@ VariableNode::writeOutput(ostream& output, ExprNodeOutputType output_type,
case SymbolType::endogenous: case SymbolType::endogenous:
switch (int tsid {getTypeSpecificID()}; output_type) switch (int tsid {getTypeSpecificID()}; output_type)
{ {
case ExprNodeOutputType::juliaDynamicModel:
case ExprNodeOutputType::juliaSparseDynamicModel: case ExprNodeOutputType::juliaSparseDynamicModel:
case ExprNodeOutputType::matlabDynamicModel:
case ExprNodeOutputType::matlabSparseDynamicModel: case ExprNodeOutputType::matlabSparseDynamicModel:
case ExprNodeOutputType::CDynamicModel:
case ExprNodeOutputType::CSparseDynamicModel: case ExprNodeOutputType::CSparseDynamicModel:
assert(lag >= -1 && lag <= 1);
i = tsid + (lag + 1) * datatree.symbol_table.endo_nbr()
+ ARRAY_SUBSCRIPT_OFFSET(output_type);
output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i
<< RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case ExprNodeOutputType::juliaDynamicModel:
case ExprNodeOutputType::matlabDynamicModel:
case ExprNodeOutputType::CDynamicModel:
i = datatree.getJacobianCol(getDerivID(), isSparseModelOutput(output_type)) i = datatree.getJacobianCol(getDerivID(), isSparseModelOutput(output_type))
+ ARRAY_SUBSCRIPT_OFFSET(output_type); + ARRAY_SUBSCRIPT_OFFSET(output_type);
output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i
...@@ -1405,6 +1443,64 @@ VariableNode::writeOutput(ostream& output, ExprNodeOutputType output_type, ...@@ -1405,6 +1443,64 @@ VariableNode::writeOutput(ostream& output, ExprNodeOutputType output_type,
case SymbolType::excludedVariable: case SymbolType::excludedVariable:
cerr << "VariableNode::writeOutput: Impossible case" << endl; cerr << "VariableNode::writeOutput: Impossible case" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
case SymbolType::heterogeneousEndogenous:
switch (int tsid = datatree.symbol_table.getTypeSpecificID(symb_id); output_type)
{
case ExprNodeOutputType::juliaSparseDynamicModel:
case ExprNodeOutputType::matlabSparseDynamicModel:
case ExprNodeOutputType::CSparseDynamicModel:
assert(lag >= -1 && lag <= 1);
i = tsid
+ (lag + 1)
* datatree.symbol_table.het_endo_nbr(
datatree.symbol_table.getHeterogeneityDimension(symb_id))
+ ARRAY_SUBSCRIPT_OFFSET(output_type);
output << "yh" << LEFT_ARRAY_SUBSCRIPT(output_type) << i
<< RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
default:
cerr << "VariableNode::writeOutput: unsupported output type for heterogeneousEndogenous "
"symbol"
<< endl;
exit(EXIT_FAILURE);
}
break;
case SymbolType::heterogeneousExogenous:
i = datatree.symbol_table.getTypeSpecificID(symb_id) + ARRAY_SUBSCRIPT_OFFSET(output_type);
switch (output_type)
{
case ExprNodeOutputType::juliaSparseDynamicModel:
case ExprNodeOutputType::matlabSparseDynamicModel:
case ExprNodeOutputType::CSparseDynamicModel:
assert(lag == 0);
output << "xh" << LEFT_ARRAY_SUBSCRIPT(output_type) << i
<< RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
default:
cerr << "VariableNode::writeOutput: unsupported output type for heterogeneousExogenous "
"symbol"
<< endl;
exit(EXIT_FAILURE);
}
break;
case SymbolType::heterogeneousParameter:
i = datatree.symbol_table.getTypeSpecificID(symb_id) + ARRAY_SUBSCRIPT_OFFSET(output_type);
switch (output_type)
{
case ExprNodeOutputType::juliaSparseDynamicModel:
case ExprNodeOutputType::matlabSparseDynamicModel:
case ExprNodeOutputType::CSparseDynamicModel:
output << "paramsh" << LEFT_ARRAY_SUBSCRIPT(output_type) << i
<< RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
default:
cerr << "VariableNode::writeOutput: unsupported output type for heterogeneousParameter "
"symbol"
<< endl;
exit(EXIT_FAILURE);
}
break;
} }
} }
...@@ -1519,6 +1615,7 @@ VariableNode::computeChainRuleDerivative( ...@@ -1519,6 +1615,7 @@ VariableNode::computeChainRuleDerivative(
[[fallthrough]]; [[fallthrough]];
case SymbolType::endogenous: case SymbolType::endogenous:
case SymbolType::parameter: case SymbolType::parameter:
case SymbolType::heterogeneousEndogenous:
if (deriv_id == getDerivID()) if (deriv_id == getDerivID())
return datatree.One; return datatree.One;
// If there is in the equation a recursive variable we could use a chaine rule derivation // If there is in the equation a recursive variable we could use a chaine rule derivation
...@@ -1527,6 +1624,9 @@ VariableNode::computeChainRuleDerivative( ...@@ -1527,6 +1624,9 @@ VariableNode::computeChainRuleDerivative(
non_null_chain_rule_derivatives, cache); non_null_chain_rule_derivatives, cache);
else else
return datatree.Zero; return datatree.Zero;
case SymbolType::heterogeneousExogenous:
case SymbolType::heterogeneousParameter:
return datatree.Zero;
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
return datatree.getLocalVariable(symb_id, lag) return datatree.getLocalVariable(symb_id, lag)
...@@ -1584,6 +1684,9 @@ VariableNode::computeXrefs(EquationInfo& ei) const ...@@ -1584,6 +1684,9 @@ VariableNode::computeXrefs(EquationInfo& ei) const
case SymbolType::externalFunction: case SymbolType::externalFunction:
case SymbolType::epilogue: case SymbolType::epilogue:
case SymbolType::excludedVariable: case SymbolType::excludedVariable:
case SymbolType::heterogeneousEndogenous:
case SymbolType::heterogeneousExogenous:
case SymbolType::heterogeneousParameter:
break; break;
} }
} }
...@@ -1682,6 +1785,9 @@ VariableNode::maxLead() const ...@@ -1682,6 +1785,9 @@ VariableNode::maxLead() const
case SymbolType::endogenous: case SymbolType::endogenous:
case SymbolType::exogenous: case SymbolType::exogenous:
case SymbolType::exogenousDet: case SymbolType::exogenousDet:
case SymbolType::epilogue:
case SymbolType::heterogeneousEndogenous:
case SymbolType::heterogeneousExogenous:
return lag; return lag;
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
return datatree.getLocalVariable(symb_id, lag)->maxLead(); return datatree.getLocalVariable(symb_id, lag)->maxLead();
...@@ -1698,6 +1804,9 @@ VariableNode::maxLag() const ...@@ -1698,6 +1804,9 @@ VariableNode::maxLag() const
case SymbolType::endogenous: case SymbolType::endogenous:
case SymbolType::exogenous: case SymbolType::exogenous:
case SymbolType::exogenousDet: case SymbolType::exogenousDet:
case SymbolType::epilogue:
case SymbolType::heterogeneousEndogenous:
case SymbolType::heterogeneousExogenous:
return -lag; return -lag;
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
return datatree.getLocalVariable(symb_id, lag)->maxLag(); return datatree.getLocalVariable(symb_id, lag)->maxLag();
...@@ -1715,6 +1824,8 @@ VariableNode::maxLagWithDiffsExpanded() const ...@@ -1715,6 +1824,8 @@ VariableNode::maxLagWithDiffsExpanded() const
case SymbolType::exogenous: case SymbolType::exogenous:
case SymbolType::exogenousDet: case SymbolType::exogenousDet:
case SymbolType::epilogue: case SymbolType::epilogue:
case SymbolType::heterogeneousEndogenous:
case SymbolType::heterogeneousExogenous:
return -lag; return -lag;
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
return datatree.getLocalVariable(symb_id, lag)->maxLagWithDiffsExpanded(); return datatree.getLocalVariable(symb_id, lag)->maxLagWithDiffsExpanded();
...@@ -1836,8 +1947,11 @@ VariableNode::decreaseLeadsLags(int n) const ...@@ -1836,8 +1947,11 @@ VariableNode::decreaseLeadsLags(int n) const
case SymbolType::endogenous: case SymbolType::endogenous:
case SymbolType::exogenous: case SymbolType::exogenous:
case SymbolType::exogenousDet: case SymbolType::exogenousDet:
case SymbolType::epilogue:
case SymbolType::trend: case SymbolType::trend:
case SymbolType::logTrend: case SymbolType::logTrend:
case SymbolType::heterogeneousEndogenous:
case SymbolType::heterogeneousExogenous:
return datatree.AddVariable(symb_id, lag - n); return datatree.AddVariable(symb_id, lag - n);
case SymbolType::modelLocalVariable: case SymbolType::modelLocalVariable:
return datatree.getLocalVariable(symb_id, lag)->decreaseLeadsLags(n); return datatree.getLocalVariable(symb_id, lag)->decreaseLeadsLags(n);
...@@ -2234,6 +2348,17 @@ VariableNode::substituteLogTransform(int orig_symb_id, int aux_symb_id) const ...@@ -2234,6 +2348,17 @@ VariableNode::substituteLogTransform(int orig_symb_id, int aux_symb_id) const
return const_cast<VariableNode*>(this); return const_cast<VariableNode*>(this);
} }
expr_t
VariableNode::substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
{
if (get_type() == SymbolType::modelLocalVariable)
return datatree.getLocalVariable(symb_id, lag)
->substituteAggregationOperators(subst_table, neweqs);
return const_cast<VariableNode*>(this);
}
UnaryOpNode::UnaryOpNode(DataTree& datatree_arg, int idx_arg, UnaryOpcode op_code_arg, UnaryOpNode::UnaryOpNode(DataTree& datatree_arg, int idx_arg, UnaryOpcode op_code_arg,
const expr_t arg_arg, int expectation_information_set_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, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg,
...@@ -2259,12 +2384,12 @@ UnaryOpNode::prepareForDerivation() ...@@ -2259,12 +2384,12 @@ UnaryOpNode::prepareForDerivation()
/* Non-null derivatives are those of the argument (except for STEADY_STATE in /* Non-null derivatives are those of the argument (except for STEADY_STATE in
a dynamic context, in which case the potentially non-null derivatives are a dynamic context, in which case the potentially non-null derivatives are
all the parameters) */ all the parameters; and for SUM, which will be substituted out before deriving) */
if ((op_code == UnaryOpcode::steadyState || op_code == UnaryOpcode::steadyStateParamDeriv if ((op_code == UnaryOpcode::steadyState || op_code == UnaryOpcode::steadyStateParamDeriv
|| op_code == UnaryOpcode::steadyStateParam2ndDeriv) || op_code == UnaryOpcode::steadyStateParam2ndDeriv)
&& datatree.is_dynamic) && datatree.is_dynamic)
datatree.addAllParamDerivId(non_null_derivatives); datatree.addAllParamDerivId(non_null_derivatives);
else else if (op_code != UnaryOpcode::sum)
{ {
arg->prepareForDerivation(); arg->prepareForDerivation();
non_null_derivatives = arg->non_null_derivatives; non_null_derivatives = arg->non_null_derivatives;
...@@ -2441,6 +2566,9 @@ UnaryOpNode::composeDerivatives(expr_t darg, int deriv_id) ...@@ -2441,6 +2566,9 @@ UnaryOpNode::composeDerivatives(expr_t darg, int deriv_id)
case UnaryOpcode::adl: case UnaryOpcode::adl:
cerr << "UnaryOpNode::composeDerivatives: not implemented on UnaryOpcode::adl" << endl; cerr << "UnaryOpNode::composeDerivatives: not implemented on UnaryOpcode::adl" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
case UnaryOpcode::sum:
cerr << "UnaryOpNode::composeDerivatives: not implemented on UnaryOpcode::sum" << endl;
exit(EXIT_FAILURE);
} }
__builtin_unreachable(); // Silence GCC warning __builtin_unreachable(); // Silence GCC warning
} }
...@@ -2535,6 +2663,8 @@ UnaryOpNode::cost(int cost, bool is_matlab) const ...@@ -2535,6 +2663,8 @@ UnaryOpNode::cost(int cost, bool is_matlab) const
case UnaryOpcode::adl: case UnaryOpcode::adl:
cerr << "UnaryOpNode::cost: not implemented on UnaryOpcode::adl" << endl; cerr << "UnaryOpNode::cost: not implemented on UnaryOpcode::adl" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
case UnaryOpcode::sum:
return 0; // In the generated files, the SUM() operator behaves like a variable
} }
else else
// Cost for C files // Cost for C files
...@@ -2585,6 +2715,8 @@ UnaryOpNode::cost(int cost, bool is_matlab) const ...@@ -2585,6 +2715,8 @@ UnaryOpNode::cost(int cost, bool is_matlab) const
case UnaryOpcode::adl: case UnaryOpcode::adl:
cerr << "UnaryOpNode::cost: not implemented on UnaryOpcode::adl" << endl; cerr << "UnaryOpNode::cost: not implemented on UnaryOpcode::adl" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
case UnaryOpcode::sum:
return 0; // In the generated files, the SUM() operator behaves like a variable
} }
__builtin_unreachable(); // Silence GCC warning __builtin_unreachable(); // Silence GCC warning
} }
...@@ -2729,6 +2861,9 @@ UnaryOpNode::writeJsonAST(ostream& output) const ...@@ -2729,6 +2861,9 @@ UnaryOpNode::writeJsonAST(ostream& output) const
case UnaryOpcode::erfc: case UnaryOpcode::erfc:
output << "erfc"; output << "erfc";
break; break;
case UnaryOpcode::sum:
output << "sum";
break;
} }
output << R"(", "arg" : )"; output << R"(", "arg" : )";
arg->writeJsonAST(output); arg->writeJsonAST(output);
...@@ -2843,10 +2978,8 @@ UnaryOpNode::writeJsonOutput(ostream& output, const temporary_terms_t& temporary ...@@ -2843,10 +2978,8 @@ UnaryOpNode::writeJsonOutput(ostream& output, const temporary_terms_t& temporary
output << "])"; output << "])";
return; return;
case UnaryOpcode::steadyState: case UnaryOpcode::steadyState:
output << "("; output << "STEADY_STATE";
arg->writeJsonOutput(output, temporary_terms, tef_terms, isdynamic); break;
output << ")";
return;
case UnaryOpcode::steadyStateParamDeriv: case UnaryOpcode::steadyStateParamDeriv:
{ {
auto varg = dynamic_cast<VariableNode*>(arg); auto varg = dynamic_cast<VariableNode*>(arg);
...@@ -2881,6 +3014,9 @@ UnaryOpNode::writeJsonOutput(ostream& output, const temporary_terms_t& temporary ...@@ -2881,6 +3014,9 @@ UnaryOpNode::writeJsonOutput(ostream& output, const temporary_terms_t& temporary
case UnaryOpcode::erfc: case UnaryOpcode::erfc:
output << "erfc"; output << "erfc";
break; break;
case UnaryOpcode::sum:
output << "sum";
break;
} }
bool close_parenthesis = false; bool close_parenthesis = false;
...@@ -3111,6 +3247,20 @@ UnaryOpNode::writeOutput(ostream& output, ExprNodeOutputType output_type, ...@@ -3111,6 +3247,20 @@ UnaryOpNode::writeOutput(ostream& output, ExprNodeOutputType output_type,
case UnaryOpcode::adl: case UnaryOpcode::adl:
output << "adl"; output << "adl";
break; break;
case UnaryOpcode::sum:
if (isLatexOutput(output_type))
output << "sum";
else
{
auto varg {dynamic_cast<VariableNode*>(arg)};
assert(varg && varg->lag == 0);
int idx {
datatree.heterogeneity_table.getSummedHeterogenousEndogenousIndex(varg->symb_id)};
output << "yagg" << LEFT_ARRAY_SUBSCRIPT(output_type) << idx + 1
<< RIGHT_ARRAY_SUBSCRIPT(output_type);
return;
}
break;
} }
if (output_type == ExprNodeOutputType::juliaTimeDataFrame && op_code != UnaryOpcode::uminus) if (output_type == ExprNodeOutputType::juliaTimeDataFrame && op_code != UnaryOpcode::uminus)
...@@ -3240,6 +3390,9 @@ UnaryOpNode::eval_opcode(UnaryOpcode op_code, double v) noexcept(false) ...@@ -3240,6 +3390,9 @@ UnaryOpNode::eval_opcode(UnaryOpcode op_code, double v) noexcept(false)
case UnaryOpcode::adl: case UnaryOpcode::adl:
cerr << "UnaryOpNode::eval_opcode: not implemented on UnaryOpcode::adl" << endl; cerr << "UnaryOpNode::eval_opcode: not implemented on UnaryOpcode::adl" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
case UnaryOpcode::sum:
cerr << "UnaryOpNode::eval_opcode: not implemented on UnaryOpcode::sum" << endl;
exit(EXIT_FAILURE);
} }
__builtin_unreachable(); // Silence GCC warning __builtin_unreachable(); // Silence GCC warning
} }
...@@ -3497,6 +3650,8 @@ UnaryOpNode::buildSimilarUnaryOpNode(expr_t alt_arg, DataTree& alt_datatree) con ...@@ -3497,6 +3650,8 @@ UnaryOpNode::buildSimilarUnaryOpNode(expr_t alt_arg, DataTree& alt_datatree) con
return alt_datatree.AddDiff(alt_arg); return alt_datatree.AddDiff(alt_arg);
case UnaryOpcode::adl: case UnaryOpcode::adl:
return alt_datatree.AddAdl(alt_arg, adl_param_name, adl_lags); return alt_datatree.AddAdl(alt_arg, adl_param_name, adl_lags);
case UnaryOpcode::sum:
return alt_datatree.AddSum(alt_arg);
} }
__builtin_unreachable(); // Silence GCC warning __builtin_unreachable(); // Silence GCC warning
} }
...@@ -4089,6 +4244,34 @@ UnaryOpNode::substituteLogTransform(int orig_symb_id, int aux_symb_id) const ...@@ -4089,6 +4244,34 @@ UnaryOpNode::substituteLogTransform(int orig_symb_id, int aux_symb_id) const
return recurseTransform(&ExprNode::substituteLogTransform, orig_symb_id, aux_symb_id); return recurseTransform(&ExprNode::substituteLogTransform, orig_symb_id, aux_symb_id);
} }
expr_t
UnaryOpNode::substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
{
if (op_code == UnaryOpcode::sum)
{
if (auto it = subst_table.find(const_cast<UnaryOpNode*>(this)); it != subst_table.end())
return const_cast<VariableNode*>(it->second);
// Arriving here, we need to create an auxiliary variable for this operator
const VariableNode* varg {dynamic_cast<const VariableNode*>(arg)};
assert(varg && varg->lag == 0);
const string varname {"SUM_" + varg->getName()};
int symb_id {datatree.symbol_table.addAggregationOpAuxiliaryVar(
varname, const_cast<UnaryOpNode*>(this))};
expr_t newAuxE = datatree.AddVariable(symb_id, 0);
subst_table[this] = dynamic_cast<VariableNode*>(newAuxE);
neweqs.push_back(datatree.AddEqual(newAuxE, const_cast<UnaryOpNode*>(this)));
datatree.heterogeneity_table.addSummedHeterogeneousEndogenous(varg->symb_id);
return newAuxE;
}
else
return recurseTransform(&ExprNode::substituteAggregationOperators, subst_table, neweqs);
}
BinaryOpNode::BinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg, BinaryOpNode::BinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg,
BinaryOpcode op_code_arg, const expr_t arg2_arg, BinaryOpcode op_code_arg, const expr_t arg2_arg,
int powerDerivOrder_arg) : int powerDerivOrder_arg) :
...@@ -4114,9 +4297,8 @@ BinaryOpNode::prepareForDerivation() ...@@ -4114,9 +4297,8 @@ BinaryOpNode::prepareForDerivation()
// Non-null derivatives are the union of those of the arguments // Non-null derivatives are the union of those of the arguments
// Compute set union of arg1->non_null_derivatives and arg2->non_null_derivatives // Compute set union of arg1->non_null_derivatives and arg2->non_null_derivatives
set_union(arg1->non_null_derivatives.begin(), arg1->non_null_derivatives.end(), ranges::set_union(arg1->non_null_derivatives, arg2->non_null_derivatives,
arg2->non_null_derivatives.begin(), arg2->non_null_derivatives.end(), inserter(non_null_derivatives, non_null_derivatives.begin()));
inserter(non_null_derivatives, non_null_derivatives.begin()));
} }
void void
...@@ -4131,10 +4313,8 @@ BinaryOpNode::prepareForChainRuleDerivation( ...@@ -4131,10 +4313,8 @@ BinaryOpNode::prepareForChainRuleDerivation(
arg2->prepareForChainRuleDerivation(recursive_variables, non_null_chain_rule_derivatives); arg2->prepareForChainRuleDerivation(recursive_variables, non_null_chain_rule_derivatives);
set<int>& nnd {non_null_chain_rule_derivatives[const_cast<BinaryOpNode*>(this)]}; set<int>& nnd {non_null_chain_rule_derivatives[const_cast<BinaryOpNode*>(this)]};
set_union(non_null_chain_rule_derivatives.at(arg1).begin(), ranges::set_union(non_null_chain_rule_derivatives.at(arg1),
non_null_chain_rule_derivatives.at(arg1).end(), non_null_chain_rule_derivatives.at(arg2), inserter(nnd, nnd.begin()));
non_null_chain_rule_derivatives.at(arg2).begin(),
non_null_chain_rule_derivatives.at(arg2).end(), inserter(nnd, nnd.begin()));
} }
expr_t expr_t
...@@ -6017,6 +6197,13 @@ BinaryOpNode::substituteLogTransform(int orig_symb_id, int aux_symb_id) const ...@@ -6017,6 +6197,13 @@ BinaryOpNode::substituteLogTransform(int orig_symb_id, int aux_symb_id) const
return recurseTransform(&ExprNode::substituteLogTransform, orig_symb_id, aux_symb_id); return recurseTransform(&ExprNode::substituteLogTransform, orig_symb_id, aux_symb_id);
} }
expr_t
BinaryOpNode::substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
{
return recurseTransform(&ExprNode::substituteAggregationOperators, subst_table, neweqs);
}
TrinaryOpNode::TrinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg, TrinaryOpNode::TrinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg,
TrinaryOpcode op_code_arg, const expr_t arg2_arg, TrinaryOpcode op_code_arg, const expr_t arg2_arg,
const expr_t arg3_arg) : const expr_t arg3_arg) :
...@@ -6043,12 +6230,10 @@ TrinaryOpNode::prepareForDerivation() ...@@ -6043,12 +6230,10 @@ TrinaryOpNode::prepareForDerivation()
// Non-null derivatives are the union of those of the arguments // Non-null derivatives are the union of those of the arguments
// Compute set union of arg{1,2,3}->non_null_derivatives // Compute set union of arg{1,2,3}->non_null_derivatives
set<int> non_null_derivatives_tmp; set<int> non_null_derivatives_tmp;
set_union(arg1->non_null_derivatives.begin(), arg1->non_null_derivatives.end(), ranges::set_union(arg1->non_null_derivatives, arg2->non_null_derivatives,
arg2->non_null_derivatives.begin(), arg2->non_null_derivatives.end(), inserter(non_null_derivatives_tmp, non_null_derivatives_tmp.begin()));
inserter(non_null_derivatives_tmp, non_null_derivatives_tmp.begin())); ranges::set_union(non_null_derivatives_tmp, arg3->non_null_derivatives,
set_union(non_null_derivatives_tmp.begin(), non_null_derivatives_tmp.end(), inserter(non_null_derivatives, non_null_derivatives.begin()));
arg3->non_null_derivatives.begin(), arg3->non_null_derivatives.end(),
inserter(non_null_derivatives, non_null_derivatives.begin()));
} }
void void
...@@ -6065,12 +6250,9 @@ TrinaryOpNode::prepareForChainRuleDerivation( ...@@ -6065,12 +6250,9 @@ TrinaryOpNode::prepareForChainRuleDerivation(
set<int>& nnd {non_null_chain_rule_derivatives[const_cast<TrinaryOpNode*>(this)]}; set<int>& nnd {non_null_chain_rule_derivatives[const_cast<TrinaryOpNode*>(this)]};
set<int> nnd_tmp; set<int> nnd_tmp;
set_union(non_null_chain_rule_derivatives.at(arg1).begin(), ranges::set_union(non_null_chain_rule_derivatives.at(arg1),
non_null_chain_rule_derivatives.at(arg1).end(), non_null_chain_rule_derivatives.at(arg2), inserter(nnd_tmp, nnd_tmp.begin()));
non_null_chain_rule_derivatives.at(arg2).begin(), ranges::set_union(nnd_tmp, non_null_chain_rule_derivatives.at(arg3), inserter(nnd, nnd.begin()));
non_null_chain_rule_derivatives.at(arg2).end(), inserter(nnd_tmp, nnd_tmp.begin()));
set_union(nnd_tmp.begin(), nnd_tmp.end(), non_null_chain_rule_derivatives.at(arg3).begin(),
non_null_chain_rule_derivatives.at(arg3).end(), inserter(nnd, nnd.begin()));
} }
expr_t expr_t
...@@ -6274,9 +6456,9 @@ TrinaryOpNode::eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v ...@@ -6274,9 +6456,9 @@ TrinaryOpNode::eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v
switch (op_code) switch (op_code)
{ {
case TrinaryOpcode::normcdf: case TrinaryOpcode::normcdf:
return (0.5 * (1 + erf((v1 - v2) / v3 / numbers::sqrt2))); return 0.5 * (1 + erf((v1 - v2) / v3 / numbers::sqrt2));
case TrinaryOpcode::normpdf: case TrinaryOpcode::normpdf:
return (1 / (v3 * sqrt(2 * numbers::pi) * exp(pow((v1 - v2) / v3, 2) / 2))); return 1 / (v3 * sqrt(2 * numbers::pi) * exp(pow((v1 - v2) / v3, 2) / 2));
} }
__builtin_unreachable(); // Silence GCC warning __builtin_unreachable(); // Silence GCC warning
} }
...@@ -6805,9 +6987,9 @@ TrinaryOpNode::isVariableNodeEqualTo([[maybe_unused]] SymbolType type_arg, ...@@ -6805,9 +6987,9 @@ TrinaryOpNode::isVariableNodeEqualTo([[maybe_unused]] SymbolType type_arg,
bool bool
TrinaryOpNode::containsPacExpectation(const string& pac_model_name) const TrinaryOpNode::containsPacExpectation(const string& pac_model_name) const
{ {
return (arg1->containsPacExpectation(pac_model_name) return arg1->containsPacExpectation(pac_model_name)
|| arg2->containsPacExpectation(pac_model_name) || arg2->containsPacExpectation(pac_model_name)
|| arg3->containsPacExpectation(pac_model_name)); || arg3->containsPacExpectation(pac_model_name);
} }
bool bool
...@@ -6861,6 +7043,13 @@ TrinaryOpNode::substituteLogTransform(int orig_symb_id, int aux_symb_id) const ...@@ -6861,6 +7043,13 @@ TrinaryOpNode::substituteLogTransform(int orig_symb_id, int aux_symb_id) const
return recurseTransform(&ExprNode::substituteLogTransform, orig_symb_id, aux_symb_id); return recurseTransform(&ExprNode::substituteLogTransform, orig_symb_id, aux_symb_id);
} }
expr_t
TrinaryOpNode::substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
{
return recurseTransform(&ExprNode::substituteAggregationOperators, subst_table, neweqs);
}
AbstractExternalFunctionNode::AbstractExternalFunctionNode(DataTree& datatree_arg, int idx_arg, AbstractExternalFunctionNode::AbstractExternalFunctionNode(DataTree& datatree_arg, int idx_arg,
int symb_id_arg, int symb_id_arg,
vector<expr_t> arguments_arg) : vector<expr_t> arguments_arg) :
...@@ -6887,10 +7076,8 @@ AbstractExternalFunctionNode::prepareForDerivation() ...@@ -6887,10 +7076,8 @@ AbstractExternalFunctionNode::prepareForDerivation()
for (int i = 1; i < static_cast<int>(arguments.size()); i++) for (int i = 1; i < static_cast<int>(arguments.size()); i++)
{ {
set<int> non_null_derivatives_tmp; set<int> non_null_derivatives_tmp;
set_union(non_null_derivatives.begin(), non_null_derivatives.end(), ranges::set_union(non_null_derivatives, arguments.at(i)->non_null_derivatives,
arguments.at(i)->non_null_derivatives.begin(), inserter(non_null_derivatives_tmp, non_null_derivatives_tmp.begin()));
arguments.at(i)->non_null_derivatives.end(),
inserter(non_null_derivatives_tmp, non_null_derivatives_tmp.begin()));
non_null_derivatives = move(non_null_derivatives_tmp); non_null_derivatives = move(non_null_derivatives_tmp);
} }
...@@ -6915,9 +7102,8 @@ AbstractExternalFunctionNode::prepareForChainRuleDerivation( ...@@ -6915,9 +7102,8 @@ AbstractExternalFunctionNode::prepareForChainRuleDerivation(
for (int i {1}; i < static_cast<int>(arguments.size()); i++) for (int i {1}; i < static_cast<int>(arguments.size()); i++)
{ {
set<int> nnd_tmp; set<int> nnd_tmp;
set_union(nnd.begin(), nnd.end(), non_null_chain_rule_derivatives.at(arguments.at(i)).begin(), ranges::set_union(nnd, non_null_chain_rule_derivatives.at(arguments.at(i)),
non_null_chain_rule_derivatives.at(arguments.at(i)).end(), inserter(nnd_tmp, nnd_tmp.begin()));
inserter(nnd_tmp, nnd_tmp.begin()));
nnd = move(nnd_tmp); nnd = move(nnd_tmp);
} }
} }
...@@ -6991,43 +7177,43 @@ AbstractExternalFunctionNode::maxHelper(const function<int(expr_t)>& f) const ...@@ -6991,43 +7177,43 @@ AbstractExternalFunctionNode::maxHelper(const function<int(expr_t)>& f) const
int int
AbstractExternalFunctionNode::maxEndoLead() const AbstractExternalFunctionNode::maxEndoLead() const
{ {
return maxHelper([](expr_t e) { return e->maxEndoLead(); }); return maxHelper(&ExprNode::maxEndoLead);
} }
int int
AbstractExternalFunctionNode::maxExoLead() const AbstractExternalFunctionNode::maxExoLead() const
{ {
return maxHelper([](expr_t e) { return e->maxExoLead(); }); return maxHelper(&ExprNode::maxExoLead);
} }
int int
AbstractExternalFunctionNode::maxEndoLag() const AbstractExternalFunctionNode::maxEndoLag() const
{ {
return maxHelper([](expr_t e) { return e->maxEndoLag(); }); return maxHelper(&ExprNode::maxEndoLag);
} }
int int
AbstractExternalFunctionNode::maxExoLag() const AbstractExternalFunctionNode::maxExoLag() const
{ {
return maxHelper([](expr_t e) { return e->maxExoLag(); }); return maxHelper(&ExprNode::maxExoLag);
} }
int int
AbstractExternalFunctionNode::maxLead() const AbstractExternalFunctionNode::maxLead() const
{ {
return maxHelper([](expr_t e) { return e->maxLead(); }); return maxHelper(&ExprNode::maxLead);
} }
int int
AbstractExternalFunctionNode::maxLag() const AbstractExternalFunctionNode::maxLag() const
{ {
return maxHelper([](expr_t e) { return e->maxLag(); }); return maxHelper(&ExprNode::maxLag);
} }
int int
AbstractExternalFunctionNode::maxLagWithDiffsExpanded() const AbstractExternalFunctionNode::maxLagWithDiffsExpanded() const
{ {
return maxHelper([](expr_t e) { return e->maxLagWithDiffsExpanded(); }); return maxHelper(&ExprNode::maxLagWithDiffsExpanded);
} }
expr_t expr_t
...@@ -7165,7 +7351,7 @@ AbstractExternalFunctionNode::substituteUnaryOpNodes(const lag_equivalence_table ...@@ -7165,7 +7351,7 @@ AbstractExternalFunctionNode::substituteUnaryOpNodes(const lag_equivalence_table
int int
AbstractExternalFunctionNode::countDiffs() const AbstractExternalFunctionNode::countDiffs() const
{ {
return maxHelper([](expr_t e) { return e->countDiffs(); }); return maxHelper(&ExprNode::countDiffs);
} }
expr_t expr_t
...@@ -7300,7 +7486,7 @@ AbstractExternalFunctionNode::removeTrendLeadLag(const map<int, expr_t>& trend_s ...@@ -7300,7 +7486,7 @@ AbstractExternalFunctionNode::removeTrendLeadLag(const map<int, expr_t>& trend_s
bool bool
AbstractExternalFunctionNode::isInStaticForm() const AbstractExternalFunctionNode::isInStaticForm() const
{ {
return ranges::all_of(arguments, [](expr_t e) { return e->isInStaticForm(); }); return ranges::all_of(arguments, &ExprNode::isInStaticForm);
} }
bool bool
...@@ -7413,6 +7599,13 @@ AbstractExternalFunctionNode::substituteLogTransform(int orig_symb_id, int aux_s ...@@ -7413,6 +7599,13 @@ AbstractExternalFunctionNode::substituteLogTransform(int orig_symb_id, int aux_s
return recurseTransform(&ExprNode::substituteLogTransform, orig_symb_id, aux_symb_id); return recurseTransform(&ExprNode::substituteLogTransform, orig_symb_id, aux_symb_id);
} }
expr_t
AbstractExternalFunctionNode::substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
{
return recurseTransform(&ExprNode::substituteAggregationOperators, subst_table, neweqs);
}
expr_t expr_t
AbstractExternalFunctionNode::toStatic(DataTree& static_datatree) const AbstractExternalFunctionNode::toStatic(DataTree& static_datatree) const
{ {
...@@ -7696,7 +7889,6 @@ ExternalFunctionNode::writeJsonExternalFunctionOutput(vector<string>& efout, ...@@ -7696,7 +7889,6 @@ ExternalFunctionNode::writeJsonExternalFunctionOutput(vector<string>& efout,
void void
ExternalFunctionNode::computeXrefs(EquationInfo& ei) const ExternalFunctionNode::computeXrefs(EquationInfo& ei) const
{ {
vector<expr_t> dynamic_arguments;
for (auto argument : arguments) for (auto argument : arguments)
argument->computeXrefs(ei); argument->computeXrefs(ei);
} }
...@@ -7713,7 +7905,7 @@ ExternalFunctionNode::sameTefTermPredicate() const ...@@ -7713,7 +7905,7 @@ ExternalFunctionNode::sameTefTermPredicate() const
{ {
return [this](expr_t e) { return [this](expr_t e) {
auto e2 = dynamic_cast<ExternalFunctionNode*>(e); auto e2 = dynamic_cast<ExternalFunctionNode*>(e);
return (e2 != nullptr && e2->symb_id == symb_id && e2->arguments == arguments); return e2 != nullptr && e2->symb_id == symb_id && e2->arguments == arguments;
}; };
} }
...@@ -8040,7 +8232,6 @@ FirstDerivExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t>& ...@@ -8040,7 +8232,6 @@ FirstDerivExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t>&
void void
FirstDerivExternalFunctionNode::computeXrefs(EquationInfo& ei) const FirstDerivExternalFunctionNode::computeXrefs(EquationInfo& ei) const
{ {
vector<expr_t> dynamic_arguments;
for (auto argument : arguments) for (auto argument : arguments)
argument->computeXrefs(ei); argument->computeXrefs(ei);
} }
...@@ -8052,12 +8243,12 @@ FirstDerivExternalFunctionNode::sameTefTermPredicate() const ...@@ -8052,12 +8243,12 @@ FirstDerivExternalFunctionNode::sameTefTermPredicate() const
if (first_deriv_symb_id == symb_id) if (first_deriv_symb_id == symb_id)
return [this](expr_t e) { return [this](expr_t e) {
auto e2 = dynamic_cast<ExternalFunctionNode*>(e); auto e2 = dynamic_cast<ExternalFunctionNode*>(e);
return (e2 && e2->symb_id == symb_id && e2->arguments == arguments); return e2 && e2->symb_id == symb_id && e2->arguments == arguments;
}; };
else else
return [this](expr_t e) { return [this](expr_t e) {
auto e2 = dynamic_cast<FirstDerivExternalFunctionNode*>(e); auto e2 = dynamic_cast<FirstDerivExternalFunctionNode*>(e);
return (e2 && e2->symb_id == symb_id && e2->arguments == arguments); return e2 && e2->symb_id == symb_id && e2->arguments == arguments;
}; };
} }
...@@ -8319,7 +8510,6 @@ SecondDerivExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t> ...@@ -8319,7 +8510,6 @@ SecondDerivExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t>
void void
SecondDerivExternalFunctionNode::computeXrefs(EquationInfo& ei) const SecondDerivExternalFunctionNode::computeXrefs(EquationInfo& ei) const
{ {
vector<expr_t> dynamic_arguments;
for (auto argument : arguments) for (auto argument : arguments)
argument->computeXrefs(ei); argument->computeXrefs(ei);
} }
...@@ -8408,12 +8598,12 @@ SecondDerivExternalFunctionNode::sameTefTermPredicate() const ...@@ -8408,12 +8598,12 @@ SecondDerivExternalFunctionNode::sameTefTermPredicate() const
if (second_deriv_symb_id == symb_id) if (second_deriv_symb_id == symb_id)
return [this](expr_t e) { return [this](expr_t e) {
auto e2 = dynamic_cast<ExternalFunctionNode*>(e); auto e2 = dynamic_cast<ExternalFunctionNode*>(e);
return (e2 && e2->symb_id == symb_id && e2->arguments == arguments); return e2 && e2->symb_id == symb_id && e2->arguments == arguments;
}; };
else else
return [this](expr_t e) { return [this](expr_t e) {
auto e2 = dynamic_cast<SecondDerivExternalFunctionNode*>(e); auto e2 = dynamic_cast<SecondDerivExternalFunctionNode*>(e);
return (e2 && e2->symb_id == symb_id && e2->arguments == arguments); return e2 && e2->symb_id == symb_id && e2->arguments == arguments;
}; };
} }
...@@ -8774,6 +8964,13 @@ SubModelNode::substituteLogTransform([[maybe_unused]] int orig_symb_id, ...@@ -8774,6 +8964,13 @@ SubModelNode::substituteLogTransform([[maybe_unused]] int orig_symb_id,
return const_cast<SubModelNode*>(this); return const_cast<SubModelNode*>(this);
} }
expr_t
SubModelNode::substituteAggregationOperators([[maybe_unused]] subst_table_t& subst_table,
[[maybe_unused]] vector<BinaryOpNode*>& neweqs) const
{
return const_cast<SubModelNode*>(this);
}
VarExpectationNode::VarExpectationNode(DataTree& datatree_arg, int idx_arg, string model_name_arg) : VarExpectationNode::VarExpectationNode(DataTree& datatree_arg, int idx_arg, string model_name_arg) :
SubModelNode {datatree_arg, idx_arg, move(model_name_arg)} SubModelNode {datatree_arg, idx_arg, move(model_name_arg)}
{ {
...@@ -9292,9 +9489,9 @@ ExprNode::matchParamTimesTargetMinusVariable(int symb_id) const ...@@ -9292,9 +9489,9 @@ ExprNode::matchParamTimesTargetMinusVariable(int symb_id) const
auto& avi = datatree.symbol_table.getAuxVarInfo(target->symb_id); auto& avi = datatree.symbol_table.getAuxVarInfo(target->symb_id);
if (avi.type == AuxVarType::pacTargetNonstationary && target->lag == -1) if (avi.type == AuxVarType::pacTargetNonstationary && target->lag == -1)
return true; return true;
return (avi.type == AuxVarType::unaryOp && avi.unary_op == "log" && avi.orig_symb_id return avi.type == AuxVarType::unaryOp && avi.unary_op == "log" && avi.orig_symb_id
&& !datatree.symbol_table.isAuxiliaryVariable(*avi.orig_symb_id) && !datatree.symbol_table.isAuxiliaryVariable(*avi.orig_symb_id)
&& target->lag + avi.orig_lead_lag.value() == -1); && target->lag + avi.orig_lead_lag.value() == -1;
} }
else else
return target->lag == -1; return target->lag == -1;
...@@ -9373,13 +9570,14 @@ ExprNode::toString() const ...@@ -9373,13 +9570,14 @@ ExprNode::toString() const
} }
tuple<int, expr_t, expr_t> tuple<int, expr_t, expr_t>
ExprNode::matchComplementarityCondition() const ExprNode::matchComplementarityCondition(
[[maybe_unused]] const optional<int>& heterogeneity_dimension) const
{ {
throw MatchFailureException {"This expression is not an inequality"}; throw MatchFailureException {"This expression is not an inequality"};
} }
tuple<int, expr_t, expr_t> tuple<int, expr_t, expr_t>
BinaryOpNode::matchComplementarityCondition() const BinaryOpNode::matchComplementarityCondition(const optional<int>& heterogeneity_dimension) const
{ {
bool is_greater {[&] { bool is_greater {[&] {
switch (op_code) switch (op_code)
...@@ -9397,7 +9595,13 @@ BinaryOpNode::matchComplementarityCondition() const ...@@ -9397,7 +9595,13 @@ BinaryOpNode::matchComplementarityCondition() const
auto match_contemporaneous_endogenous = [&](expr_t e) -> optional<int> { auto match_contemporaneous_endogenous = [&](expr_t e) -> optional<int> {
auto* ve = dynamic_cast<VariableNode*>(e); auto* ve = dynamic_cast<VariableNode*>(e);
if (ve && ve->lag == 0 && datatree.symbol_table.getType(ve->symb_id) == SymbolType::endogenous) if (ve && ve->lag == 0
&& ((!heterogeneity_dimension
&& datatree.symbol_table.getType(ve->symb_id) == SymbolType::endogenous)
|| (heterogeneity_dimension
&& datatree.symbol_table.getType(ve->symb_id) == SymbolType::heterogeneousEndogenous
&& datatree.symbol_table.getHeterogeneityDimension(ve->symb_id)
== *heterogeneity_dimension)))
return ve->symb_id; return ve->symb_id;
else else
return nullopt; return nullopt;
...@@ -9434,11 +9638,11 @@ BinaryOpNode::matchComplementarityCondition() const ...@@ -9434,11 +9638,11 @@ BinaryOpNode::matchComplementarityCondition() const
|| (!is_greater || (!is_greater
&& (barg1->op_code == BinaryOpcode::less && (barg1->op_code == BinaryOpcode::less
|| barg1->op_code == BinaryOpcode::lessEqual))))) || barg1->op_code == BinaryOpcode::lessEqual)))))
throw MatchFailureException {"Complementarity condition does not have the right form"}; throw MatchFailureException {};
auto id = match_contemporaneous_endogenous(barg1->arg2); auto id = match_contemporaneous_endogenous(barg1->arg2);
if (!id) if (!id)
throw MatchFailureException {"Complementarity condition does not have the right form"}; throw MatchFailureException {};
check_bound_constant(barg1->arg1); check_bound_constant(barg1->arg1);
check_bound_constant(arg2); check_bound_constant(arg2);
......
/* /*
* Copyright © 2007-2024 Dynare Team * Copyright © 2007-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -283,7 +283,7 @@ protected: ...@@ -283,7 +283,7 @@ protected:
min_cost(bool is_matlab) min_cost(bool is_matlab)
{ {
return is_matlab ? min_cost_matlab : min_cost_c; return is_matlab ? min_cost_matlab : min_cost_c;
}; }
//! Initializes data member non_null_derivatives //! Initializes data member non_null_derivatives
virtual void prepareForDerivation() = 0; virtual void prepareForDerivation() = 0;
...@@ -572,38 +572,35 @@ public: ...@@ -572,38 +572,35 @@ public:
{ {
}; };
//! Returns the maximum lead of endogenous in this expression //! Returns the maximum lead of endogenous in this expression (not incl. heterogeneous endo)
/*! Always returns a non-negative value */ /*! Always returns a non-negative value */
[[nodiscard]] virtual int maxEndoLead() const = 0; [[nodiscard]] virtual int maxEndoLead() const = 0;
//! Returns the maximum lead of exogenous in this expression //! Returns the maximum lead of exogenous in this expression (not incl. heterogeneous exo)
/*! Always returns a non-negative value */ /*! Always returns a non-negative value */
[[nodiscard]] virtual int maxExoLead() const = 0; [[nodiscard]] virtual int maxExoLead() const = 0;
//! Returns the maximum lag of endogenous in this expression //! Returns the maximum lag of endogenous in this expression (not incl. heterogeneous endo)
/*! Always returns a non-negative value */ /*! Always returns a non-negative value */
[[nodiscard]] virtual int maxEndoLag() const = 0; [[nodiscard]] virtual int maxEndoLag() const = 0;
//! Returns the maximum lag of exogenous in this expression //! Returns the maximum lag of exogenous in this expression (not incl. heterogeneous exo)
/*! Always returns a non-negative value */ /*! Always returns a non-negative value */
[[nodiscard]] virtual int maxExoLag() const = 0; [[nodiscard]] virtual int maxExoLag() const = 0;
//! Returns the maximum lead of endo/exo/exodet in this expression /* Returns the maximum lead of endo/exo/exodet in this expression (including heterogeneous
/*! A negative value means that the expression contains only lagged endo/exo). A negative value means that the expression contains only lagged variables. A value
variables. A value of numeric_limits<int>::min() means that there is of numeric_limits<int>::min() means that there is no variable. */
no variable. */
[[nodiscard]] virtual int maxLead() const = 0; [[nodiscard]] virtual int maxLead() const = 0;
//! Returns the maximum lag of endo/exo/exodet in this expression /* Returns the maximum lag of endo/exo/exodet in this expression (including heterogeneous
/*! A negative value means that the expression contains only leaded endo/exo). A negative value means that the expression contains only leaded variables. A value
variables. A value of numeric_limits<int>::min() means that there is of numeric_limits<int>::min() means that there is no variable. */
no variable. */
[[nodiscard]] virtual int maxLag() const = 0; [[nodiscard]] virtual int maxLag() const = 0;
//! Returns the maximum lag of endo/exo/exodet, as if diffs were expanded /* Returns the maximum lag of endo/exo/exodet (including heterogeneous endo/exo), as if diffs were
/*! This function behaves as maxLag(), except that it treats diff() expanded. This function behaves as maxLag(), except that it treats diff() differently. For
differently. For e.g., on diff(diff(x(-1))), maxLag() returns 1 while e.g., on diff(diff(x(-1))), maxLag() returns 1 while maxLagWithDiffsExpanded() returns 3. */
maxLagWithDiffsExpanded() returns 3. */
[[nodiscard]] virtual int maxLagWithDiffsExpanded() const = 0; [[nodiscard]] virtual int maxLagWithDiffsExpanded() const = 0;
[[nodiscard]] virtual expr_t undiff() const = 0; [[nodiscard]] virtual expr_t undiff() const = 0;
...@@ -946,7 +943,15 @@ public: ...@@ -946,7 +943,15 @@ public:
/* Matches an expression that constitutes a complementarity condition. /* Matches an expression that constitutes a complementarity condition.
If successful, returns a triplet (endo_symb_id, lower_bound, upper_bound). If successful, returns a triplet (endo_symb_id, lower_bound, upper_bound).
Otherwise, throws a MatchFailureException. */ Otherwise, throws a MatchFailureException. */
[[nodiscard]] virtual tuple<int, expr_t, expr_t> matchComplementarityCondition() const; [[nodiscard]] virtual tuple<int, expr_t, expr_t>
matchComplementarityCondition(const optional<int>& heterogeneity_dimension = nullopt) const;
/* Replaces aggregation operators (e.g. SUM()) by new auxiliary variables.
Also declares those aggregation operators in the HeterogeneityTable, so as to
compute their index in the dedicated vector in argument of the dynamic/static files. */
[[nodiscard]] virtual expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
}; };
//! Object used to compare two nodes (using their indexes) //! Object used to compare two nodes (using their indexes)
...@@ -1058,6 +1063,8 @@ public: ...@@ -1058,6 +1063,8 @@ public:
= "") const override; = "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override; [[nodiscard]] bool isParamTimesEndogExpr() const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) 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 //! Symbol or variable node
...@@ -1165,6 +1172,8 @@ public: ...@@ -1165,6 +1172,8 @@ public:
vector<int>& powers) const override; vector<int>& powers) const override;
[[nodiscard]] pair<int, expr_t> matchEndogenousTimesConstant() 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 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 //! Unary operator node
...@@ -1312,6 +1321,8 @@ public: ...@@ -1312,6 +1321,8 @@ public:
[[nodiscard]] bool isParamTimesEndogExpr() const override; [[nodiscard]] bool isParamTimesEndogExpr() const override;
void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign) 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 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 //! Binary operator node
...@@ -1507,7 +1518,11 @@ public: ...@@ -1507,7 +1518,11 @@ public:
vector<int>& powers) const override; vector<int>& powers) const override;
[[nodiscard]] pair<int, expr_t> matchEndogenousTimesConstant() 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 substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
[[nodiscard]] tuple<int, expr_t, expr_t> matchComplementarityCondition() const override; [[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] tuple<int, expr_t, expr_t>
matchComplementarityCondition(const optional<int>& heterogeneity_dimension
= nullopt) const override;
}; };
//! Trinary operator node //! Trinary operator node
...@@ -1651,6 +1666,8 @@ public: ...@@ -1651,6 +1666,8 @@ public:
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name [[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override; = "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() 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; [[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
}; };
...@@ -1826,6 +1843,8 @@ public: ...@@ -1826,6 +1843,8 @@ public:
= "") const override; = "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override; [[nodiscard]] bool isParamTimesEndogExpr() const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) 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 class ExternalFunctionNode : public AbstractExternalFunctionNode
...@@ -2028,6 +2047,8 @@ public: ...@@ -2028,6 +2047,8 @@ public:
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override; expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) 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 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: protected:
void prepareForDerivation() override; void prepareForDerivation() override;
......
/*
* 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);
}
}
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;
}