Temporary terms: various simplifications and added comments

issue#70
Sébastien Villemot 2018-11-16 16:53:07 +01:00
parent e89dd9cb8b
commit 3d2125287a
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
4 changed files with 49 additions and 56 deletions

View File

@ -2508,16 +2508,13 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
deriv_node_temp_terms_t tef_terms;
temporary_terms_t temp_term_union;
for (auto it : temporary_terms_mlv)
temp_term_union.insert(it.first);
writeModelLocalVariableTemporaryTerms(temp_term_union, temporary_terms_mlv,
writeModelLocalVariableTemporaryTerms(temp_term_union,
model_tt_output, output_type, tef_terms);
writeTemporaryTerms(temporary_terms_derivatives[0],
temp_term_union,
temporary_terms_idxs,
model_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_derivatives[0].begin(), temporary_terms_derivatives[0].end());
writeModelEquations(model_output, output_type, temp_term_union);
@ -2531,7 +2528,6 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
temp_term_union,
temporary_terms_idxs,
jacobian_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_derivatives[1].begin(), temporary_terms_derivatives[1].end());
for (const auto & first_derivative : derivatives[1])
{
@ -2554,7 +2550,6 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
temp_term_union,
temporary_terms_idxs,
hessian_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_derivatives[2].begin(), temporary_terms_derivatives[2].end());
int k = 0; // Keep the line of a 2nd derivative in v2
for (const auto & second_derivative : derivatives[2])
@ -2623,7 +2618,6 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
temp_term_union,
temporary_terms_idxs,
third_derivatives_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_derivatives[3].begin(), temporary_terms_derivatives[3].end());
int k = 0; // Keep the line of a 3rd derivative in v3
for (const auto & third_derivative : derivatives[3])
@ -5389,9 +5383,10 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con
ostringstream third_derivs_output; // Used for storing third order derivatives equations
ostringstream third_derivs1_output; // Used for storing third order derivatives equations
temporary_terms_t temp_term_union;
deriv_node_temp_terms_t tef_terms;
writeTemporaryTerms(params_derivs_temporary_terms, {}, params_derivs_temporary_terms_idxs, model_output, output_type, tef_terms);
writeTemporaryTerms(params_derivs_temporary_terms, temp_term_union, params_derivs_temporary_terms_idxs, model_output, output_type, tef_terms);
for (const auto & residuals_params_derivative : params_derivatives.find({ 0, 1 })->second)
{

View File

@ -1361,17 +1361,18 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms)
temporary_terms_derivatives.clear();
temporary_terms_derivatives.resize(4);
// Collect all model local variables appearing in equations. See #101
// All used model local variables are automatically set as temporary variables
/* Collect all model local variables appearing in equations (and only those,
because printing unused model local variables can lead to a crash,
see Dynare/dynare#101).
Then store them in a dedicated structure (temporary_terms_mlv), that will
be treated as the rest of temporary terms. */
set<int> used_local_vars;
for (auto & equation : equations)
equation->collectVariables(SymbolType::modelLocalVariable, used_local_vars);
for (int used_local_var : used_local_vars)
{
VariableNode *v = AddVariable(used_local_var);
temporary_terms_mlv[v] = local_variables_table.find(used_local_var)->second;
reference_count[v] = { ExprNode::min_cost(is_matlab)+1, NodeTreeReference::residuals };
}
map<NodeTreeReference, temporary_terms_t> temp_terms_map;
@ -1413,9 +1414,8 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms)
temporary_terms_derivatives[3] = temp_terms_map[NodeTreeReference::thirdDeriv];
int idx = 0;
for (map<expr_t, expr_t, ExprNodeLess>::const_iterator it = temporary_terms_mlv.begin();
it != temporary_terms_mlv.end(); it++)
temporary_terms_idxs[it->first] = idx++;
for (auto &it : temporary_terms_mlv)
temporary_terms_idxs[it.first] = idx++;
for (auto it : temporary_terms_derivatives[0])
temporary_terms_idxs[it] = idx++;
@ -1431,56 +1431,57 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms)
}
void
ModelTree::writeModelLocalVariableTemporaryTerms(const temporary_terms_t &tto, const map<expr_t, expr_t, ExprNodeLess> &tt,
ModelTree::writeModelLocalVariableTemporaryTerms(temporary_terms_t &temp_term_union,
ostream &output, ExprNodeOutputType output_type,
deriv_node_temp_terms_t &tef_terms) const
{
temporary_terms_t tt2;
for (auto it : tt)
temporary_terms_t tto;
for (auto it : temporary_terms_mlv)
tto.insert(it.first);
for (auto &it : temporary_terms_mlv)
{
if (isJuliaOutput(output_type))
output << " @inbounds const ";
it.first->writeOutput(output, output_type, tto, temporary_terms_idxs, tef_terms);
output << " = ";
it.second->writeOutput(output, output_type, tt2, temporary_terms_idxs, tef_terms);
it.second->writeOutput(output, output_type, temp_term_union, temporary_terms_idxs, tef_terms);
if (isCOutput(output_type) || isMatlabOutput(output_type))
output << ";";
output << endl;
// Insert current node into tt2
tt2.insert(it.first);
/* We put in temp_term_union the VariableNode corresponding to the MLV,
not its definition, so that when equations use the MLV,
T(XXX) is printed instead of the MLV name */
temp_term_union.insert(it.first);
}
}
void
ModelTree::writeTemporaryTerms(const temporary_terms_t &tt,
const temporary_terms_t &ttm1,
temporary_terms_t &temp_term_union,
const temporary_terms_idxs_t &tt_idxs,
ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const
{
// Local var used to keep track of temp nodes already written
temporary_terms_t tt2 = ttm1;
for (auto it = tt.begin();
it != tt.end(); it++)
for (auto it : tt)
{
if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != nullptr)
(*it)->writeExternalFunctionOutput(output, output_type, tt2, tt_idxs, tef_terms);
if (dynamic_cast<AbstractExternalFunctionNode *>(it) != nullptr)
it->writeExternalFunctionOutput(output, output_type, temp_term_union, tt_idxs, tef_terms);
if (isJuliaOutput(output_type))
output << " @inbounds ";
(*it)->writeOutput(output, output_type, tt, tt_idxs, tef_terms);
it->writeOutput(output, output_type, tt, tt_idxs, tef_terms);
output << " = ";
(*it)->writeOutput(output, output_type, tt2, tt_idxs, tef_terms);
it->writeOutput(output, output_type, temp_term_union, tt_idxs, tef_terms);
if (isCOutput(output_type) || isMatlabOutput(output_type))
output << ";";
output << endl;
// Insert current node into tt2
tt2.insert(*it);
temp_term_union.insert(it);
}
}

View File

@ -107,10 +107,11 @@ protected:
the derivation IDs of endogenous, then the IDs of parameters */
map<pair<int,int>, map<vector<int>, expr_t>> params_derivatives;
//! Temporary terms for the static/dynamic file (those which will be noted T[x])
//! Storage for temporary terms in block/bytecode mode
temporary_terms_t temporary_terms;
//! Temporary terms for model local variables
//! Used model local variables, that will be treated as temporary terms
/*! See the comments in ModelTree::computeTemporaryTerms() */
map<expr_t, expr_t, ExprNodeLess> temporary_terms_mlv;
//! Temporary terms for residuals and derivatives
@ -164,7 +165,7 @@ protected:
//! Computes temporary terms for the file containing parameters derivatives
void computeParamsDerivativesTemporaryTerms();
//! Writes temporary terms
void writeTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
void writeTemporaryTerms(const temporary_terms_t &tt, temporary_terms_t &temp_term_union, const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
void writeJsonTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, ostream &output, deriv_node_temp_terms_t &tef_terms, string &concat) const;
//! Compiles temporary terms
void compileTemporaryTerms(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, map_idx_t map_idx, bool dynamic, bool steady_dynamic) const;
@ -174,7 +175,7 @@ protected:
void fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_paren_vars, bool &message_printed) const;
//! Tests if string contains more than 32 nested parens, Issue #1201
bool testNestedParenthesis(const string &str) const;
void writeModelLocalVariableTemporaryTerms(const temporary_terms_t &tto, const map<expr_t, expr_t, ExprNodeLess> &tt,
void writeModelLocalVariableTemporaryTerms(temporary_terms_t &temp_term_union,
ostream &output, ExprNodeOutputType output_type,
deriv_node_temp_terms_t &tef_terms) const;
//! Writes model equations

View File

@ -1519,16 +1519,13 @@ StaticModel::writeStaticModel(const string &basename,
deriv_node_temp_terms_t tef_terms;
temporary_terms_t temp_term_union;
for (auto it : temporary_terms_mlv)
temp_term_union.insert(it.first);
writeModelLocalVariableTemporaryTerms(temp_term_union, temporary_terms_mlv,
writeModelLocalVariableTemporaryTerms(temp_term_union,
model_tt_output, output_type, tef_terms);
writeTemporaryTerms(temporary_terms_derivatives[0],
temp_term_union,
temporary_terms_idxs,
model_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_derivatives[0].begin(), temporary_terms_derivatives[0].end());
writeModelEquations(model_output, output_type, temp_term_union);
@ -1543,20 +1540,20 @@ StaticModel::writeStaticModel(const string &basename,
temp_term_union,
temporary_terms_idxs,
jacobian_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_derivatives[1].begin(), temporary_terms_derivatives[1].end());
}
for (const auto & first_derivative : derivatives[1])
{
int eq, var;
tie(eq, var) = vectorToTuple<2>(first_derivative.first);
expr_t d1 = first_derivative.second;
int symb_id = getSymbIDByDerivID(var);
jacobianHelper(jacobian_output, eq, symbol_table.getTypeSpecificID(symb_id), output_type);
jacobian_output << "=";
d1->writeOutput(jacobian_output, output_type,
temp_term_union, temporary_terms_idxs, tef_terms);
jacobian_output << ";" << endl;
for (const auto & first_derivative : derivatives[1])
{
int eq, var;
tie(eq, var) = vectorToTuple<2>(first_derivative.first);
expr_t d1 = first_derivative.second;
int symb_id = getSymbIDByDerivID(var);
jacobianHelper(jacobian_output, eq, symbol_table.getTypeSpecificID(symb_id), output_type);
jacobian_output << "=";
d1->writeOutput(jacobian_output, output_type,
temp_term_union, temporary_terms_idxs, tef_terms);
jacobian_output << ";" << endl;
}
}
int g2ncols = symbol_table.endo_nbr() * symbol_table.endo_nbr();
@ -1567,7 +1564,6 @@ StaticModel::writeStaticModel(const string &basename,
temp_term_union,
temporary_terms_idxs,
hessian_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_derivatives[2].begin(), temporary_terms_derivatives[2].end());
int k = 0; // Keep the line of a 2nd derivative in v2
for (const auto & second_derivative : derivatives[2])
@ -1638,7 +1634,6 @@ StaticModel::writeStaticModel(const string &basename,
temp_term_union,
temporary_terms_idxs,
third_derivatives_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_derivatives[3].begin(), temporary_terms_derivatives[3].end());
int k = 0; // Keep the line of a 3rd derivative in v3
for (const auto & third_derivative : derivatives[3])
@ -2653,9 +2648,10 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons
ostringstream third_derivs_output; // Used for storing third order derivatives equations
ostringstream third_derivs1_output; // Used for storing third order derivatives equations
temporary_terms_t temp_term_union;
deriv_node_temp_terms_t tef_terms;
writeTemporaryTerms(params_derivs_temporary_terms, {}, params_derivs_temporary_terms_idxs, model_output, output_type, tef_terms);
writeTemporaryTerms(params_derivs_temporary_terms, temp_term_union, params_derivs_temporary_terms_idxs, tt_output, output_type, tef_terms);
for (const auto & residuals_params_derivative : params_derivatives.find({ 0, 1 })->second)
{