Merge branch 'exclude_eqs' into 'master'
introduce command line options: `exclude_eqs` and `include_eqs` See merge request Dynare/preprocessor!7issue#70
commit
8be9efa425
|
@ -150,7 +150,8 @@ enum class SymbolType
|
||||||
logTrend = 15, //!< Log-trend variable
|
logTrend = 15, //!< Log-trend variable
|
||||||
unusedEndogenous = 16, //!< Type to mark unused endogenous variables when `nostrict` option is passed
|
unusedEndogenous = 16, //!< Type to mark unused endogenous variables when `nostrict` option is passed
|
||||||
endogenousVAR = 17, //!< Variables declared in a var_model statement
|
endogenousVAR = 17, //!< Variables declared in a var_model statement
|
||||||
epilogue = 18 //!< Variables created in epilogue block
|
epilogue = 18, //!< Variables created in epilogue block
|
||||||
|
excludedVariable = 19 //!< Type to use when an equation is excluded via include/exclude_eqs and the LHS variable is not used elsewhere in the model
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ExpressionType
|
enum ExpressionType
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#include "DynamicModel.hh"
|
#include "DynamicModel.hh"
|
||||||
|
|
||||||
|
@ -103,6 +104,7 @@ DynamicModel::DynamicModel(const DynamicModel &m) :
|
||||||
balanced_growth_test_tol {m.balanced_growth_test_tol},
|
balanced_growth_test_tol {m.balanced_growth_test_tol},
|
||||||
static_only_equations_lineno {m.static_only_equations_lineno},
|
static_only_equations_lineno {m.static_only_equations_lineno},
|
||||||
static_only_equations_equation_tags {m.static_only_equations_equation_tags},
|
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},
|
deriv_id_table {m.deriv_id_table},
|
||||||
inv_deriv_id_table {m.inv_deriv_id_table},
|
inv_deriv_id_table {m.inv_deriv_id_table},
|
||||||
dyn_jacobian_cols_table {m.dyn_jacobian_cols_table},
|
dyn_jacobian_cols_table {m.dyn_jacobian_cols_table},
|
||||||
|
@ -165,6 +167,7 @@ DynamicModel::operator=(const DynamicModel &m)
|
||||||
|
|
||||||
static_only_equations_lineno = m.static_only_equations_lineno;
|
static_only_equations_lineno = m.static_only_equations_lineno;
|
||||||
static_only_equations_equation_tags = m.static_only_equations_equation_tags;
|
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;
|
deriv_id_table = m.deriv_id_table;
|
||||||
inv_deriv_id_table = m.inv_deriv_id_table;
|
inv_deriv_id_table = m.inv_deriv_id_table;
|
||||||
dyn_jacobian_cols_table = m.dyn_jacobian_cols_table;
|
dyn_jacobian_cols_table = m.dyn_jacobian_cols_table;
|
||||||
|
@ -2930,6 +2933,179 @@ DynamicModel::writeDynamicJacobianNonZeroElts(const string &basename) const
|
||||||
output.close();
|
output.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
ifstream exclude_file;
|
||||||
|
exclude_file.open(inc_exc_eq_tags, ifstream::in);
|
||||||
|
if (!exclude_file.is_open())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Could not open " << inc_exc_eq_tags << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
string line;
|
||||||
|
bool tagname_on_first_line = false;
|
||||||
|
while (getline(exclude_file, line))
|
||||||
|
{
|
||||||
|
removeLeadingTrailingWhitespace(line);
|
||||||
|
if (!line.empty())
|
||||||
|
if (tags.empty() && line.find("=") != string::npos)
|
||||||
|
{
|
||||||
|
tagname_on_first_line = true;
|
||||||
|
tags += line + "(";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (line.find("'") != string::npos)
|
||||||
|
tags += line + ",";
|
||||||
|
else
|
||||||
|
tags += "'" + line + "',";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tags.empty())
|
||||||
|
{
|
||||||
|
tags = tags.substr(0, tags.size()-1);
|
||||||
|
if (tagname_on_first_line)
|
||||||
|
tags += ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tags = inc_exc_eq_tags;
|
||||||
|
removeLeadingTrailingWhitespace(tags);
|
||||||
|
|
||||||
|
if (tags.front() == '[' && tags.back() != ']')
|
||||||
|
{
|
||||||
|
cerr << "Error: " << (exclude_eqs ? "exclude_eqs" : "include_eqs")
|
||||||
|
<< ": if the first character is '[' the last must be ']'" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tags.front() == '[' && tags.back() == ']')
|
||||||
|
tags = tags.substr(1, tags.length() - 2);
|
||||||
|
removeLeadingTrailingWhitespace(tags);
|
||||||
|
|
||||||
|
regex q ("^\\w+\\s*=");
|
||||||
|
smatch matches;
|
||||||
|
string tagname = "name";
|
||||||
|
if (regex_search(tags, matches, q))
|
||||||
|
{
|
||||||
|
tagname = matches[0].str();
|
||||||
|
tags = tags.substr(tagname.size(), tags.length() - tagname.size() + 1);
|
||||||
|
removeLeadingTrailingWhitespace(tags);
|
||||||
|
if (tags.front() == '(' && tags.back() == ')')
|
||||||
|
{
|
||||||
|
tags = tags.substr(1, tags.length() - 2);
|
||||||
|
removeLeadingTrailingWhitespace(tags);
|
||||||
|
}
|
||||||
|
tagname = tagname.substr(0, tagname.size()-1);
|
||||||
|
removeLeadingTrailingWhitespace(tagname);
|
||||||
|
}
|
||||||
|
|
||||||
|
string quote_regex = "'[^']+'";
|
||||||
|
string non_quote_regex = "[^,\\s]+";
|
||||||
|
regex r ("(\\s*" + quote_regex + "|" + non_quote_regex + "\\s*)(,\\s*(" + quote_regex + "|" + non_quote_regex + ")\\s*)*");
|
||||||
|
if (!regex_match (tags, r))
|
||||||
|
{
|
||||||
|
cerr << "Error: " << (exclude_eqs ? "exclude_eqs" : "include_eqs")
|
||||||
|
<< ": argument is of incorrect format." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
regex s (quote_regex + "|" + non_quote_regex);
|
||||||
|
for (auto it = sregex_iterator(tags.begin(), tags.end(), s);
|
||||||
|
it != sregex_iterator(); it++)
|
||||||
|
{
|
||||||
|
auto str = it->str();
|
||||||
|
if (str[0] == '\'' && str[str.size()-1] == '\'')
|
||||||
|
str = str.substr(1, str.size()-2);
|
||||||
|
eq_tag_set.insert({tagname, str});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DynamicModel::includeExcludeEquations(const string & eqs, bool exclude_eqs)
|
||||||
|
{
|
||||||
|
if (eqs.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
set<pair<string, string>> eq_tag_set;
|
||||||
|
parseIncludeExcludeEquations(eqs, eq_tag_set, exclude_eqs);
|
||||||
|
|
||||||
|
vector<int> excluded_vars =
|
||||||
|
ModelTree::includeExcludeEquations(eq_tag_set, exclude_eqs,
|
||||||
|
equations, equations_lineno,
|
||||||
|
equation_tags, equation_tags_xref, 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);
|
||||||
|
if (!eq_tag_set.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: " << (exclude_eqs ? "exclude_eqs" : "include_eqs") << ": The equations specified by `";
|
||||||
|
cerr << eq_tag_set.begin()->first << "= ";
|
||||||
|
for (auto & it : eq_tag_set)
|
||||||
|
cerr << it.second << ", ";
|
||||||
|
cerr << "` were not found." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (staticOnlyEquationsNbr() != dynamicOnlyEquationsNbr())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: " << (exclude_eqs ? "exclude_eqs" : "include_eqs")
|
||||||
|
<< ": You must remove the same number of equations marked `static` as equations marked `dynamic`." << endl;
|
||||||
|
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)
|
||||||
|
eqn->collectDynamicVariables(SymbolType::endogenous, eqn_vars);
|
||||||
|
for (const auto & eqn : static_only_equations)
|
||||||
|
eqn->collectDynamicVariables(SymbolType::endogenous, eqn_vars);
|
||||||
|
|
||||||
|
// Change LHS variable type of excluded equation if it is used in an eqution that has been kept
|
||||||
|
for (auto ev : excluded_vars)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (const auto & it : eqn_vars)
|
||||||
|
if (it.first == ev)
|
||||||
|
{
|
||||||
|
symbol_table.changeType(ev, SymbolType::exogenous);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
symbol_table.changeType(ev, SymbolType::excludedVariable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DynamicModel::writeOutput(ostream &output, const string &basename, bool block_decomposition, bool linear_decomposition, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const
|
DynamicModel::writeOutput(ostream &output, const string &basename, bool block_decomposition, bool linear_decomposition, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const
|
||||||
{
|
{
|
||||||
|
@ -6305,13 +6481,22 @@ DynamicModel::getEquationNumbersFromTags(const set<string> &eqtags) const
|
||||||
{
|
{
|
||||||
vector<int> eqnumbers;
|
vector<int> eqnumbers;
|
||||||
for (auto & eqtag : eqtags)
|
for (auto & eqtag : eqtags)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
for (const auto & equation_tag : equation_tags)
|
for (const auto & equation_tag : equation_tags)
|
||||||
if (equation_tag.second.first == "name"
|
if (equation_tag.second.first == "name"
|
||||||
&& equation_tag.second.second == eqtag)
|
&& equation_tag.second.second == eqtag)
|
||||||
{
|
{
|
||||||
|
found = true;
|
||||||
eqnumbers.push_back(equation_tag.first);
|
eqnumbers.push_back(equation_tag.first);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: looking for equation tag " << eqtag << " failed." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
return eqnumbers;
|
return eqnumbers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6618,9 +6803,12 @@ DynamicModel::addStaticOnlyEquation(expr_t eq, int lineno, const vector<pair<str
|
||||||
for (const auto & eq_tag : eq_tags)
|
for (const auto & eq_tag : eq_tags)
|
||||||
soe_eq_tags.push_back(eq_tag);
|
soe_eq_tags.push_back(eq_tag);
|
||||||
|
|
||||||
|
int n = static_only_equations.size();
|
||||||
static_only_equations.push_back(beq);
|
static_only_equations.push_back(beq);
|
||||||
static_only_equations_lineno.push_back(lineno);
|
static_only_equations_lineno.push_back(lineno);
|
||||||
static_only_equations_equation_tags.push_back(soe_eq_tags);
|
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
|
size_t
|
||||||
|
|
|
@ -56,6 +56,9 @@ private:
|
||||||
//! Stores the equation tags of equations declared as [static]
|
//! Stores the equation tags of equations declared as [static]
|
||||||
vector<vector<pair<string, string>>> static_only_equations_equation_tags;
|
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;
|
||||||
|
|
||||||
using deriv_id_table_t = map<pair<int, int>, int>;
|
using deriv_id_table_t = map<pair<int, int>, int>;
|
||||||
//! Maps a pair (symbol_id, lag) to a deriv ID
|
//! Maps a pair (symbol_id, lag) to a deriv ID
|
||||||
deriv_id_table_t deriv_id_table;
|
deriv_id_table_t deriv_id_table;
|
||||||
|
@ -266,6 +269,32 @@ private:
|
||||||
pointers into their equivalent in the new tree */
|
pointers into their equivalent in the new tree */
|
||||||
void copyHelper(const DynamicModel &m);
|
void copyHelper(const DynamicModel &m);
|
||||||
|
|
||||||
|
// Internal helper functions for includeExcludeEquations()
|
||||||
|
/*! Handles parsing of argument passed to exclude_eqs/include_eqs*/
|
||||||
|
/*
|
||||||
|
Expects command line arguments of the form:
|
||||||
|
* filename.txt
|
||||||
|
* eq1
|
||||||
|
* ['eq 1', 'eq 2']
|
||||||
|
* [tagname='eq 1']
|
||||||
|
* [tagname=('eq 1', 'eq 2')]
|
||||||
|
If argument is a file, the file should be formatted as:
|
||||||
|
eq 1
|
||||||
|
eq 2
|
||||||
|
OR
|
||||||
|
tagname=
|
||||||
|
X
|
||||||
|
Y
|
||||||
|
*/
|
||||||
|
void parseIncludeExcludeEquations(const string &inc_exc_eq_tags, set<pair<string, string>> & eq_tag_set, bool exclude_eqs);
|
||||||
|
|
||||||
|
// General function that removes leading/trailing whitespace from a string
|
||||||
|
inline void removeLeadingTrailingWhitespace(string & str)
|
||||||
|
{
|
||||||
|
str.erase(0, str.find_first_not_of("\t\n\v\f\r "));
|
||||||
|
str.erase(str.find_last_not_of("\t\n\v\f\r ") + 1);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DynamicModel(SymbolTable &symbol_table_arg,
|
DynamicModel(SymbolTable &symbol_table_arg,
|
||||||
NumericalConstants &num_constants_arg,
|
NumericalConstants &num_constants_arg,
|
||||||
|
@ -397,6 +426,9 @@ public:
|
||||||
//! Set the max leads/lags of the original model
|
//! Set the max leads/lags of the original model
|
||||||
void setLeadsLagsOrig();
|
void setLeadsLagsOrig();
|
||||||
|
|
||||||
|
//! Removes equations from the model according to name tags
|
||||||
|
void includeExcludeEquations(const string & eqs, bool exclude_eqs);
|
||||||
|
|
||||||
//! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous
|
//! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous
|
||||||
void computeRamseyPolicyFOCs(const StaticModel &static_model);
|
void computeRamseyPolicyFOCs(const StaticModel &static_model);
|
||||||
//! Replaces the model equations in dynamic_model with those in this model
|
//! Replaces the model equations in dynamic_model with those in this model
|
||||||
|
|
|
@ -46,6 +46,7 @@ void main2(stringstream &in, const string &basename, bool debug, bool clear_all,
|
||||||
WarningConsolidation &warnings_arg, bool nostrict, bool stochastic, bool check_model_changes,
|
WarningConsolidation &warnings_arg, bool nostrict, bool stochastic, bool check_model_changes,
|
||||||
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
|
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
|
||||||
LanguageOutputType lang, int params_derivs_order, bool transform_unary_ops,
|
LanguageOutputType lang, int params_derivs_order, bool transform_unary_ops,
|
||||||
|
const string &exclude_eqs, const string &include_eqs,
|
||||||
JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple,
|
JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple,
|
||||||
const string &mexext, const filesystem::path &matlabroot,
|
const string &mexext, const filesystem::path &matlabroot,
|
||||||
const filesystem::path &dynareroot, bool onlymodel);
|
const filesystem::path &dynareroot, bool onlymodel);
|
||||||
|
@ -60,7 +61,7 @@ usage()
|
||||||
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]"
|
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]"
|
||||||
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
|
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
|
||||||
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=matlab|julia]"
|
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=matlab|julia]"
|
||||||
<< " [params_derivs_order=0|1|2] [transform_unary_ops]"
|
<< " [params_derivs_order=0|1|2] [transform_unary_ops] [exclude_eqs=<equation_tag_list_or_file>] [include_eqs=<equation_tag_list_or_file>]"
|
||||||
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]"
|
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]"
|
||||||
<< " [mexext=<extension>] [matlabroot=<path>] [onlymodel]"
|
<< " [mexext=<extension>] [matlabroot=<path>] [onlymodel]"
|
||||||
<< endl;
|
<< endl;
|
||||||
|
@ -154,6 +155,7 @@ main(int argc, char **argv)
|
||||||
bool minimal_workspace = false;
|
bool minimal_workspace = false;
|
||||||
bool compute_xrefs = false;
|
bool compute_xrefs = false;
|
||||||
bool transform_unary_ops = false;
|
bool transform_unary_ops = false;
|
||||||
|
string exclude_eqs, include_eqs;
|
||||||
vector<pair<string, string>> defines;
|
vector<pair<string, string>> defines;
|
||||||
vector<filesystem::path> paths;
|
vector<filesystem::path> paths;
|
||||||
FileOutputType output_mode{FileOutputType::none};
|
FileOutputType output_mode{FileOutputType::none};
|
||||||
|
@ -371,6 +373,24 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
mexext = s.substr(7);
|
mexext = s.substr(7);
|
||||||
}
|
}
|
||||||
|
else if (s.substr(0, 11) == "exclude_eqs")
|
||||||
|
{
|
||||||
|
if (s.length() <= 12 || s.at(11) != '=')
|
||||||
|
{
|
||||||
|
cerr << "Incorrect syntax for exclude_eqs option" << endl;
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
exclude_eqs = s.substr(12);
|
||||||
|
}
|
||||||
|
else if (s.substr(0, 11) == "include_eqs")
|
||||||
|
{
|
||||||
|
if (s.length() <= 12 || s.at(11) != '=')
|
||||||
|
{
|
||||||
|
cerr << "Incorrect syntax for include_eqs option" << endl;
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
include_eqs = s.substr(12);
|
||||||
|
}
|
||||||
else if (s.substr(0, 10) == "matlabroot")
|
else if (s.substr(0, 10) == "matlabroot")
|
||||||
{
|
{
|
||||||
if (s.length() <= 11 || s.at(10) != '=')
|
if (s.length() <= 11 || s.at(10) != '=')
|
||||||
|
@ -418,11 +438,17 @@ main(int argc, char **argv)
|
||||||
if (only_macro)
|
if (only_macro)
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
|
if (!exclude_eqs.empty() && !include_eqs.empty())
|
||||||
|
{
|
||||||
|
cerr << "You may only pass one of `include_eqs` and `exclude_eqs`" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
// Do the rest
|
// Do the rest
|
||||||
main2(macro_output, basename, debug, clear_all, clear_global,
|
main2(macro_output, basename, debug, clear_all, clear_global,
|
||||||
no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive,
|
no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive,
|
||||||
parallel, config_file, warnings, nostrict, stochastic, check_model_changes, minimal_workspace,
|
parallel, config_file, warnings, nostrict, stochastic, check_model_changes, minimal_workspace,
|
||||||
compute_xrefs, output_mode, language, params_derivs_order, transform_unary_ops,
|
compute_xrefs, output_mode, language, params_derivs_order, transform_unary_ops, exclude_eqs, include_eqs,
|
||||||
json, json_output_mode, onlyjson, jsonderivsimple,
|
json, json_output_mode, onlyjson, jsonderivsimple,
|
||||||
mexext, matlabroot, dynareroot, onlymodel);
|
mexext, matlabroot, dynareroot, onlymodel);
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ main2(stringstream &in, const string &basename, bool debug, bool clear_all, bool
|
||||||
WarningConsolidation &warnings, bool nostrict, bool stochastic, bool check_model_changes,
|
WarningConsolidation &warnings, bool nostrict, bool stochastic, bool check_model_changes,
|
||||||
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
|
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
|
||||||
LanguageOutputType language, int params_derivs_order, bool transform_unary_ops,
|
LanguageOutputType language, int params_derivs_order, bool transform_unary_ops,
|
||||||
|
const string &exclude_eqs, const string &include_eqs,
|
||||||
JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple,
|
JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple,
|
||||||
const string &mexext, const filesystem::path &matlabroot,
|
const string &mexext, const filesystem::path &matlabroot,
|
||||||
const filesystem::path &dynareroot, bool onlymodel)
|
const filesystem::path &dynareroot, bool onlymodel)
|
||||||
|
@ -51,7 +52,8 @@ main2(stringstream &in, const string &basename, bool debug, bool clear_all, bool
|
||||||
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
|
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
|
||||||
|
|
||||||
// Perform transformations on the model (creation of auxiliary vars and equations)
|
// Perform transformations on the model (creation of auxiliary vars and equations)
|
||||||
mod_file->transformPass(nostrict, stochastic, compute_xrefs || json == JsonOutputPointType::transformpass, transform_unary_ops);
|
mod_file->transformPass(nostrict, stochastic, compute_xrefs || json == JsonOutputPointType::transformpass,
|
||||||
|
transform_unary_ops, exclude_eqs, include_eqs);
|
||||||
if (json == JsonOutputPointType::transformpass)
|
if (json == JsonOutputPointType::transformpass)
|
||||||
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
|
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
|
||||||
|
|
||||||
|
|
|
@ -839,6 +839,11 @@ VariableNode::prepareForDerivation()
|
||||||
case SymbolType::epilogue:
|
case SymbolType::epilogue:
|
||||||
cerr << "VariableNode::prepareForDerivation: impossible case" << endl;
|
cerr << "VariableNode::prepareForDerivation: impossible case" << endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
case SymbolType::excludedVariable:
|
||||||
|
cerr << "VariableNode::prepareForDerivation: impossible case: "
|
||||||
|
<< "You are trying to derive a variable that has been excluded via include_eqs/exclude_eqs: "
|
||||||
|
<< datatree.symbol_table.getName(symb_id) << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -871,6 +876,7 @@ VariableNode::computeDerivative(int deriv_id)
|
||||||
case SymbolType::externalFunction:
|
case SymbolType::externalFunction:
|
||||||
case SymbolType::endogenousVAR:
|
case SymbolType::endogenousVAR:
|
||||||
case SymbolType::epilogue:
|
case SymbolType::epilogue:
|
||||||
|
case SymbolType::excludedVariable:
|
||||||
cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
|
cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -939,6 +945,9 @@ VariableNode::writeJsonAST(ostream &output) const
|
||||||
case SymbolType::epilogue:
|
case SymbolType::epilogue:
|
||||||
output << "epilogue";
|
output << "epilogue";
|
||||||
break;
|
break;
|
||||||
|
case SymbolType::excludedVariable:
|
||||||
|
cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
output << R"(", "lag" : )" << lag << "}";
|
output << R"(", "lag" : )" << lag << "}";
|
||||||
}
|
}
|
||||||
|
@ -1220,6 +1229,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|
||||||
case SymbolType::logTrend:
|
case SymbolType::logTrend:
|
||||||
case SymbolType::statementDeclaredVariable:
|
case SymbolType::statementDeclaredVariable:
|
||||||
case SymbolType::endogenousVAR:
|
case SymbolType::endogenousVAR:
|
||||||
|
case SymbolType::excludedVariable:
|
||||||
cerr << "VariableNode::writeOutput: Impossible case" << endl;
|
cerr << "VariableNode::writeOutput: Impossible case" << endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -1439,6 +1449,7 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recur
|
||||||
case SymbolType::externalFunction:
|
case SymbolType::externalFunction:
|
||||||
case SymbolType::endogenousVAR:
|
case SymbolType::endogenousVAR:
|
||||||
case SymbolType::epilogue:
|
case SymbolType::epilogue:
|
||||||
|
case SymbolType::excludedVariable:
|
||||||
cerr << "VariableNode::getChainRuleDerivative: Impossible case" << endl;
|
cerr << "VariableNode::getChainRuleDerivative: Impossible case" << endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -1478,6 +1489,7 @@ VariableNode::computeXrefs(EquationInfo &ei) const
|
||||||
case SymbolType::externalFunction:
|
case SymbolType::externalFunction:
|
||||||
case SymbolType::endogenousVAR:
|
case SymbolType::endogenousVAR:
|
||||||
case SymbolType::epilogue:
|
case SymbolType::epilogue:
|
||||||
|
case SymbolType::excludedVariable:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,7 +381,8 @@ ModFile::checkPass(bool nostrict, bool stochastic)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool transform_unary_ops)
|
ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool transform_unary_ops,
|
||||||
|
const string &exclude_eqs, const string &include_eqs)
|
||||||
{
|
{
|
||||||
/* Save the original model (must be done before any model transformations by preprocessor)
|
/* Save the original model (must be done before any model transformations by preprocessor)
|
||||||
— except substituting out variables which we know are constant (they
|
— except substituting out variables which we know are constant (they
|
||||||
|
@ -390,6 +391,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
|
||||||
— except diff operators with a lead which have been expanded by
|
— except diff operators with a lead which have been expanded by
|
||||||
DataTree:AddDiff()
|
DataTree:AddDiff()
|
||||||
*/
|
*/
|
||||||
|
dynamic_model.includeExcludeEquations(exclude_eqs, true);
|
||||||
|
dynamic_model.includeExcludeEquations(include_eqs, false);
|
||||||
dynamic_model.simplifyEquations();
|
dynamic_model.simplifyEquations();
|
||||||
dynamic_model.substituteAdl();
|
dynamic_model.substituteAdl();
|
||||||
dynamic_model.setLeadsLagsOrig();
|
dynamic_model.setLeadsLagsOrig();
|
||||||
|
|
|
@ -146,7 +146,8 @@ public:
|
||||||
void checkPass(bool nostrict, bool stochastic);
|
void checkPass(bool nostrict, bool stochastic);
|
||||||
//! Perform some transformations on the model (creation of auxiliary vars and equations)
|
//! Perform some transformations on the model (creation of auxiliary vars and equations)
|
||||||
/*! \param compute_xrefs if true, equation cross references will be computed */
|
/*! \param compute_xrefs if true, equation cross references will be computed */
|
||||||
void transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool transform_unary_ops);
|
void transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool transform_unary_ops,
|
||||||
|
const string &exclude_eqs, const string &include_eqs);
|
||||||
//! Execute computations
|
//! Execute computations
|
||||||
/*! \param no_tmp_terms if true, no temporary terms will be computed in the static and dynamic files */
|
/*! \param no_tmp_terms if true, no temporary terms will be computed in the static and dynamic files */
|
||||||
/*! \param params_derivs_order compute this order of derivs wrt parameters */
|
/*! \param params_derivs_order compute this order of derivs wrt parameters */
|
||||||
|
|
|
@ -1934,6 +1934,104 @@ ModelTree::addEquation(expr_t eq, int lineno)
|
||||||
equations_lineno.push_back(lineno);
|
equations_lineno.push_back(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
|
||||||
|
{
|
||||||
|
vector<int> excluded_vars;
|
||||||
|
if (equations.empty())
|
||||||
|
return excluded_vars;
|
||||||
|
|
||||||
|
// Get equation numbers of tags
|
||||||
|
set<int> tag_eqns;
|
||||||
|
for (auto & it : eqs)
|
||||||
|
if (equation_tags_xref.find(it) != equation_tags_xref.end())
|
||||||
|
{
|
||||||
|
auto range = equation_tags_xref.equal_range(it);
|
||||||
|
for_each ( range.first, range.second, [&tag_eqns](auto & x){ tag_eqns.insert(x.second); } );
|
||||||
|
eqs.erase(it);
|
||||||
|
}
|
||||||
|
if (tag_eqns.empty())
|
||||||
|
return excluded_vars;
|
||||||
|
|
||||||
|
set<int> eqns;
|
||||||
|
if (exclude_eqs)
|
||||||
|
eqns = tag_eqns;
|
||||||
|
else
|
||||||
|
for (size_t i = 0; i < equations.size(); i++)
|
||||||
|
if (tag_eqns.find(i) == tag_eqns.end())
|
||||||
|
eqns.insert(i);
|
||||||
|
|
||||||
|
// remove from equations, equations_lineno, equation_tags, equation_tags_xref
|
||||||
|
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 & it : equation_tags)
|
||||||
|
if (it.first == static_cast<int>(i) && it.second.first == "endogenous")
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
excluded_vars.push_back(symbol_table.getID(it.second.second));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
set<pair<int, int>> result;
|
||||||
|
equations[i]->arg1->collectDynamicVariables(SymbolType::endogenous, result);
|
||||||
|
if (result.size() == 1)
|
||||||
|
excluded_vars.push_back(result.begin()->first);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Equation " << i
|
||||||
|
<< " has been excluded but does not have a single variable on LHS or `endogenous` tag" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_eqns.emplace_back(equations[i]);
|
||||||
|
old_eqn_num_2_new[i] = new_eqns.size() - 1;
|
||||||
|
new_equations_lineno.emplace_back(equations_lineno[i]);
|
||||||
|
}
|
||||||
|
int n_excl = equations.size() - new_eqns.size();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!static_equations)
|
||||||
|
for (size_t i = 0; i < excluded_vars.size(); i++)
|
||||||
|
for (size_t j = i+1; j < excluded_vars.size(); j++)
|
||||||
|
if (excluded_vars[i] == excluded_vars[j])
|
||||||
|
{
|
||||||
|
cerr << "Error: Variable " << symbol_table.getName(i) << " was excluded twice"
|
||||||
|
<< " via in/exclude_eqs option" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "Excluded " << n_excl << (static_equations ? " static " : " dynamic ")
|
||||||
|
<< "equation" << (n_excl > 1 ? "s" : "" ) << " via in/exclude_eqs option" << endl;
|
||||||
|
|
||||||
|
return excluded_vars;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ModelTree::simplifyEquations()
|
ModelTree::simplifyEquations()
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,13 +75,10 @@ protected:
|
||||||
*/
|
*/
|
||||||
//! Stores declared and generated auxiliary equations
|
//! Stores declared and generated auxiliary equations
|
||||||
vector<BinaryOpNode *> equations;
|
vector<BinaryOpNode *> equations;
|
||||||
|
|
||||||
//! Stores line numbers of declared equations; -1 means undefined
|
//! Stores line numbers of declared equations; -1 means undefined
|
||||||
vector<int> equations_lineno;
|
vector<int> equations_lineno;
|
||||||
|
|
||||||
//! Stores equation tags
|
//! Stores equation tags
|
||||||
vector<pair<int, pair<string, string>>> equation_tags;
|
vector<pair<int, pair<string, string>>> equation_tags;
|
||||||
|
|
||||||
//! Stores mapping from equation tags to equation number
|
//! Stores mapping from equation tags to equation number
|
||||||
multimap<pair<string, string>, int> equation_tags_xref;
|
multimap<pair<string, string>, int> equation_tags_xref;
|
||||||
/*
|
/*
|
||||||
|
@ -262,6 +259,11 @@ protected:
|
||||||
void printBlockDecomposition(const vector<pair<int, int>> &blocks) const;
|
void printBlockDecomposition(const vector<pair<int, int>> &blocks) const;
|
||||||
//! Determine for each block if it is linear or not
|
//! Determine for each block if it is linear or not
|
||||||
vector<bool> BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vector<int> &variable_reordered) const;
|
vector<bool> BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vector<int> &variable_reordered) const;
|
||||||
|
//! 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;
|
||||||
|
|
||||||
//! Determine the simulation type of each block
|
//! Determine the simulation type of each block
|
||||||
virtual BlockSimulationType getBlockSimulationType(int block_number) const = 0;
|
virtual BlockSimulationType getBlockSimulationType(int block_number) const = 0;
|
||||||
|
@ -348,6 +350,8 @@ public:
|
||||||
void addEquation(expr_t eq, int lineno);
|
void addEquation(expr_t eq, int lineno);
|
||||||
//! Declare a node as an equation of the model, also giving its tags
|
//! 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 vector<pair<string, string>> &eq_tags);
|
||||||
|
//! Add equation tags to equation tag table
|
||||||
|
void addEquationTagsToTable(const vector<pair<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
|
//! 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);
|
void addAuxEquation(expr_t eq);
|
||||||
//! Returns the number of equations in the model
|
//! Returns the number of equations in the model
|
||||||
|
|
|
@ -148,12 +148,25 @@ InitOrEndValStatement::writeInitValues(ostream &output) const
|
||||||
SymbolType type = symbol_table.getType(symb_id);
|
SymbolType type = symbol_table.getType(symb_id);
|
||||||
int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
|
int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
|
||||||
|
|
||||||
if (type == SymbolType::endogenous)
|
switch (type)
|
||||||
|
{
|
||||||
|
case SymbolType::endogenous:
|
||||||
output << "oo_.steady_state";
|
output << "oo_.steady_state";
|
||||||
else if (type == SymbolType::exogenous)
|
break;
|
||||||
|
case SymbolType::exogenous:
|
||||||
output << "oo_.exo_steady_state";
|
output << "oo_.exo_steady_state";
|
||||||
else if (type == SymbolType::exogenousDet)
|
break;
|
||||||
|
case SymbolType::exogenousDet:
|
||||||
output << "oo_.exo_det_steady_state";
|
output << "oo_.exo_det_steady_state";
|
||||||
|
break;
|
||||||
|
case SymbolType::excludedVariable:
|
||||||
|
cerr << "ERROR: Variable `" << symbol_table.getName(symb_id)
|
||||||
|
<< "` was excluded but found in an initval or endval statement" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
default:
|
||||||
|
cerr << "Should not arrive here" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
output << "( " << tsid << " ) = ";
|
output << "( " << tsid << " ) = ";
|
||||||
expression->writeOutput(output);
|
expression->writeOutput(output);
|
||||||
|
|
Loading…
Reference in New Issue