Compare commits

...

10 Commits

Author SHA1 Message Date
Sébastien Villemot 5d0ad3f666
include_eqs/exclude_eqs: fix equation number in error message 2021-12-13 16:47:35 +01:00
Sébastien Villemot f44155d43a
Fix logic of include_eqs in the presence of [static]/[dynamic] equations
In a model with [static]/[dynamic] equations, if the user was using include_eqs
with a list of equations that does *not* contain equations marked
[static]/[dynamic], then the call to ModelTree::includeExcludeEquations(…,
static_equations=true) would have an empty list of equation tags (as stored
in tag_eqns).

The right behaviour in this case is to exclude all static equations. However,
the code would exclude none, and this would disrupt the equilibrium between
[static] and [dynamic] equations (since all [dynamic] equations were excluded
by the other call to the same method).

The fix consists in removing the shortcut that returns from the method if
tag_eqns is empty.

(cherry picked from commit a73b0d911a)
2021-12-13 12:19:16 +01:00
Sébastien Villemot 4deb397d18
Bump version number 2021-12-08 14:35:47 +01:00
Johannes Pfeifer 1341963d32
occbin_write_regimes: add option to select type
(cherry picked from commit 164e2debdc)
2021-12-07 18:13:25 +01:00
Sébastien Villemot 7fff5c4c30
Occbin: use element-by-element multiply, divide and power in occbin_difference.m
This file operates on vectors.

Ref. dynare#1826

(cherry picked from commit 81abea042b)
2021-12-07 18:11:13 +01:00
Sébastien Villemot f257b96060
When looking for unused endos/exos, also search in equations marked [static]
(cherry picked from commit fe974c4c31)
2021-12-07 11:37:27 +01:00
Sébastien Villemot cac24dad7e
Substitute model-local variables in equations marked [static]
(cherry picked from commit 8d4cab6fe3)
2021-12-07 11:37:27 +01:00
Sébastien Villemot ced586febf
Symbolic detrending engine: correctly handle equations marked [static]
Incidentally, this also fixes a detrending bug in the Occbin engine (since the
latter internally generates a [static] equation).

Ref. dynare#1827

By the way, perform a small code simplification.

(cherry picked from commit 7b8fc8edb7)
2021-12-07 11:37:27 +01:00
Sébastien Villemot bdbafdc34c
No longer consider an equation of the form “x(+1) = 0” as defining x to be a constant
Fix this by restricting the detection of constant equations to those where the
variable appears without a lead or lag.

Closes: #83
(cherry picked from commit 1cc512962c)
2021-11-22 10:23:57 +01:00
Sébastien Villemot 008a0dbb9e
With nostrict, really ignore unused endogenous in initval/endval/histval
Closes: #82
(cherry picked from commit b51f122e59)
2021-11-22 10:23:57 +01:00
7 changed files with 69 additions and 25 deletions

View File

@ -18,7 +18,7 @@ dnl You should have received a copy of the GNU General Public License
dnl along with Dynare. If not, see <https://www.gnu.org/licenses/>.
AC_PREREQ([2.62])
AC_INIT([dynare-preprocessor], [4.7.0])
AC_INIT([dynare-preprocessor], [5.0])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR([src/DynareMain.cc])
AM_INIT_AUTOMAKE([1.11 -Wall -Wno-portability foreign no-dist-gzip dist-xz tar-pax])

View File

@ -995,7 +995,7 @@ void
OccbinWriteRegimesStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
options_list.writeOutput(output, "options_.occbin");
output << "occbin.write_regimes_to_xls(oo_.occbin.regime_history, M_, options_);" << endl;
output << "occbin.write_regimes_to_xls(oo_.occbin, M_, options_);" << endl;
}
void

View File

