Merge branch 'exclude_eqs' into 'master'

introduce command line options: `exclude_eqs` and `include_eqs`

See merge request Dynare/preprocessor!7
issue#70
Sébastien Villemot 2019-11-26 15:04:00 +00:00
commit 8be9efa425
11 changed files with 400 additions and 20 deletions

View File

@ -150,7 +150,8 @@ enum class SymbolType
logTrend = 15, //!< Log-trend variable
unusedEndogenous = 16, //!< Type to mark unused endogenous variables when `nostrict` option is passed
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

View File

@ -23,6 +23,7 @@
#include <cassert>
#include <algorithm>
#include <numeric>
#include <regex>
#include "DynamicModel.hh"
@ -103,6 +104,7 @@ 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},
@ -165,6 +167,7 @@ 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;
@ -2930,6 +2933,179 @@ DynamicModel::writeDynamicJacobianNonZeroElts(const string &basename) const
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
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;
for (auto & eqtag : eqtags)
for (const auto & equation_tag : equation_tags)
if (equation_tag.second.first == "name"
&& equation_tag.second.second == eqtag)
{
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)
{
eqnumbers.push_back(equation_tag.first);
break;
cerr << "ERROR: looking for equation tag " << eqtag << " failed." << endl;
exit(EXIT_FAILURE);
}
}
return eqnumbers;
}
@ -6618,9 +6803,12 @@ DynamicModel::addStaticOnlyEquation(expr_t eq, int lineno, const vector<pair<str
for (const auto & eq_tag : eq_tags)
soe_eq_tags.push_back(eq_tag);
int n = static_only_equations.size();
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

View File

@ -56,6 +56,9 @@ private:
//! 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;
using deriv_id_table_t = map<pair<int, int>, int>;
//! Maps a pair (symbol_id, lag) to a deriv ID
deriv_id_table_t deriv_id_table;
@ -266,6 +269,32 @@ private:
pointers into their equivalent in the new tree */
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:
DynamicModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
@ -397,6 +426,9 @@ public:
//! Set the max leads/lags of the original model
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
void computeRamseyPolicyFOCs(const StaticModel &static_model);
//! Replaces the model equations in dynamic_model with those in this model

View File

@ -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,
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
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,
const string &mexext, const filesystem::path &matlabroot,
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]"
<< " [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]"
<< " [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]"
<< " [mexext=<extension>] [matlabroot=<path>] [onlymodel]"
<< endl;
@ -154,6 +155,7 @@ main(int argc, char **argv)
bool minimal_workspace = false;
bool compute_xrefs = false;
bool transform_unary_ops = false;
string exclude_eqs, include_eqs;
vector<pair<string, string>> defines;
vector<filesystem::path> paths;
FileOutputType output_mode{FileOutputType::none};
@ -371,6 +373,24 @@ main(int argc, char **argv)
}
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")
{
if (s.length() <= 11 || s.at(10) != '=')
@ -418,11 +438,17 @@ main(int argc, char **argv)
if (only_macro)
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
main2(macro_output, basename, debug, clear_all, clear_global,
no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive,
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,
mexext, matlabroot, dynareroot, onlymodel);

View File

@ -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,
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
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,
const string &mexext, const filesystem::path &matlabroot,
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);
// 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)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);

View File

@ -839,6 +839,11 @@ VariableNode::prepareForDerivation()
case SymbolType::epilogue:
cerr << "VariableNode::prepareForDerivation: impossible case" << endl;
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::endogenousVAR:
case SymbolType::epilogue:
case SymbolType::excludedVariable:
cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
exit(EXIT_FAILURE);
}
@ -939,6 +945,9 @@ VariableNode::writeJsonAST(ostream &output) const
case SymbolType::epilogue:
output << "epilogue";
break;
case SymbolType::excludedVariable:
cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
exit(EXIT_FAILURE);
}
output << R"(", "lag" : )" << lag << "}";
}
@ -1220,6 +1229,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case SymbolType::logTrend:
case SymbolType::statementDeclaredVariable:
case SymbolType::endogenousVAR:
case SymbolType::excludedVariable:
cerr << "VariableNode::writeOutput: Impossible case" << endl;
exit(EXIT_FAILURE);
}
@ -1439,6 +1449,7 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recur
case SymbolType::externalFunction:
case SymbolType::endogenousVAR:
case SymbolType::epilogue:
case SymbolType::excludedVariable:
cerr << "VariableNode::getChainRuleDerivative: Impossible case" << endl;
exit(EXIT_FAILURE);
}
@ -1478,6 +1489,7 @@ VariableNode::computeXrefs(EquationInfo &ei) const
case SymbolType::externalFunction:
case SymbolType::endogenousVAR:
case SymbolType::epilogue:
case SymbolType::excludedVariable:
break;
}
}

View File

@ -381,7 +381,8 @@ ModFile::checkPass(bool nostrict, bool stochastic)
}
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)
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
DataTree:AddDiff()
*/
dynamic_model.includeExcludeEquations(exclude_eqs, true);
dynamic_model.includeExcludeEquations(include_eqs, false);
dynamic_model.simplifyEquations();
dynamic_model.substituteAdl();
dynamic_model.setLeadsLagsOrig();

View File

@ -146,7 +146,8 @@ public:
void checkPass(bool nostrict, bool stochastic);
//! Perform some transformations on the model (creation of auxiliary vars and equations)
/*! \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
/*! \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 */

View File

@ -1934,6 +1934,104 @@ ModelTree::addEquation(expr_t eq, int 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
ModelTree::simplifyEquations()
{

View File

@ -75,13 +75,10 @@ protected:
*/
//! Stores declared and generated auxiliary equations
vector<BinaryOpNode *> equations;
//! 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;
/*
@ -262,6 +259,11 @@ protected:
void printBlockDecomposition(const vector<pair<int, int>> &blocks) const;
//! 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;
//! 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
virtual BlockSimulationType getBlockSimulationType(int block_number) const = 0;
@ -348,6 +350,8 @@ public:
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);
//! 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
void addAuxEquation(expr_t eq);
//! Returns the number of equations in the model

View File

@ -148,12 +148,25 @@ InitOrEndValStatement::writeInitValues(ostream &output) const
SymbolType type = symbol_table.getType(symb_id);
int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
if (type == SymbolType::endogenous)
output << "oo_.steady_state";
else if (type == SymbolType::exogenous)
output << "oo_.exo_steady_state";
else if (type == SymbolType::exogenousDet)
output << "oo_.exo_det_steady_state";
switch (type)
{
case SymbolType::endogenous:
output << "oo_.steady_state";
break;
case SymbolType::exogenous:
output << "oo_.exo_steady_state";
break;
case SymbolType::exogenousDet:
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 << " ) = ";
expression->writeOutput(output);