rework equation tags
Create new EquationTags class to simplify use of equation tags throughout the code and avoid repeated code issue #38issue#70
parent
28b98c7c0e
commit
7371558321
|
@ -103,7 +103,6 @@ DynamicModel::DynamicModel(const DynamicModel &m) :
|
|||
balanced_growth_test_tol{m.balanced_growth_test_tol},
|
||||
static_only_equations_lineno{m.static_only_equations_lineno},
|
||||
static_only_equations_equation_tags{m.static_only_equations_equation_tags},
|
||||
static_only_equation_tags_xref{m.static_only_equation_tags_xref},
|
||||
deriv_id_table{m.deriv_id_table},
|
||||
inv_deriv_id_table{m.inv_deriv_id_table},
|
||||
dyn_jacobian_cols_table{m.dyn_jacobian_cols_table},
|
||||
|
@ -166,7 +165,6 @@ DynamicModel::operator=(const DynamicModel &m)
|
|||
|
||||
static_only_equations_lineno = m.static_only_equations_lineno;
|
||||
static_only_equations_equation_tags = m.static_only_equations_equation_tags;
|
||||
static_only_equation_tags_xref = m.static_only_equation_tags_xref;
|
||||
deriv_id_table = m.deriv_id_table;
|
||||
inv_deriv_id_table = m.inv_deriv_id_table;
|
||||
dyn_jacobian_cols_table = m.dyn_jacobian_cols_table;
|
||||
|
@ -2907,7 +2905,8 @@ DynamicModel::writeDynamicJacobianNonZeroElts(const string &basename) const
|
|||
}
|
||||
|
||||
void
|
||||
DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_eq_tags, set<pair<string, string>> &eq_tag_set, bool exclude_eqs)
|
||||
DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_eq_tags,
|
||||
set<pair<string, string>> &eq_tag_set, bool exclude_eqs)
|
||||
{
|
||||
string tags;
|
||||
if (filesystem::exists(inc_exc_eq_tags))
|
||||
|
@ -3010,24 +3009,13 @@ DynamicModel::includeExcludeEquations(const string &eqs, bool exclude_eqs)
|
|||
vector<int> excluded_vars
|
||||
= ModelTree::includeExcludeEquations(eq_tag_set, exclude_eqs,
|
||||
equations, equations_lineno,
|
||||
equation_tags, equation_tags_xref, false);
|
||||
equation_tags, false);
|
||||
|
||||
// `static_only_equation_tags` is `vector<vector<pair<string, string>>>`
|
||||
// while `equation_tags` is `vector<pair<int, pair<string, string>>>`
|
||||
// so convert former structure to latter to conform with function call
|
||||
int n = 0;
|
||||
vector<pair<int, pair<string, string>>> tmp_static_only_equation_tags;
|
||||
for (auto &eqn_tags : static_only_equations_equation_tags)
|
||||
{
|
||||
for (auto &eqn_tag : eqn_tags)
|
||||
tmp_static_only_equation_tags.emplace_back(make_pair(n, eqn_tag));
|
||||
n++;
|
||||
}
|
||||
// Ignore output because variables are not excluded when equations marked 'static' are excluded
|
||||
ModelTree::includeExcludeEquations(eq_tag_set, exclude_eqs,
|
||||
static_only_equations, static_only_equations_lineno,
|
||||
tmp_static_only_equation_tags,
|
||||
static_only_equation_tags_xref, true);
|
||||
static_only_equations_equation_tags, true);
|
||||
|
||||
if (!eq_tag_set.empty())
|
||||
{
|
||||
cerr << "ERROR: " << (exclude_eqs ? "exclude_eqs" : "include_eqs") << ": The equations specified by `";
|
||||
|
@ -3045,17 +3033,6 @@ DynamicModel::includeExcludeEquations(const string &eqs, bool exclude_eqs)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// convert back static equation info
|
||||
if (static_only_equations.empty())
|
||||
static_only_equations_equation_tags.clear();
|
||||
else
|
||||
{
|
||||
static_only_equations_equation_tags.resize(static_only_equations.size());
|
||||
fill(static_only_equations_equation_tags.begin(), static_only_equations_equation_tags.end(), vector<pair<string, string>>());
|
||||
for (auto &it : tmp_static_only_equation_tags)
|
||||
static_only_equations_equation_tags.at(it.first).emplace_back(it.second);
|
||||
}
|
||||
|
||||
// Collect list of used variables in updated list of equations
|
||||
set<pair<int, int>> eqn_vars;
|
||||
for (const auto &eqn : equations)
|
||||
|
@ -3180,42 +3157,10 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de
|
|||
}
|
||||
|
||||
// Write equation tags
|
||||
if (julia)
|
||||
{
|
||||
output << modstruct << "equation_tags = [" << endl;
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
output << " EquationTag("
|
||||
<< equation_tag.first + 1 << R"( , ")"
|
||||
<< equation_tag.second.first << R"(" , ")"
|
||||
<< equation_tag.second.second << R"("))" << endl;
|
||||
output << " ]" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
output << modstruct << "equations_tags = {" << endl;
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
output << " " << equation_tag.first + 1 << " , '"
|
||||
<< equation_tag.second.first << "' , '"
|
||||
<< equation_tag.second.second << "' ;" << endl;
|
||||
output << "};" << endl;
|
||||
}
|
||||
equation_tags.writeOutput(output, modstruct, julia);
|
||||
|
||||
// Write Occbin tags
|
||||
map<int, vector<pair<string, string>>> occbin_options;
|
||||
for (const auto &[eqn, tag] : equation_tags)
|
||||
if (tag.first == "pswitch"
|
||||
|| tag.first == "bind"
|
||||
|| tag.first == "relax"
|
||||
|| tag.first == "pcrit")
|
||||
occbin_options[eqn].push_back(tag);
|
||||
|
||||
int idx = 0;
|
||||
for (const auto &[eqn, tags] : occbin_options)
|
||||
{
|
||||
idx++;
|
||||
for (const auto &[tag_name, tag_value] : tags)
|
||||
output << "M_.occbin.constraint(" << idx << ")." << tag_name << " = '" << tag_value << "';" << endl;
|
||||
}
|
||||
equation_tags.writeOccbinOutput(output, modstruct, julia);
|
||||
|
||||
// Write mapping for variables and equations they are present in
|
||||
for (const auto &variable : variableMapping)
|
||||
|
@ -4071,16 +4016,8 @@ DynamicModel::fillVarModelTable() const
|
|||
|
||||
for (const auto &eqtag : it.second)
|
||||
{
|
||||
int eqn = -1;
|
||||
set<pair<int, int>> lhs_set, lhs_tmp_set, rhs_set;
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
if (equation_tag.second.first == "name"
|
||||
&& equation_tag.second.second == eqtag)
|
||||
{
|
||||
eqn = equation_tag.first;
|
||||
break;
|
||||
}
|
||||
|
||||
int eqn = equation_tags.getEqnByTag("name", eqtag);
|
||||
if (eqn == -1)
|
||||
{
|
||||
cerr << "ERROR: equation tag '" << eqtag << "' not found" << endl;
|
||||
|
@ -4243,15 +4180,7 @@ DynamicModel::fillTrendComponentModelTable() const
|
|||
vector<int> trend_eqnumber;
|
||||
for (const auto &eqtag : it.second)
|
||||
{
|
||||
int eqn = -1;
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
if (equation_tag.second.first == "name"
|
||||
&& equation_tag.second.second == eqtag)
|
||||
{
|
||||
eqn = equation_tag.first;
|
||||
break;
|
||||
}
|
||||
|
||||
int eqn = equation_tags.getEqnByTag("name", eqtag);
|
||||
if (eqn == -1)
|
||||
{
|
||||
cerr << "ERROR: trend equation tag '" << eqtag << "' not found" << endl;
|
||||
|
@ -4270,16 +4199,8 @@ DynamicModel::fillTrendComponentModelTable() const
|
|||
|
||||
for (const auto &eqtag : it.second)
|
||||
{
|
||||
int eqn = -1;
|
||||
set<pair<int, int>> lhs_set, lhs_tmp_set, rhs_set;
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
if (equation_tag.second.first == "name"
|
||||
&& equation_tag.second.second == eqtag)
|
||||
{
|
||||
eqn = equation_tag.first;
|
||||
break;
|
||||
}
|
||||
|
||||
int eqn = equation_tags.getEqnByTag("name", eqtag);
|
||||
if (eqn == -1)
|
||||
{
|
||||
cerr << "ERROR: equation tag '" << eqtag << "' not found" << endl;
|
||||
|
@ -4636,14 +4557,7 @@ DynamicModel::walkPacParameters(const string &name)
|
|||
}
|
||||
}
|
||||
|
||||
string eqtag;
|
||||
for (auto &tag : equation_tags)
|
||||
if (tag.first == (&equation - &equations[0]))
|
||||
if (tag.second.first == "name")
|
||||
{
|
||||
eqtag = tag.second.second;
|
||||
break;
|
||||
}
|
||||
string eqtag = equation_tags.getTagValueByEqnAndKey(&equation - &equations[0], "name");
|
||||
if (eqtag.empty())
|
||||
{
|
||||
cerr << "Every equation with a pac expectation must have been assigned an equation tag name" << endl;
|
||||
|
@ -4686,14 +4600,7 @@ DynamicModel::getPacMaxLag(const string &pac_model_name, map<pair<string, string
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
string eqtag;
|
||||
for (auto &tag : equation_tags)
|
||||
if (tag.first == (&equation - &equations[0]))
|
||||
if (tag.second.first == "name")
|
||||
{
|
||||
eqtag = tag.second.second;
|
||||
break;
|
||||
}
|
||||
string eqtag = equation_tags.getTagValueByEqnAndKey(&equation - &equations[0], "name");
|
||||
string eq = eqtag_and_lag[{pac_model_name, eqtag}].first;
|
||||
eqtag_and_lag[{pac_model_name, eqtag}] = {eq, equation->PacMaxLag(endogs.begin()->first)};
|
||||
}
|
||||
|
@ -4731,15 +4638,7 @@ DynamicModel::declarePacModelConsistentExpectationEndogs(const string &name)
|
|||
for (auto &equation : equations)
|
||||
if (equation->containsPacExpectation())
|
||||
{
|
||||
string eqtag;
|
||||
for (auto &tag : equation_tags)
|
||||
if (tag.first == (&equation - &equations[0]))
|
||||
if (tag.second.first == "name")
|
||||
{
|
||||
eqtag = tag.second.second;
|
||||
break;
|
||||
}
|
||||
if (eqtag.empty())
|
||||
if (!equation_tags.exists(&equation - &equations[0], "name"))
|
||||
{
|
||||
cerr << "Every equation with a pac expectation must have been assigned an equation tag name" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -4934,15 +4833,13 @@ DynamicModel::substitutePacExpectation(const string &pac_model_name)
|
|||
for (auto &it : pac_expectation_substitution)
|
||||
if (it.first.first == pac_model_name)
|
||||
for (auto &equation : equations)
|
||||
for (auto & [tagged_eq, tag_pair] : equation_tags)
|
||||
if (tagged_eq == (&equation - &equations[0])
|
||||
&& tag_pair.first == "name" && tag_pair.second == it.first.second)
|
||||
{
|
||||
auto substeq = dynamic_cast<BinaryOpNode *>(equation->substitutePacExpectation(pac_model_name, it.second));
|
||||
assert(substeq);
|
||||
equation = substeq;
|
||||
break;
|
||||
}
|
||||
if (equation_tags.exists(&equation - &equations[0], "name", it.first.second))
|
||||
{
|
||||
auto substeq = dynamic_cast<BinaryOpNode *>(equation->substitutePacExpectation(pac_model_name, it.second));
|
||||
assert(substeq);
|
||||
equation = substeq;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5536,7 +5433,6 @@ DynamicModel::clearEquations()
|
|||
equations.clear();
|
||||
equations_lineno.clear();
|
||||
equation_tags.clear();
|
||||
equation_tags_xref.clear();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5548,7 +5444,6 @@ DynamicModel::replaceMyEquations(DynamicModel &dynamic_model) const
|
|||
dynamic_model.addEquation(equations[i]->clone(dynamic_model), equations_lineno[i]);
|
||||
|
||||
dynamic_model.equation_tags = equation_tags;
|
||||
dynamic_model.equation_tags_xref = equation_tags_xref;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5623,7 +5518,7 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model)
|
|||
(i.e. a FOC identical to an equation of the original model) */
|
||||
vector<expr_t> neweqs;
|
||||
vector<int> neweqs_lineno;
|
||||
map<int, vector<pair<string, string>>> neweqs_tags;
|
||||
map<int, map<string, string>> neweqs_tags;
|
||||
for (auto &[symb_id_and_lag, deriv_id] : deriv_id_table)
|
||||
{
|
||||
auto &[symb_id, lag] = symb_id_and_lag;
|
||||
|
@ -5635,10 +5530,10 @@ DynamicModel::computeRamseyPolicyFOCs(const StaticModel &static_model)
|
|||
{
|
||||
// This is a derivative w.r.t. a Lagrange multiplier
|
||||
neweqs_lineno.push_back(old_equations_lineno[i]);
|
||||
vector<pair<string, string>> tags;
|
||||
for (auto &[j, tagpair] : old_equation_tags)
|
||||
if (j == i)
|
||||
tags.emplace_back(tagpair);
|
||||
map<string, string> tags;
|
||||
auto tmp = old_equation_tags.getTagsByEqn(i);
|
||||
for (const auto &[key, value] : tmp)
|
||||
tags[key] = value;
|
||||
neweqs_tags[neweqs.size()-1] = tags;
|
||||
}
|
||||
else
|
||||
|
@ -5686,30 +5581,20 @@ DynamicModel::createVariableMapping(int orig_eq_nbr)
|
|||
void
|
||||
DynamicModel::expandEqTags()
|
||||
{
|
||||
set<int> existing_tags;
|
||||
for (const auto &eqn : equation_tags)
|
||||
if (eqn.second.first == "name")
|
||||
existing_tags.insert(eqn.first);
|
||||
|
||||
set<int> existing_tags = equation_tags.getEqnsByKey("name");
|
||||
for (int eq = 0; eq < static_cast<int>(equations.size()); eq++)
|
||||
if (existing_tags.find(eq) == existing_tags.end())
|
||||
if (auto lhs_expr = dynamic_cast<VariableNode *>(equations[eq]->arg1); lhs_expr && equation_tags_xref.find({ "name", symbol_table.getName(lhs_expr->symb_id)}) == equation_tags_xref.end())
|
||||
{
|
||||
equation_tags.emplace_back(eq, pair("name", symbol_table.getName(lhs_expr->symb_id)));
|
||||
equation_tags_xref.emplace(pair("name", symbol_table.getName(lhs_expr->symb_id)), eq);
|
||||
}
|
||||
else if (equation_tags_xref.find({ "name", to_string(eq+1) }) == equation_tags_xref.end())
|
||||
{
|
||||
equation_tags.emplace_back(eq, pair("name", to_string(eq+1)));
|
||||
equation_tags_xref.emplace(pair("name", to_string(eq+1)), eq);
|
||||
}
|
||||
if (auto lhs_expr = dynamic_cast<VariableNode *>(equations[eq]->arg1);
|
||||
lhs_expr
|
||||
&& !equation_tags.exists("name", symbol_table.getName(lhs_expr->symb_id)))
|
||||
equation_tags.add(eq, "name", symbol_table.getName(lhs_expr->symb_id));
|
||||
else if (!equation_tags.exists("name", to_string(eq+1)))
|
||||
equation_tags.add(eq, "name", to_string(eq+1));
|
||||
else
|
||||
{
|
||||
cerr << "Error creating default equation tag: cannot assign default tag to equation number " << eq+1 << " because it is already in use" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sort(equation_tags.begin(), equation_tags.end());
|
||||
}
|
||||
|
||||
set<int>
|
||||
|
@ -6459,39 +6344,32 @@ DynamicModel::substituteAdl()
|
|||
equation = dynamic_cast<BinaryOpNode *>(equation->substituteAdl());
|
||||
}
|
||||
|
||||
vector<int>
|
||||
set<int>
|
||||
DynamicModel::getEquationNumbersFromTags(const set<string> &eqtags) const
|
||||
{
|
||||
vector<int> eqnumbers;
|
||||
set<int> eqnumbers;
|
||||
for (auto &eqtag : eqtags)
|
||||
{
|
||||
bool found = false;
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
if (equation_tag.second.first == "name"
|
||||
&& equation_tag.second.second == eqtag)
|
||||
{
|
||||
found = true;
|
||||
eqnumbers.push_back(equation_tag.first);
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
set<int> tmp = equation_tags.getEqnsByTag("name", eqtag);
|
||||
if (tmp.empty())
|
||||
{
|
||||
cerr << "ERROR: looking for equation tag " << eqtag << " failed." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
eqnumbers.insert(tmp.begin(), tmp.end());
|
||||
}
|
||||
return eqnumbers;
|
||||
}
|
||||
|
||||
void
|
||||
DynamicModel::findPacExpectationEquationNumbers(vector<int> &eqnumbers) const
|
||||
DynamicModel::findPacExpectationEquationNumbers(set<int> &eqnumbers) const
|
||||
{
|
||||
int i = 0;
|
||||
for (auto &equation : equations)
|
||||
{
|
||||
if (equation->containsPacExpectation()
|
||||
&& find(eqnumbers.begin(), eqnumbers.end(), i) == eqnumbers.end())
|
||||
eqnumbers.push_back(i);
|
||||
eqnumbers.insert(i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -6507,9 +6385,10 @@ DynamicModel::substituteUnaryOps()
|
|||
pair<lag_equivalence_table_t, ExprNode::subst_table_t>
|
||||
DynamicModel::substituteUnaryOps(const set<string> &var_model_eqtags)
|
||||
{
|
||||
vector<int> eqnumbers = getEquationNumbersFromTags(var_model_eqtags);
|
||||
set<int> eqnumbers = getEquationNumbersFromTags(var_model_eqtags);
|
||||
findPacExpectationEquationNumbers(eqnumbers);
|
||||
return substituteUnaryOps(eqnumbers);
|
||||
vector<int> eqnumbers_vec(eqnumbers.begin(), eqnumbers.end());
|
||||
return substituteUnaryOps(eqnumbers_vec);
|
||||
}
|
||||
|
||||
pair<lag_equivalence_table_t, ExprNode::subst_table_t>
|
||||
|
@ -6751,21 +6630,14 @@ DynamicModel::isModelLocalVariableUsed() const
|
|||
}
|
||||
|
||||
void
|
||||
DynamicModel::addStaticOnlyEquation(expr_t eq, int lineno, const vector<pair<string, string>> &eq_tags)
|
||||
DynamicModel::addStaticOnlyEquation(expr_t eq, int lineno, const map<string, string> &eq_tags)
|
||||
{
|
||||
auto beq = dynamic_cast<BinaryOpNode *>(eq);
|
||||
assert(beq && beq->op_code == BinaryOpcode::equal);
|
||||
|
||||
vector<pair<string, string>> soe_eq_tags;
|
||||
for (const auto &eq_tag : eq_tags)
|
||||
soe_eq_tags.push_back(eq_tag);
|
||||
|
||||
int n = static_only_equations.size();
|
||||
static_only_equations_equation_tags.add(static_only_equations.size(), eq_tags);
|
||||
static_only_equations.push_back(beq);
|
||||
static_only_equations_lineno.push_back(lineno);
|
||||
static_only_equations_equation_tags.push_back(soe_eq_tags);
|
||||
for (auto &it : soe_eq_tags)
|
||||
static_only_equation_tags_xref.emplace(it, n);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -6777,13 +6649,7 @@ DynamicModel::staticOnlyEquationsNbr() const
|
|||
size_t
|
||||
DynamicModel::dynamicOnlyEquationsNbr() const
|
||||
{
|
||||
set<int> eqs;
|
||||
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
if (equation_tag.second.first == "dynamic")
|
||||
eqs.insert(equation_tag.first);
|
||||
|
||||
return eqs.size();
|
||||
return equation_tags.getDynamicEqns().size();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -6792,10 +6658,7 @@ DynamicModel::isChecksumMatching(const string &basename, bool block) const
|
|||
stringstream buffer;
|
||||
|
||||
// Write equation tags
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
buffer << " " << equation_tag.first + 1
|
||||
<< equation_tag.second.first
|
||||
<< equation_tag.second.second << endl;
|
||||
equation_tags.writeCheckSumInfo(buffer);
|
||||
|
||||
ExprNodeOutputType buffer_type = block ? ExprNodeOutputType::matlabDynamicModelSparse : ExprNodeOutputType::CDynamicModel;
|
||||
|
||||
|
@ -6866,24 +6729,7 @@ DynamicModel::writeJsonAST(ostream &output) const
|
|||
output << R"({ "number":)" << eq
|
||||
<< R"(, "line":)" << equations_lineno[eq];
|
||||
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
if (equation_tag.first == eq)
|
||||
eqtags.push_back(equation_tag.second);
|
||||
|
||||
if (!eqtags.empty())
|
||||
{
|
||||
output << R"(, "tags": {)";
|
||||
int i = 0;
|
||||
for (const auto &[name, value] : eqtags)
|
||||
{
|
||||
if (i != 0)
|
||||
output << ", ";
|
||||
output << R"(")" << name << R"(": ")" << value << R"(")";
|
||||
i++;
|
||||
}
|
||||
output << "}";
|
||||
eqtags.clear();
|
||||
}
|
||||
equation_tags.writeJsonAST(output, eq);
|
||||
|
||||
output << R"(, "AST": )";
|
||||
equations[eq]->writeJsonAST(output);
|
||||
|
@ -6904,9 +6750,8 @@ DynamicModel::writeJsonVariableMapping(ostream &output) const
|
|||
int it = 0;
|
||||
int end_idx_eq = static_cast<int>(variable.second.size())-1;
|
||||
for (const auto &equation : variable.second)
|
||||
for (const auto &equation_tag : equation_tags)
|
||||
if (equation_tag.first == equation && equation_tag.second.first == "name")
|
||||
output << R"(")" << equation_tag.second.second << (it++ == end_idx_eq ? R"("])" : R"(", )");
|
||||
if (auto tmp = equation_tags.getTagValueByEqnAndKey(equation, "name"); !tmp.empty())
|
||||
output << R"(")" << tmp << (it++ == end_idx_eq ? R"("])" : R"(", )");
|
||||
output << (ii++ == end_idx_map ? R"(})" : R"(},)") << endl;
|
||||
}
|
||||
output << "]";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2003-2019 Dynare Team
|
||||
* Copyright © 2003-2020 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -54,10 +54,7 @@ private:
|
|||
vector<int> static_only_equations_lineno;
|
||||
|
||||
//! Stores the equation tags of equations declared as [static]
|
||||
vector<vector<pair<string, string>>> static_only_equations_equation_tags;
|
||||
|
||||
//! Stores mapping from equation tags to equation number
|
||||
multimap<pair<string, string>, int> static_only_equation_tags_xref;
|
||||
EquationTags static_only_equations_equation_tags;
|
||||
|
||||
using deriv_id_table_t = map<pair<int, int>, int>;
|
||||
//! Maps a pair (symbol_id, lag) to a deriv ID
|
||||
|
@ -260,9 +257,9 @@ private:
|
|||
//! Create a legacy *_dynamic.m file for Matlab/Octave not yet using the temporary terms array interface
|
||||
void writeDynamicMatlabCompatLayer(const string &basename) const;
|
||||
|
||||
vector<int> getEquationNumbersFromTags(const set<string> &eqtags) const;
|
||||
set<int> getEquationNumbersFromTags(const set<string> &eqtags) const;
|
||||
|
||||
void findPacExpectationEquationNumbers(vector<int> &eqnumber) const;
|
||||
void findPacExpectationEquationNumbers(set<int> &eqnumber) const;
|
||||
|
||||
//! Internal helper for the copy constructor and assignment operator
|
||||
/*! Copies all the structures that contain ExprNode*, by the converting the
|
||||
|
@ -452,7 +449,7 @@ public:
|
|||
void replaceMyEquations(DynamicModel &dynamic_model) const;
|
||||
|
||||
//! Adds an equation marked as [static]
|
||||
void addStaticOnlyEquation(expr_t eq, int lineno, const vector<pair<string, string>> &eq_tags);
|
||||
void addStaticOnlyEquation(expr_t eq, int lineno, const map<string, string> &eq_tags);
|
||||
|
||||
//! Returns number of static only equations
|
||||
size_t staticOnlyEquationsNbr() const;
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright © 2020 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "EquationTags.hh"
|
||||
|
||||
#include <regex>
|
||||
|
||||
set<int>
|
||||
EquationTags::getEqnsByKey(const string &key) const
|
||||
{
|
||||
set<int> retval;
|
||||
for (const auto & [eqn, tags] : eqn_tags)
|
||||
if (tags.find(key) != tags.end())
|
||||
retval.insert(eqn);
|
||||
return retval;
|
||||
}
|
||||
|
||||
set<int>
|
||||
EquationTags::getEqnsByTag(const string &key, const string &value) const
|
||||
{
|
||||
set<int> retval;
|
||||
for (const auto & [eqn, tags] : eqn_tags)
|
||||
if (auto tmp = tags.find(key); tmp != tags.end() && tmp->second == value)
|
||||
retval.insert(eqn);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
EquationTags::getEqnByTag(const string &key, const string &value) const
|
||||
{
|
||||
for (const auto & [eqn, tags] : eqn_tags)
|
||||
if (auto tmp = tags.find(key); tmp != tags.end() && tmp->second == value)
|
||||
return eqn;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
EquationTags::erase(const set<int> &eqns, const map<int, int> &old_eqn_num_2_new)
|
||||
{
|
||||
for (const auto &eqn : eqns)
|
||||
eqn_tags.erase(eqn);
|
||||
|
||||
for (const auto & [oldeqn, neweqn] : old_eqn_num_2_new)
|
||||
for (auto & [eqn, tags] : eqn_tags)
|
||||
if (eqn == oldeqn)
|
||||
{
|
||||
auto tmp = eqn_tags.extract(eqn);
|
||||
tmp.key() = neweqn;
|
||||
eqn_tags.insert(move(tmp));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EquationTags::writeCheckSumInfo(ostream &output) const
|
||||
{
|
||||
for (const auto & [eqn, tags] : eqn_tags)
|
||||
for (const auto & [key, value] : tags)
|
||||
output << " " << eqn + 1
|
||||
<< key << " " << value << endl;
|
||||
}
|
||||
|
||||
void
|
||||
EquationTags::writeOutput(ostream &output, const string &modstruct, bool julia) const
|
||||
{
|
||||
if (julia)
|
||||
{
|
||||
output << modstruct << "equation_tags = [" << endl;
|
||||
for (const auto & [eqn, tags] : eqn_tags)
|
||||
for (const auto & [key, value] : tags)
|
||||
output << " EquationTag("
|
||||
<< eqn + 1 << R"( , ")"
|
||||
<< key << R"(" , ")" << value << R"("))" << endl;
|
||||
output << " ]" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
output << modstruct << "equations_tags = {" << endl;
|
||||
for (const auto & [eqn, tags] : eqn_tags)
|
||||
{
|
||||
for (const auto & [key, value] : tags)
|
||||
output << " " << eqn + 1 << " , '"
|
||||
<< key << "' , '" << value << "' ;" << endl;
|
||||
}
|
||||
output << "};" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EquationTags::writeOccbinOutput(ostream &output, const string &modstruct, bool julia) const
|
||||
{
|
||||
if (julia)
|
||||
return;
|
||||
|
||||
map<int, map<string, string>> occbin_options;
|
||||
for (const auto & [eqn, tags] : eqn_tags)
|
||||
for (const auto & [key, value] : tags)
|
||||
if (key == "pswitch"
|
||||
|| key == "bind"
|
||||
|| key == "relax"
|
||||
|| key == "pcrit")
|
||||
occbin_options[eqn][key] = value;
|
||||
|
||||
int idx = 0;
|
||||
for (const auto & [eqn, tags] : occbin_options)
|
||||
{
|
||||
idx++;
|
||||
for (const auto & [key, value] : tags)
|
||||
output << modstruct << "occbin.constraint(" << idx << ")."
|
||||
<< key << " = '" << value << "';" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EquationTags::writeLatexOutput(ostream &output, int eqn) const
|
||||
{
|
||||
if (!exists(eqn))
|
||||
return;
|
||||
|
||||
auto escape_special_latex_symbols
|
||||
= [](string str)
|
||||
{
|
||||
const regex special_latex_chars (R"([&%$#_{}])");
|
||||
const regex backslash (R"(\\)");
|
||||
const regex tilde (R"(~)");
|
||||
const regex carrot (R"(\^)");
|
||||
const regex textbackslash (R"(\\textbackslash)");
|
||||
str = regex_replace(str, backslash, R"(\textbackslash)");
|
||||
str = regex_replace(str, special_latex_chars, R"(\$&)");
|
||||
str = regex_replace(str, carrot, R"(\^{})");
|
||||
str = regex_replace(str, tilde, R"(\textasciitilde{})");
|
||||
return regex_replace(str, textbackslash, R"(\textbackslash{})");
|
||||
};
|
||||
|
||||
bool wrote_eq_tag = false;
|
||||
output << R"(\noindent[)";
|
||||
for (const auto & [key, value] : eqn_tags.at(eqn))
|
||||
{
|
||||
if (wrote_eq_tag)
|
||||
output << ", ";
|
||||
output << escape_special_latex_symbols(key);
|
||||
|
||||
if (!value.empty())
|
||||
output << "= `" << escape_special_latex_symbols(value) << "'";
|
||||
|
||||
wrote_eq_tag = true;
|
||||
}
|
||||
output << "]" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
EquationTags::writeJsonAST(ostream &output, const int eqn) const
|
||||
{
|
||||
if (!exists(eqn))
|
||||
return;
|
||||
|
||||
output << R"(, "tags": {)";
|
||||
bool wroteFirst = false;
|
||||
for (const auto &[key, value] : eqn_tags.at(eqn))
|
||||
{
|
||||
if (wroteFirst)
|
||||
output << ", ";
|
||||
else
|
||||
wroteFirst = true;
|
||||
output << R"(")" << key << R"(": ")" << value << R"(")";
|
||||
}
|
||||
output << "}";
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright © 2020 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _EQUATION_TAGS_HH
|
||||
#define _EQUATION_TAGS_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
class EquationTags
|
||||
{
|
||||
private:
|
||||
map<int, map<string, string>> eqn_tags;
|
||||
public:
|
||||
// Add multiple equatoin tags for the given equation
|
||||
inline void add(int eqn, map<string, string> tags)
|
||||
{
|
||||
if (eqn_tags.find(eqn) == eqn_tags.end())
|
||||
eqn_tags[eqn] = move(tags);
|
||||
else
|
||||
eqn_tags[eqn].insert(tags.begin(), tags.end());
|
||||
}
|
||||
|
||||
//! Add a single equation tag for the given equation
|
||||
inline void add(int eqn, string key, string value)
|
||||
{
|
||||
eqn_tags[eqn][move(key)] = move(value);
|
||||
}
|
||||
|
||||
//! Clear all equation tag information
|
||||
inline void clear()
|
||||
{
|
||||
eqn_tags.clear();
|
||||
}
|
||||
|
||||
//! Erase tags for given equations, using old_eqn_num_2_new as the mapping
|
||||
//! to use for the remaining equation numbers
|
||||
void erase(const set<int> &eqns, const map<int, int> &old_eqn_num_2_new);
|
||||
|
||||
//! Various functions to get info from equation tags
|
||||
//! Get equation tags for a given equation
|
||||
inline map<string, string> getTagsByEqn(const int eqn) const
|
||||
{
|
||||
if (eqn_tags.find(eqn) != eqn_tags.end())
|
||||
return eqn_tags.find(eqn)->second;
|
||||
return map<string, string>{};
|
||||
}
|
||||
|
||||
//! Get equations that have the given key
|
||||
set<int> getEqnsByKey(const string &key) const;
|
||||
|
||||
//! Get equations that have the given key and value
|
||||
set<int> getEqnsByTag(const string &key, const string &value) const;
|
||||
|
||||
//! Get the first equation that has the given key and value
|
||||
int getEqnByTag(const string &key, const string &value) const;
|
||||
|
||||
//! Get the tag value given the equation number and key
|
||||
inline string getTagValueByEqnAndKey(const int eqn, const string &key) const
|
||||
{
|
||||
return exists(eqn, key) ? eqn_tags.at(eqn).at(key) : "";
|
||||
}
|
||||
|
||||
//! Get the equations marked dynamic
|
||||
inline set<int> getDynamicEqns() const
|
||||
{
|
||||
return getEqnsByTag("dynamic", "");
|
||||
}
|
||||
|
||||
//! Returns true if equation tag with key and value exists
|
||||
inline bool exists(const string &key, const string &value) const
|
||||
{
|
||||
return getEqnByTag(key, value) >= 0;
|
||||
}
|
||||
|
||||
inline bool exists(const int eqn) const
|
||||
{
|
||||
return eqn_tags.find(eqn) != eqn_tags.end();
|
||||
}
|
||||
|
||||
//! Returns true if equation tag with key exists for a given equation
|
||||
inline bool exists(const int eqn, const string &key) const
|
||||
{
|
||||
return exists(eqn) ? eqn_tags.at(eqn).find(key) != eqn_tags.at(eqn).end() : false;
|
||||
}
|
||||
|
||||
//! Returns true if equation tag with key and value exists for a given equation
|
||||
inline bool exists(const int eqn, const string &key, const string &value) const
|
||||
{
|
||||
return exists(eqn, key) ? eqn_tags.at(eqn).at(key) == value : false;
|
||||
}
|
||||
|
||||
//! Various functions to write equation tags
|
||||
void writeCheckSumInfo(ostream &output) const;
|
||||
void writeOutput(ostream &output, const string &modstruct, bool julia) const;
|
||||
void writeOccbinOutput(ostream &output, const string &modstruct, bool julia) const;
|
||||
void writeLatexOutput(ostream &output, int eqn) const;
|
||||
void writeJsonAST(ostream &output, const int eq) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -10,6 +10,8 @@ dynare_m_SOURCES = \
|
|||
DynareBison.yy \
|
||||
ComputingTasks.cc \
|
||||
ComputingTasks.hh \
|
||||
EquationTags.cc \
|
||||
EquationTags.hh \
|
||||
ModelTree.cc \
|
||||
ModelTree.hh \
|
||||
StaticModel.cc \
|
||||
|
|
|
@ -111,7 +111,6 @@ ModelTree::ModelTree(const ModelTree &m) :
|
|||
user_set_compiler{m.user_set_compiler},
|
||||
equations_lineno{m.equations_lineno},
|
||||
equation_tags{m.equation_tags},
|
||||
equation_tags_xref{m.equation_tags_xref},
|
||||
computed_derivs_order{m.computed_derivs_order},
|
||||
NNZDerivatives{m.NNZDerivatives},
|
||||
equation_reordered{m.equation_reordered},
|
||||
|
@ -138,7 +137,6 @@ ModelTree::operator=(const ModelTree &m)
|
|||
equations_lineno = m.equations_lineno;
|
||||
aux_equations.clear();
|
||||
equation_tags = m.equation_tags;
|
||||
equation_tags_xref = m.equation_tags_xref;
|
||||
computed_derivs_order = m.computed_derivs_order;
|
||||
NNZDerivatives = m.NNZDerivatives;
|
||||
|
||||
|
@ -1857,41 +1855,7 @@ ModelTree::writeLatexModelFile(const string &mod_basename, const string &latex_b
|
|||
{
|
||||
content_output << "% Equation " << eq + 1 << endl;
|
||||
if (write_equation_tags)
|
||||
{
|
||||
auto escape_special_latex_symbols
|
||||
= [](string str)
|
||||
{
|
||||
const regex special_latex_chars (R"([&%$#_{}])");
|
||||
const regex backslash (R"(\\)");
|
||||
const regex tilde (R"(~)");
|
||||
const regex carrot (R"(\^)");
|
||||
const regex textbackslash (R"(\\textbackslash)");
|
||||
str = regex_replace(str, backslash, R"(\textbackslash)");
|
||||
str = regex_replace(str, special_latex_chars, R"(\$&)");
|
||||
str = regex_replace(str, carrot, R"(\^{})");
|
||||
str = regex_replace(str, tilde, R"(\textasciitilde{})");
|
||||
return regex_replace(str, textbackslash, R"(\textbackslash{})");
|
||||
};
|
||||
bool wrote_eq_tag = false;
|
||||
for (const auto & [tagged_eq, tag_pair] : equation_tags)
|
||||
if (tagged_eq == eq)
|
||||
{
|
||||
if (!wrote_eq_tag)
|
||||
content_output << R"(\noindent[)";
|
||||
else
|
||||
content_output << ", ";
|
||||
|
||||
content_output << escape_special_latex_symbols(tag_pair.first);
|
||||
|
||||
if (!(tag_pair.second.empty()))
|
||||
content_output << "= `" << escape_special_latex_symbols(tag_pair.second) << "'";
|
||||
|
||||
wrote_eq_tag = true;
|
||||
}
|
||||
|
||||
if (wrote_eq_tag)
|
||||
content_output << "]" << endl;
|
||||
}
|
||||
equation_tags.writeLatexOutput(content_output, eq);
|
||||
|
||||
content_output << R"(\begin{dmath})" << endl;
|
||||
// Here it is necessary to cast to superclass ExprNode, otherwise the overloaded writeOutput() method is not found
|
||||
|
@ -1919,8 +1883,7 @@ ModelTree::addEquation(expr_t eq, int lineno)
|
|||
vector<int>
|
||||
ModelTree::includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_eqs,
|
||||
vector<BinaryOpNode *> &equations, vector<int> &equations_lineno,
|
||||
vector<pair<int, pair<string, string>>> &equation_tags,
|
||||
multimap<pair<string, string>, int> &equation_tags_xref, bool static_equations) const
|
||||
EquationTags &equation_tags, bool static_equations) const
|
||||
{
|
||||
vector<int> excluded_vars;
|
||||
if (equations.empty())
|
||||
|
@ -1929,12 +1892,12 @@ ModelTree::includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_
|
|||
// Get equation numbers of tags
|
||||
set<int> tag_eqns;
|
||||
for (auto &it : eqs)
|
||||
if (equation_tags_xref.find(it) != equation_tags_xref.end())
|
||||
if (auto tmp = equation_tags.getEqnsByTag(it.first, it.second); !tmp.empty())
|
||||
{
|
||||
auto range = equation_tags_xref.equal_range(it);
|
||||
for_each(range.first, range.second, [&tag_eqns](auto &x) { tag_eqns.insert(x.second); });
|
||||
tag_eqns.insert(tmp.begin(), tmp.end());
|
||||
eqs.erase(it);
|
||||
}
|
||||
|
||||
if (tag_eqns.empty())
|
||||
return excluded_vars;
|
||||
|
||||
|
@ -1946,23 +1909,16 @@ ModelTree::includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_
|
|||
if (tag_eqns.find(i) == tag_eqns.end())
|
||||
eqns.insert(i);
|
||||
|
||||
// remove from equations, equations_lineno, equation_tags, equation_tags_xref
|
||||
// remove from equations, equations_lineno, equation_tags
|
||||
vector<BinaryOpNode *> new_eqns;
|
||||
vector<int> new_equations_lineno;
|
||||
map<int, int> old_eqn_num_2_new;
|
||||
for (size_t i = 0; i < equations.size(); i++)
|
||||
if (eqns.find(i) != eqns.end())
|
||||
{
|
||||
bool found = false;
|
||||
for (const auto & [tagged_eq, tag_pair] : equation_tags)
|
||||
if (tagged_eq == static_cast<int>(i) && tag_pair.first == "endogenous")
|
||||
{
|
||||
found = true;
|
||||
excluded_vars.push_back(symbol_table.getID(tag_pair.second));
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
if (auto tmp = equation_tags.getTagValueByEqnAndKey(i, "endogenous"); !tmp.empty())
|
||||
{
|
||||
excluded_vars.push_back(symbol_table.getID(tmp));
|
||||
set<pair<int, int>> result;
|
||||
equations[i]->arg1->collectDynamicVariables(SymbolType::endogenous, result);
|
||||
if (result.size() == 1)
|
||||
|
@ -1986,17 +1942,7 @@ ModelTree::includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_
|
|||
equations = new_eqns;
|
||||
equations_lineno = new_equations_lineno;
|
||||
|
||||
equation_tags.erase(remove_if(equation_tags.begin(), equation_tags.end(),
|
||||
[&](const auto &it) { return eqns.find(it.first) != eqns.end(); }),
|
||||
equation_tags.end());
|
||||
for (auto &it : old_eqn_num_2_new)
|
||||
for (auto &it1 : equation_tags)
|
||||
if (it1.first == it.first)
|
||||
it1.first = it.second;
|
||||
|
||||
equation_tags_xref.clear();
|
||||
for (const auto &it : equation_tags)
|
||||
equation_tags_xref.emplace(it.second, it.first);
|
||||
equation_tags.erase(eqns, old_eqn_num_2_new);
|
||||
|
||||
if (!static_equations)
|
||||
for (size_t i = 0; i < excluded_vars.size(); i++)
|
||||
|
@ -2040,14 +1986,9 @@ ModelTree::findConstantEquationsWithoutTags(map<VariableNode *, NumConstNode *>
|
|||
}
|
||||
|
||||
void
|
||||
ModelTree::addEquation(expr_t eq, int lineno, const vector<pair<string, string>> &eq_tags)
|
||||
ModelTree::addEquation(expr_t eq, int lineno, const map<string, string> &eq_tags)
|
||||
{
|
||||
int n = equations.size();
|
||||
for (const auto &eq_tag : eq_tags)
|
||||
{
|
||||
equation_tags.emplace_back(n, eq_tag);
|
||||
equation_tags_xref.emplace(eq_tag, n);
|
||||
}
|
||||
equation_tags.add(equations.size(), eq_tags);
|
||||
addEquation(eq, lineno);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ using namespace std;
|
|||
#include <filesystem>
|
||||
|
||||
#include "DataTree.hh"
|
||||
#include "EquationTags.hh"
|
||||
#include "ExtendedPreprocessorTypes.hh"
|
||||
|
||||
// Helper to convert a vector into a tuple
|
||||
|
@ -87,9 +88,7 @@ protected:
|
|||
//! Stores line numbers of declared equations; -1 means undefined
|
||||
vector<int> equations_lineno;
|
||||
//! Stores equation tags
|
||||
vector<pair<int, pair<string, string>>> equation_tags;
|
||||
//! Stores mapping from equation tags to equation number
|
||||
multimap<pair<string, string>, int> equation_tags_xref;
|
||||
EquationTags equation_tags;
|
||||
/*
|
||||
* ************** END **************
|
||||
*/
|
||||
|
@ -274,8 +273,7 @@ protected:
|
|||
//! Remove equations specified by exclude_eqs
|
||||
vector<int> includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_eqs,
|
||||
vector<BinaryOpNode *> &equations, vector<int> &equations_lineno,
|
||||
vector<pair<int, pair<string, string>>> &equation_tags,
|
||||
multimap<pair<string, string>, int> &equation_tags_xref, bool static_equations) const;
|
||||
EquationTags &equation_tags, bool static_equations) const;
|
||||
|
||||
//! Determine the simulation type of each block
|
||||
virtual BlockSimulationType getBlockSimulationType(int block_number) const = 0;
|
||||
|
@ -361,7 +359,7 @@ public:
|
|||
//! Declare a node as an equation of the model; also give its line number
|
||||
void addEquation(expr_t eq, int lineno);
|
||||
//! Declare a node as an equation of the model, also giving its tags
|
||||
void addEquation(expr_t eq, int lineno, const vector<pair<string, string>> &eq_tags);
|
||||
void addEquation(expr_t eq, int lineno, const map<string, string> &eq_tags);
|
||||
//! Declare a node as an auxiliary equation of the model, adding it at the end of the list of auxiliary equations
|
||||
void addAuxEquation(expr_t eq);
|
||||
//! Returns the number of equations in the model
|
||||
|
@ -394,11 +392,7 @@ public:
|
|||
inline map<string, string>
|
||||
getEquationTags(int eq) const
|
||||
{
|
||||
map<string, string> r;
|
||||
for (auto &[eq2, tagpair] : equation_tags)
|
||||
if (eq2 == eq)
|
||||
r[tagpair.first] = tagpair.second;
|
||||
return r;
|
||||
return equation_tags.getTagsByEqn(eq);
|
||||
}
|
||||
|
||||
inline static string
|
||||
|
|
|
@ -296,7 +296,7 @@ ParsingDriver::add_predetermined_variable(const string &name)
|
|||
void
|
||||
ParsingDriver::add_equation_tags(string key, string value)
|
||||
{
|
||||
eq_tags.emplace_back(key, value);
|
||||
eq_tags[key] = value;
|
||||
|
||||
transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
if (key.compare("endogenous") == 0)
|
||||
|
@ -2494,15 +2494,7 @@ ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2)
|
|||
expr_t id = model_tree->AddEqual(arg1, arg2);
|
||||
|
||||
// Detect if the equation is tagged [static]
|
||||
bool is_static_only = false;
|
||||
for (auto &eq_tag : eq_tags)
|
||||
if (eq_tag.first == "static")
|
||||
{
|
||||
is_static_only = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_static_only)
|
||||
if (eq_tags.find("static") != eq_tags.end())
|
||||
{
|
||||
if (!id->isInStaticForm())
|
||||
error("An equation tagged [static] cannot contain leads, lags, expectations or STEADY_STATE operators");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2003-2019 Dynare Team
|
||||
* Copyright © 2003-2020 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -248,7 +248,7 @@ private:
|
|||
//! For parsing the graph_format option
|
||||
SymbolList graph_formats;
|
||||
//! Temporary storage for equation tags
|
||||
vector<pair<string, string>> eq_tags;
|
||||
map<string, string> eq_tags;
|
||||
|
||||
//! Map Var name to variables
|
||||
map<string, vector<string>> var_map;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2003-2019 Dynare Team
|
||||
* Copyright © 2003-2020 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -159,38 +159,32 @@ StaticModel::StaticModel(const DynamicModel &m) :
|
|||
|
||||
// Convert equations
|
||||
int static_only_index = 0;
|
||||
set<int> dynamic_equations = m.equation_tags.getDynamicEqns();
|
||||
for (int i = 0; i < static_cast<int>(m.equations.size()); i++)
|
||||
{
|
||||
// Detect if equation is marked [dynamic]
|
||||
bool is_dynamic_only = false;
|
||||
vector<pair<string, string>> eq_tags;
|
||||
for (const auto & [tagged_eq, tag_pair] : m.equation_tags)
|
||||
if (tagged_eq == i)
|
||||
try
|
||||
{
|
||||
// If equation is dynamic, replace it by an equation marked [static]
|
||||
if (dynamic_equations.find(i) != dynamic_equations.end())
|
||||
{
|
||||
eq_tags.push_back(tag_pair);
|
||||
if (tag_pair.first == "dynamic")
|
||||
is_dynamic_only = true;
|
||||
auto [static_only_equations,
|
||||
static_only_equations_lineno,
|
||||
static_only_equations_equation_tags] = m.getStaticOnlyEquationsInfo();
|
||||
|
||||
addEquation(static_only_equations[static_only_index]->toStatic(*this),
|
||||
static_only_equations_lineno[static_only_index],
|
||||
static_only_equations_equation_tags.getTagsByEqn(static_only_index));
|
||||
static_only_index++;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// If yes, replace it by an equation marked [static]
|
||||
if (is_dynamic_only)
|
||||
{
|
||||
auto [static_only_equations, static_only_equations_lineno, static_only_equations_equation_tags] = m.getStaticOnlyEquationsInfo();
|
||||
|
||||
addEquation(static_only_equations[static_only_index]->toStatic(*this), static_only_equations_lineno[static_only_index], static_only_equations_equation_tags[static_only_index]);
|
||||
static_only_index++;
|
||||
}
|
||||
else
|
||||
addEquation(m.equations[i]->toStatic(*this), m.equations_lineno[i], eq_tags);
|
||||
}
|
||||
catch (DataTree::DivisionByZeroException)
|
||||
{
|
||||
cerr << "...division by zero error encountred when converting equation " << i << " to static" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
addEquation(m.equations[i]->toStatic(*this),
|
||||
m.equations_lineno[i],
|
||||
m.equation_tags.getTagsByEqn(i));
|
||||
}
|
||||
catch (DataTree::DivisionByZeroException)
|
||||
{
|
||||
cerr << "...division by zero error encountred when converting equation " << i << " to static" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Convert auxiliary equations
|
||||
for (auto aux_eq : m.aux_equations)
|
||||
|
|
Loading…
Reference in New Issue