model_replace, model_remove: allow selecting an equation with several (conjunct) tags

NB: does not (yet) works with Occbin regime-specific equations.

Ref. dynare#1890
master
Sébastien Villemot 2023-11-14 17:21:31 +01:00
parent 661b16440e
commit 46aa6610ab
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
7 changed files with 70 additions and 26 deletions

View File

@ -496,7 +496,7 @@ DynamicModel::writeDynamicMCompatFile(const string &basename) const
output.close();
}
vector<pair<string, string>>
vector<map<string, string>>
DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, bool exclude_eqs)
{
auto removeLeadingTrailingWhitespace = [](string &str)
@ -584,7 +584,7 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b
exit(EXIT_FAILURE);
}
vector<pair<string, string>> eq_tag_set;
vector<map<string, string>> eq_tag_set;
regex s(quote_regex + "|" + non_quote_regex);
for (auto it = sregex_iterator(tags.begin(), tags.end(), s);
it != sregex_iterator(); ++it)
@ -595,13 +595,13 @@ DynamicModel::parseIncludeExcludeEquations(const string &inc_exc_option_value, b
str.remove_prefix(1);
str.remove_suffix(1);
}
eq_tag_set.emplace_back(tagname, str);
eq_tag_set.push_back({ { tagname, string{str} } });
}
return eq_tag_set;
}
vector<int>
DynamicModel::removeEquationsHelper(set<pair<string, string>> &listed_eqs_by_tag, bool exclude_eqs,
DynamicModel::removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag, bool exclude_eqs,
bool excluded_vars_change_type,
vector<BinaryOpNode *> &all_equations,
vector<optional<int>> &all_equations_lineno,
@ -616,7 +616,7 @@ DynamicModel::removeEquationsHelper(set<pair<string, string>> &listed_eqs_by_tag
the caller knows which tag pairs have not been handled. */
set<int> listed_eqs_by_number;
for (auto it = listed_eqs_by_tag.begin(); it != listed_eqs_by_tag.end();)
if (auto tmp = all_equation_tags.getEqnsByTag(it->first, it->second);
if (auto tmp = all_equation_tags.getEqnsByTags(*it);
!tmp.empty())
{
listed_eqs_by_number.insert(tmp.begin(), tmp.end());
@ -691,7 +691,7 @@ DynamicModel::removeEquationsHelper(set<pair<string, string>> &listed_eqs_by_tag
}
void
DynamicModel::removeEquations(const vector<pair<string, string>> &listed_eqs_by_tag, bool exclude_eqs,
DynamicModel::removeEquations(const vector<map<string, string>> &listed_eqs_by_tag, bool exclude_eqs,
bool excluded_vars_change_type)
{
/* Convert the const vector to a (mutable) set */
@ -710,8 +710,22 @@ DynamicModel::removeEquations(const vector<pair<string, string>> &listed_eqs_by_
if (!listed_eqs_by_tag2.empty())
{
cerr << "ERROR: model_remove/model_replace/exclude_eqs/include_eqs: The equations specified by" << endl;
for (const auto &[tagname, tagvalue] : listed_eqs_by_tag)
cerr << " " << tagname << "=" << tagvalue << endl;
for (const auto &m : listed_eqs_by_tag)
{
cerr << " ";
if (m.size() > 1)
cerr << "[ ";
bool first_printed {false};
for (const auto &[tagname, tagvalue] : m)
{
if (exchange(first_printed, true))
cerr << ", ";
cerr << tagname << "=" << tagvalue;
}
if (m.size() > 1)
cerr << " ]";
cerr << endl;
}
cerr << "were not found." << endl;
exit(EXIT_FAILURE);
}

View File

@ -221,11 +221,12 @@ private:
Returns a set of pairs (tag name, tag value) corresponding to the set of
equations to be included or excluded.
*/
static vector<pair<string, string>> parseIncludeExcludeEquations(const string &inc_exc_option_value, bool exclude_eqs);
static vector<map<string, string>> parseIncludeExcludeEquations(const string &inc_exc_option_value, bool exclude_eqs);
/* Helper for the removeEquations() method.
listed_eqs_by_tag is the list of (tag name, tag value) pairs corresponding
to the option value, exclude_eqs is a boolean indicating whether were
listed_eqs_by_tag describes a list of equations to remove (identified by
one or more tags; if multiple tags are present for a single equation, they
are understood as a conjunction), exclude_eqs is a boolean indicating whether were
excluding or including, and excluded_vars_change_type is a boolean
indicating whether to compute variables to be excluded.
@ -233,13 +234,13 @@ private:
equations. They are either the main structures for storing equations in
ModelTree, or their counterpart for static-only equations. The
static_equations boolean indicates when we are in the latter case.
The listed_eqs_by_tag structure will be updated by removing those tag
pairs that have been matched with equations in the all_equations*
argument*.
The listed_eqs_by_tag structure will be updated by removing the tags
matched with equations in the all_equations* argument*.
Returns a list of excluded variables (empty if
excluded_vars_change_type=false) */
vector<int> removeEquationsHelper(set<pair<string, string>> &listed_eqs_by_tag,
vector<int> removeEquationsHelper(set<map<string, string>> &listed_eqs_by_tag,
bool exclude_eqs, bool excluded_vars_change_type,
vector<BinaryOpNode *> &all_equations,
vector<optional<int>> &all_equations_lineno,
@ -396,10 +397,12 @@ public:
//! Implements the include_eqs/exclude_eqs options
void includeExcludeEquations(const string &inc_exc_option_value, bool exclude_eqs);
/* Removes equations from the model (identified by their name tags).
/* Removes equations from the model (identified by one or more tags; if
multiple tags are present for a single equation, they are understood as a
conjunction).
Used for include_eqs/exclude_eqs options and for model_remove and
model_replace blocks */
void removeEquations(const vector<pair<string, string>> &listed_eqs_by_tag, bool exclude_eqs,
void removeEquations(const vector<map<string, string>> &listed_eqs_by_tag, bool exclude_eqs,
bool excluded_vars_change_type);
/* Replaces model equations with derivatives of Lagrangian w.r.t. endogenous.

View File

@ -235,7 +235,8 @@ str_tolower(string s)
%type <PriorDistributions> prior_pdf prior_distribution
%type <pair<expr_t,expr_t>> calibration_range
%type <pair<string,string>> partition_elem subsamples_eq_opt integer_range_w_inf tag_pair
%type <vector<pair<string,string>>> partition partition_1 tag_pair_list_for_selection symbol_list_with_tex
%type <vector<pair<string,string>>> partition partition_1 symbol_list_with_tex
%type <vector<map<string, string>>> tag_pair_list_for_selection
%type <map<string, string>> tag_pair_list
%type <tuple<string,string,string,string>> prior_eq_opt options_eq_opt
%type <vector<pair<int, int>>> period_list
@ -1155,18 +1156,25 @@ model_replace : MODEL_REPLACE '(' tag_pair_list_for_selection ')' ';'
model_options : MODEL_OPTIONS '(' model_options_list ')' ';'
tag_pair_list_for_selection : QUOTED_STRING
{ $$ = { { "name", $1 } }; }
{ $$ = { { { "name", $1 } } }; }
| tag_pair
{ $$ = { $1 }; }
{ $$ = { { $1 } }; }
| '[' tag_pair_list ']'
{ $$ = { $2 }; }
| tag_pair_list_for_selection COMMA QUOTED_STRING
{
$$ = $1;
$$.emplace_back("name", $3);
$$.push_back({ { "name", $3 } });
}
| tag_pair_list_for_selection COMMA tag_pair
{
$$ = $1;
$$.push_back($3);
$$.push_back({ $3 });
}
| tag_pair_list_for_selection COMMA '[' tag_pair_list ']'
{
$$ = $1;
$$.push_back($4);
}
;

View File

@ -52,6 +52,22 @@ EquationTags::getEqnByTag(const string &key, const string &value) const
return nullopt;
}
set<int>
EquationTags::getEqnsByTags(const map<string, string> &tags_selected) const
{
set<int> retval;
for (const auto &[eqn, tags] : eqn_tags)
{
for (const auto &[key, value] : tags_selected)
if (auto tmp = tags.find(key); tmp == tags.end() || tmp->second != value)
goto next_eq;
retval.insert(eqn);
next_eq:
;
}
return retval;
}
void
EquationTags::erase(const set<int> &eqns, const map<int, int> &old_eqn_num_2_new)
{

View File

@ -79,6 +79,9 @@ public:
//! Get the first equation that has the given key and value
optional<int> getEqnByTag(const string &key, const string &value) const;
// Get equations that have all the given keys and values (seen as a conjunction)
set<int> getEqnsByTags(const map<string, string> &tags_selected) const;
//! Get the tag value given the equation number and key
optional<string>
getTagValueByEqnAndKey(int eqn, const string &key) const

View File

@ -3756,13 +3756,13 @@ ParsingDriver::isSymbolIdentifier(const string &str)
}
void
ParsingDriver::model_remove(const vector<pair<string, string>> &listed_eqs_by_tags)
ParsingDriver::model_remove(const vector<map<string, string>> &listed_eqs_by_tags)
{
mod_file->dynamic_model.removeEquations(listed_eqs_by_tags, true, true);
}
void
ParsingDriver::begin_model_replace(const vector<pair<string, string>> &listed_eqs_by_tags)
ParsingDriver::begin_model_replace(const vector<map<string, string>> &listed_eqs_by_tags)
{
mod_file->dynamic_model.removeEquations(listed_eqs_by_tags, true, false);
set_current_data_tree(&mod_file->dynamic_model);

View File

@ -904,9 +904,9 @@ public:
//! Add an occbin_constraints block
void end_occbin_constraints(vector<tuple<string, BinaryOpNode *, BinaryOpNode *, expr_t, expr_t>> constraints);
// Process a model_remove statement
void model_remove(const vector<pair<string, string>> &listed_eqs_by_tags);
void model_remove(const vector<map<string, string>> &listed_eqs_by_tags);
// Begin a model_replace statement
void begin_model_replace(const vector<pair<string, string>> &listed_eqs_by_tags);
void begin_model_replace(const vector<map<string, string>> &listed_eqs_by_tags);
// Add a var_remove statement
void var_remove(const vector<string> &symbol_list);
void begin_pac_target_info(string name);