@ -4923,6 +4923,8 @@ DynamicModel::findUnusedEndogenous()
set<int> usedEndo, unusedEndo;
for (auto &equation : equations)
equation->collectVariables(SymbolType::endogenous, usedEndo);
for (auto &equation : static_only_equations)
equation->collectVariables(SymbolType::endogenous, usedEndo);
set<int> allEndo = symbol_table.getEndogenous();
set_difference(allEndo.begin(), allEndo.end(),
usedEndo.begin(), usedEndo.end(),
@ -4936,6 +4938,8 @@ DynamicModel::findUnusedExogenous()
set<int> usedExo, unusedExo, unobservedExo;
for (auto &equation : equations)
equation->collectVariables(SymbolType::exogenous, usedExo);
for (auto &equation : static_only_equations)
equation->collectVariables(SymbolType::exogenous, usedExo);
set<int> observedExo = symbol_table.getObservedExogenous();
set<int> allExo = symbol_table.getExogenous();
set_difference(allExo.begin(), allExo.end(),
@ -5677,6 +5681,9 @@ DynamicModel::substituteModelLocalVariables()
for (auto &equation : equations)
equation = dynamic_cast<BinaryOpNode *>(equation->substituteModelLocalVariables());
for (auto &equation : static_only_equations)
equation = dynamic_cast<BinaryOpNode *>(equation->substituteModelLocalVariables());
/* We cant clear local_variables_table at this point, because in case of
ramsey_policy, the original model is saved via DynamicModel::operator=()
before computing the FOC. But since DataTree::operator=() clones all
@ -5888,18 +5895,28 @@ DynamicModel::detrendEquations()
// We go backwards in the list of trend_vars, to deal correctly with I(2) processes
for (auto it = nonstationary_symbols_map.crbegin();
it != nonstationary_symbols_map.crend(); ++it)
for (auto &equation : equations)
{
auto substeq = dynamic_cast<BinaryOpNode *>(equation->detrend(it->first, it->second.first, it->second.second));
assert(substeq);
equation = dynamic_cast<BinaryOpNode *>(substeq);
}
{
for (auto &equation : equations)
{
equation = dynamic_cast<BinaryOpNode *>(equation->detrend(it->first, it->second.first, it->second.second));
assert(equation);
}
for (auto &equation : static_only_equations)
{
equation = dynamic_cast<BinaryOpNode *>(equation->detrend(it->first, it->second.first, it->second.second));
assert(equation);
}
}
for (auto &equation : equations)
{
auto substeq = dynamic_cast<BinaryOpNode *>(equation->removeTrendLeadLag(trend_symbols_map));
assert(substeq);
equation = dynamic_cast<BinaryOpNode *>(substeq);
equation = dynamic_cast<BinaryOpNode *>(equation->removeTrendLeadLag(trend_symbols_map));
assert(equation);
}
for (auto &equation : static_only_equations)
{
equation = dynamic_cast<BinaryOpNode *>(equation->removeTrendLeadLag(trend_symbols_map));
assert(equation);
}
}
@ -5908,9 +5925,13 @@ DynamicModel::removeTrendVariableFromEquations()
{
for (auto &equation : equations)
{
auto substeq = dynamic_cast<BinaryOpNode *>(equation->replaceTrendVar());
assert(substeq);
equation = dynamic_cast<BinaryOpNode *>(substeq);
equation = dynamic_cast<BinaryOpNode *>(equation->replaceTrendVar());
assert(equation);
}
for (auto &equation : static_only_equations)
{
equation = dynamic_cast<BinaryOpNode *>(equation->replaceTrendVar());
assert(equation);
}
}

View File

@ -2521,6 +2521,8 @@ occbin_write_regimes_options_list : occbin_write_regimes_option COMMA occbin_wri
occbin_write_regimes_option : o_occbin_write_regimes_periods
| o_occbin_write_regimes_filename
| o_occbin_write_regimes_smoother
| o_occbin_write_regimes_simul
;
occbin_graph : OCCBIN_GRAPH ';'
@ -4066,6 +4068,8 @@ o_occbin_write_regimes_periods : PERIODS EQUAL vec_int
| PERIODS EQUAL vec_int_number
{ driver.option_vec_int("write_regimes.periods", $3); }
o_occbin_write_regimes_filename : FILENAME EQUAL filename { driver.option_str("write_regimes.filename", $3); };
o_occbin_write_regimes_smoother : SMOOTHER { driver.option_str("write_regimes.type", "smoother"); };
o_occbin_write_regimes_simul : SIMUL { driver.option_str("write_regimes.type", "simul"); };
// Some options to "occbin_graph"
o_occbin_graph_noconstant : NOCONSTANT { driver.option_num("graph.steady_state", "false"); };

View File

@ -4475,15 +4475,25 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case BinaryOpcode::times:
if (isLatexOutput(output_type))
output << R"(\, )";
else if (output_type == ExprNodeOutputType::occbinDifferenceFile)
output << ".*"; // This file operates on vectors, see dynare#1826
else
output << "*";
break;
case BinaryOpcode::divide:
if (!isLatexOutput(output_type))
output << "/";
{
if (output_type == ExprNodeOutputType::occbinDifferenceFile)
output << "./"; // This file operates on vectors, see dynare#1826
else
output << "/";
}
break;
case BinaryOpcode::power:
output << "^";
if (output_type == ExprNodeOutputType::occbinDifferenceFile)
output << ".^"; // This file operates on vectors, see dynare#1826
else
output << "^";
break;
case BinaryOpcode::less:
output << "<";
@ -5469,10 +5479,13 @@ BinaryOpNode::findConstantEquations(map<VariableNode *, NumConstNode *> &table)
{
if (op_code == BinaryOpcode::equal)
{
if (dynamic_cast<VariableNode *>(arg1) && dynamic_cast<NumConstNode *>(arg2))
table[dynamic_cast<VariableNode *>(arg1)] = dynamic_cast<NumConstNode *>(arg2);
else if (dynamic_cast<VariableNode *>(arg2) && dynamic_cast<NumConstNode *>(arg1))
table[dynamic_cast<VariableNode *>(arg2)] = dynamic_cast<NumConstNode *>(arg1);
// The variable must be contemporaneous (see #83)
if (auto varg1 = dynamic_cast<VariableNode *>(arg1);
varg1 && varg1->lag == 0 && dynamic_cast<NumConstNode *>(arg2))
table[varg1] = dynamic_cast<NumConstNode *>(arg2);
else if (auto varg2 = dynamic_cast<VariableNode *>(arg2);
varg2 && varg2->lag == 0 && dynamic_cast<NumConstNode *>(arg1))
table[varg2] = dynamic_cast<NumConstNode *>(arg1);
}
}

View File

@ -1566,9 +1566,6 @@ ModelTree::includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_
else
++it;
if (tag_eqns.empty())
return excluded_vars;
set<int> eqns;
if (exclude_eqs)
eqns = tag_eqns;
@ -1594,7 +1591,7 @@ ModelTree::includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_
excluded_vars.push_back(result.begin()->first);
else
{
cerr << "ERROR: Equation " << i
cerr << "ERROR: Equation " << i+1
<< " has been excluded but does not have a single variable on LHS or `endogenous` tag" << endl;
exit(EXIT_FAILURE);
}

View File

@ -132,6 +132,9 @@ InitOrEndValStatement::writeInitValues(ostream &output) const
{
for (auto [symb_id, value] : init_values)
{
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
SymbolType type = symbol_table.getType(symb_id);
int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
@ -167,9 +170,11 @@ InitOrEndValStatement::writeJsonInitValues(ostream &output) const
for (auto it = init_values.begin();
it != init_values.end(); ++it)
{
auto [symb_id, value] = *it;
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
if (it != init_values.begin())
output << ", ";
auto [symb_id, value] = *it;
output << R"({"name": ")" << symbol_table.getName(symb_id) << R"(", )" << R"("value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
@ -363,6 +368,8 @@ HistValStatement::writeOutput(ostream &output, const string &basename, bool mini
for (const auto &[key, value] : hist_values)
{
auto [symb_id, lag] = key;
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
output << "M_.histval_dseries{'" << symbol_table.getName(symb_id) << "'}(dates('" << lag << "Y'))=";
value->writeOutput(output);
@ -389,6 +396,8 @@ HistValStatement::writeJsonOutput(ostream &output) const
it != hist_values.end(); ++it)
{
auto [symb_id, lag] = it->first;
if (symbol_table.getType(symb_id) == SymbolType::unusedEndogenous) // See #82
continue;
if (it != hist_values.begin())
output << ", ";
output << R"({ "name": ")" << symbol_table.getName(symb_id) << R"(")"