Optimization: use std::unordered_map instead of std::map when computing temporary terms

Improve performance on very large models (⩾ 5000 equations).

Note that std::unordered_set cannot be used for the temporary_terms_t type,
because ordering is needed there (for writing the output files).
master
Sébastien Villemot 2023-04-05 14:53:47 +02:00
parent e22d9049ee
commit 5a4297088d
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
4 changed files with 102 additions and 82 deletions

View File

@ -104,7 +104,7 @@ ExprNode::cost([[maybe_unused]] int cost, [[maybe_unused]] bool is_matlab) const
}
int
ExprNode::cost([[maybe_unused]] const vector<vector<temporary_terms_t>> &blocks_temporary_terms,
ExprNode::cost([[maybe_unused]] const vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
[[maybe_unused]] bool is_matlab) const
{
// For a terminal node, the cost is null
@ -112,7 +112,7 @@ ExprNode::cost([[maybe_unused]] const vector<vector<temporary_terms_t>> &blocks_
}
int
ExprNode::cost([[maybe_unused]] const map<pair<int, int>, temporary_terms_t> &temp_terms_map,
ExprNode::cost([[maybe_unused]] const map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
[[maybe_unused]] bool is_matlab) const
{
// For a terminal node, the cost is null
@ -211,8 +211,8 @@ ExprNode::collectEndogenous(set<pair<int, int>> &result) const
void
ExprNode::computeTemporaryTerms([[maybe_unused]] const pair<int, int> &derivOrder,
[[maybe_unused]] map<pair<int, int>, temporary_terms_t> &temp_terms_map,
[[maybe_unused]] map<expr_t, pair<int, pair<int, int>>> &reference_count,
[[maybe_unused]] map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
[[maybe_unused]] unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
[[maybe_unused]] bool is_matlab) const
{
// Nothing to do for a terminal node
@ -220,8 +220,8 @@ ExprNode::computeTemporaryTerms([[maybe_unused]] const pair<int, int> &derivOrde
void
ExprNode::computeBlockTemporaryTerms([[maybe_unused]] int blk, [[maybe_unused]] int eq,
[[maybe_unused]] vector<vector<temporary_terms_t>> &blocks_temporary_terms,
[[maybe_unused]] map<expr_t, tuple<int, int, int>> &reference_count) const
[[maybe_unused]] vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
[[maybe_unused]] unordered_map<expr_t, tuple<int, int, int>> &reference_count) const
{
// Nothing to do for a terminal node
}
@ -2377,7 +2377,7 @@ UnaryOpNode::computeDerivative(int deriv_id)
}
int
UnaryOpNode::cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const
UnaryOpNode::cost(const map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map, bool is_matlab) const
{
// For a temporary term, the cost is null
for (const auto &it : temp_terms_map)
@ -2388,7 +2388,7 @@ UnaryOpNode::cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map,
}
int
UnaryOpNode::cost(const vector<vector<temporary_terms_t>> &blocks_temporary_terms, bool is_matlab) const
UnaryOpNode::cost(const vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms, bool is_matlab) const
{
// For a temporary term, the cost is null
for (const auto &blk_tt : blocks_temporary_terms)
@ -2513,8 +2513,8 @@ UnaryOpNode::cost(int cost, bool is_matlab) const
void
UnaryOpNode::computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const
{
expr_t this2 = const_cast<UnaryOpNode *>(this);
@ -2535,8 +2535,8 @@ UnaryOpNode::computeTemporaryTerms(const pair<int, int> &derivOrder,
}
void
UnaryOpNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const
UnaryOpNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>> &reference_count) const
{
expr_t this2 = const_cast<UnaryOpNode *>(this);
if (auto it = reference_count.find(this2);
@ -4256,7 +4256,7 @@ BinaryOpNode::precedenceJson(const temporary_terms_t &temporary_terms) const
}
int
BinaryOpNode::cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const
BinaryOpNode::cost(const map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map, bool is_matlab) const
{
// For a temporary term, the cost is null
for (const auto &it : temp_terms_map)
@ -4269,7 +4269,7 @@ BinaryOpNode::cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map,
}
int
BinaryOpNode::cost(const vector<vector<temporary_terms_t>> &blocks_temporary_terms, bool is_matlab) const
BinaryOpNode::cost(const vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms, bool is_matlab) const
{
// For a temporary term, the cost is null
for (const auto &blk_tt : blocks_temporary_terms)
@ -4344,8 +4344,8 @@ BinaryOpNode::cost(int cost, bool is_matlab) const
void
BinaryOpNode::computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const
{
expr_t this2 = const_cast<BinaryOpNode *>(this);
@ -4372,8 +4372,8 @@ BinaryOpNode::computeTemporaryTerms(const pair<int, int> &derivOrder,
}
void
BinaryOpNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const
BinaryOpNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>> &reference_count) const
{
expr_t this2 = const_cast<BinaryOpNode *>(this);
if (auto it = reference_count.find(this2);
@ -6009,7 +6009,7 @@ TrinaryOpNode::precedence([[maybe_unused]] ExprNodeOutputType output_type,
}
int
TrinaryOpNode::cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const
TrinaryOpNode::cost(const map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map, bool is_matlab) const
{
// For a temporary term, the cost is null
for (const auto &it : temp_terms_map)
@ -6024,7 +6024,7 @@ TrinaryOpNode::cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map
}
int
TrinaryOpNode::cost(const vector<vector<temporary_terms_t>> &blocks_temporary_terms, bool is_matlab) const
TrinaryOpNode::cost(const vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms, bool is_matlab) const
{
// For a temporary term, the cost is null
for (const auto &blk_tt : blocks_temporary_terms)
@ -6064,8 +6064,8 @@ TrinaryOpNode::cost(int cost, bool is_matlab) const
void
TrinaryOpNode::computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const
{
expr_t this2 = const_cast<TrinaryOpNode *>(this);
@ -6091,8 +6091,8 @@ TrinaryOpNode::computeTemporaryTerms(const pair<int, int> &derivOrder,
}
void
TrinaryOpNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const
TrinaryOpNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>> &reference_count) const
{
expr_t this2 = const_cast<TrinaryOpNode *>(this);
if (auto it = reference_count.find(this2);
@ -7010,8 +7010,8 @@ AbstractExternalFunctionNode::getIndxInTefTerms(int the_symb_id, const deriv_nod
void
AbstractExternalFunctionNode::computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
[[maybe_unused]] map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
[[maybe_unused]] unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
[[maybe_unused]] bool is_matlab) const
{
/* All external function nodes are declared as temporary terms.
@ -7037,8 +7037,8 @@ AbstractExternalFunctionNode::computeTemporaryTerms(const pair<int, int> &derivO
}
void
AbstractExternalFunctionNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
[[maybe_unused]] map<expr_t, tuple<int, int, int>> &reference_count) const
AbstractExternalFunctionNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
[[maybe_unused]] unordered_map<expr_t, tuple<int, int, int>> &reference_count) const
{
// See comments in computeTemporaryTerms() for the logic
expr_t this2 = const_cast<AbstractExternalFunctionNode *>(this);
@ -8206,8 +8206,8 @@ SubModelNode::SubModelNode(DataTree &datatree_arg,
void
SubModelNode::computeTemporaryTerms([[maybe_unused]] const pair<int, int> &derivOrder,
[[maybe_unused]] map<pair<int, int>, temporary_terms_t> &temp_terms_map,
[[maybe_unused]] map<expr_t, pair<int, pair<int, int>>> &reference_count,
[[maybe_unused]] map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
[[maybe_unused]] unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
[[maybe_unused]] bool is_matlab) const
{
cerr << "SubModelNode::computeTemporaryTerms not implemented." << endl;
@ -8216,8 +8216,8 @@ SubModelNode::computeTemporaryTerms([[maybe_unused]] const pair<int, int> &deriv
void
SubModelNode::computeBlockTemporaryTerms([[maybe_unused]] int blk, [[maybe_unused]] int eq,
[[maybe_unused]] vector<vector<temporary_terms_t>> &blocks_temporary_terms,
[[maybe_unused]] map<expr_t, tuple<int, int, int>> &reference_count) const
[[maybe_unused]] vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
[[maybe_unused]] unordered_map<expr_t, tuple<int, int, int>> &reference_count) const
{
cerr << "SubModelNode::computeBlocksTemporaryTerms not implemented." << endl;
exit(EXIT_FAILURE);

View File

@ -28,6 +28,7 @@
#include <optional>
#include <utility>
#include <unordered_map>
#include <unordered_set>
using namespace std;
@ -51,7 +52,7 @@ struct ExprNodeLess;
see the definition of ExprNodeLess */
using temporary_terms_t = set<expr_t, ExprNodeLess>;
/*! Keeps track of array indices of temporary_terms for writing */
using temporary_terms_idxs_t = map<expr_t, int>;
using temporary_terms_idxs_t = unordered_map<expr_t, int>;
//! Type for evaluation contexts
/*! The key is a symbol id. Lags are assumed to be null */
@ -291,8 +292,8 @@ protected:
//! Cost of computing current node
/*! Nodes included in temporary_terms are considered having a null cost */
virtual int cost(int cost, bool is_matlab) const;
virtual int cost(const vector<vector<temporary_terms_t>> &blocks_temporary_terms, bool is_matlab) const;
virtual int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const;
virtual int cost(const vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms, bool is_matlab) const;
virtual int cost(const map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map, bool is_matlab) const;
//! For creating equation cross references
struct EquationInfo
@ -379,10 +380,13 @@ public:
A node will be marked as a temporary term if it is referenced at least
two times (i.e. has at least two parents), and has a computing cost
(multiplied by reference count) greater to datatree.min_cost
NB: the use of std::unordered_map instead of std::map for caching
purposes improves performance on very large models (5000 equations)
*/
virtual void computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const;
//! Compute temporary terms in this expression for block decomposed model
@ -397,10 +401,13 @@ public:
expression first appears, third integer is the equation number within the block)
Same rules as computeTemporaryTerms() for computing cost.
NB: the use of std::unordered_{set,map} instead of std::{set,map} for caching
and output improves performance on very large models (5000 equations)
*/
virtual void computeBlockTemporaryTerms(int blk, int eq,
vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const;
vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>> &reference_count) const;
//! Writes output of node, using a Txxx notation for nodes in temporary_terms, and specifiying the set of already written external functions
/*!
@ -1024,18 +1031,18 @@ private:
expr_t computeDerivative(int deriv_id) override;
expr_t computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode *> &recursive_variables, unordered_map<expr_t, set<int>> &non_null_chain_rule_derivatives, unordered_map<expr_t, map<int, expr_t>> &cache) override;
int cost(int cost, bool is_matlab) const override;
int cost(const vector<vector<temporary_terms_t>> &blocks_temporary_terms, bool is_matlab) const override;
int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
int cost(const vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms, bool is_matlab) const override;
int cost(const map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map, bool is_matlab) const override;
//! Returns the derivative of this node if darg is the derivative of the argument
expr_t composeDerivatives(expr_t darg, int deriv_id);
public:
UnaryOpNode(DataTree &datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg);
void computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>> &reference_count) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
@ -1124,8 +1131,8 @@ private:
expr_t computeDerivative(int deriv_id) override;
expr_t computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode *> &recursive_variables, unordered_map<expr_t, set<int>> &non_null_chain_rule_derivatives, unordered_map<expr_t, map<int, expr_t>> &cache) override;
int cost(int cost, bool is_matlab) const override;
int cost(const vector<vector<temporary_terms_t>> &blocks_temporary_terms, bool is_matlab) const override;
int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
int cost(const vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms, bool is_matlab) const override;
int cost(const map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map, bool is_matlab) const override;
//! Returns the derivative of this node if darg1 and darg2 are the derivatives of the arguments
expr_t composeDerivatives(expr_t darg1, expr_t darg2);
// Returns the node obtained by applying a transformation recursively on the arguments (in same datatree)
@ -1143,11 +1150,11 @@ public:
int precedenceJson(const temporary_terms_t &temporary_terms) const override;
int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
void computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>> &reference_count) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
@ -1274,8 +1281,8 @@ private:
expr_t computeDerivative(int deriv_id) override;
expr_t computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode *> &recursive_variables, unordered_map<expr_t, set<int>> &non_null_chain_rule_derivatives, unordered_map<expr_t, map<int, expr_t>> &cache) override;
int cost(int cost, bool is_matlab) const override;
int cost(const vector<vector<temporary_terms_t>> &blocks_temporary_terms, bool is_matlab) const override;
int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
int cost(const vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms, bool is_matlab) const override;
int cost(const map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map, bool is_matlab) const override;
//! Returns the derivative of this node if darg1, darg2 and darg3 are the derivatives of the arguments
expr_t composeDerivatives(expr_t darg1, expr_t darg2, expr_t darg3);
// Returns the node obtained by applying a transformation recursively on the arguments (in same datatree)
@ -1293,11 +1300,11 @@ public:
TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg);
int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
void computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>> &reference_count) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
@ -1418,11 +1425,11 @@ public:
AbstractExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg,
vector<expr_t> arguments_arg);
void computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>> &reference_count) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override = 0;
void writeJsonAST(ostream &output) const override = 0;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic = true) const override = 0;
@ -1609,11 +1616,11 @@ public:
const string model_name;
SubModelNode(DataTree &datatree_arg, int idx_arg, string model_name_arg);
void computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>> &temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const override;
void computeBlockTemporaryTerms(int blk, int eq, vector<vector<unordered_set<expr_t>>> &blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>> &reference_count) const override;
expr_t toStatic(DataTree &static_datatree) const override;
expr_t computeDerivative(int deriv_id) override;
int maxEndoLead() const override;

View File

@ -921,8 +921,8 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms)
}());
// Compute the temporary terms in equations and derivatives
map<pair<int, int>, temporary_terms_t> temp_terms_map;
map<expr_t, pair<int, pair<int, int>>> reference_count;
map<pair<int, int>, unordered_set<expr_t>> temp_terms_map;
unordered_map<expr_t, pair<int, pair<int, int>>> reference_count;
for (auto &equation : equations)
equation->computeTemporaryTerms({ 0, 0 },
@ -949,7 +949,8 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms)
temporary_terms_derivatives.clear();
temporary_terms_derivatives.resize(derivatives.size());
for (int order = 0; order < static_cast<int>(derivatives.size()); order++)
temporary_terms_derivatives[order] = move(temp_terms_map[{ order, 0 }]);
copy(temp_terms_map[{ order, 0 }].begin(), temp_terms_map[{ order, 0 }].end(),
inserter(temporary_terms_derivatives.at(order), temporary_terms_derivatives.at(order).begin()));
// Compute indices in MATLAB/Julia vector
for (int order {0}, idx {0}; order < static_cast<int>(derivatives.size()); order++)
@ -961,12 +962,12 @@ void
ModelTree::computeBlockTemporaryTerms(bool no_tmp_terms)
{
int nb_blocks = blocks.size();
blocks_temporary_terms.resize(nb_blocks);
map<expr_t, tuple<int, int, int>> reference_count;
unordered_map<expr_t, tuple<int, int, int>> reference_count;
vector<vector<unordered_set<expr_t>>> temp_terms(nb_blocks);
for (int blk = 0; blk < nb_blocks; blk++)
{
blocks_temporary_terms[blk].resize(blocks[blk].size + 1);
temp_terms[blk].resize(blocks[blk].size + 1);
for (int eq = 0; eq < blocks[blk].size; eq++)
{
/* It is important to compute temporary terms of the renormalized
@ -979,22 +980,30 @@ ModelTree::computeBlockTemporaryTerms(bool no_tmp_terms)
|| blocks[blk].simulation_type == BlockSimulationType::evaluateForward
|| eq < blocks[blk].getRecursiveSize())
&& isBlockEquationRenormalized(blk, eq))
getBlockEquationRenormalizedExpr(blk, eq)->computeBlockTemporaryTerms(blk, eq, blocks_temporary_terms, reference_count);
getBlockEquationRenormalizedExpr(blk, eq)->computeBlockTemporaryTerms(blk, eq, temp_terms, reference_count);
else
getBlockEquationExpr(blk, eq)->computeBlockTemporaryTerms(blk, eq, blocks_temporary_terms, reference_count);
getBlockEquationExpr(blk, eq)->computeBlockTemporaryTerms(blk, eq, temp_terms, reference_count);
}
for (const auto &[ignore, d] : blocks_derivatives[blk])
d->computeBlockTemporaryTerms(blk, blocks[blk].size, blocks_temporary_terms, reference_count);
d->computeBlockTemporaryTerms(blk, blocks[blk].size, temp_terms, reference_count);
}
/* If the user has specified the notmpterms option, clear all temporary
terms, except those that correspond to external functions (since they are
not optional) */
if (no_tmp_terms)
for (auto &it : blocks_temporary_terms)
for (auto &it : temp_terms)
for (auto &it2 : it)
erase_if(it2, [](expr_t e) { return !dynamic_cast<AbstractExternalFunctionNode *>(e); });
blocks_temporary_terms.resize(nb_blocks);
for (int blk {0}; blk < nb_blocks; blk++)
{
blocks_temporary_terms.at(blk).resize(temp_terms.at(blk).size());
for (size_t i {0}; i < temp_terms.at(blk).size(); i++)
copy(temp_terms.at(blk).at(i).begin(), temp_terms.at(blk).at(i).end(), inserter(blocks_temporary_terms.at(blk).at(i), blocks_temporary_terms.at(blk).at(i).begin()));
}
// Compute indices in the temporary terms vector
blocks_temporary_terms_idxs.clear();
for (int idx{0};
@ -1474,15 +1483,18 @@ ModelTree::computeParamsDerivatives(int paramsDerivsOrder)
void
ModelTree::computeParamsDerivativesTemporaryTerms()
{
map<expr_t, pair<int, pair<int, int>>> reference_count;
unordered_map<expr_t, pair<int, pair<int, int>>> reference_count;
/* The temp terms should be constructed in the same order as the for loops in
{Static,Dynamic}Model::write{Json,}ParamsDerivativesFile() */
params_derivs_temporary_terms.clear();
map<pair<int, int>, unordered_set<expr_t>> temp_terms_map;
for (const auto &[order, derivs] : params_derivatives)
for (const auto &[indices, d] : derivs)
d->computeTemporaryTerms(order, params_derivs_temporary_terms,
reference_count, true);
d->computeTemporaryTerms(order, temp_terms_map, reference_count, true);
for (const auto &[order, tts] : temp_terms_map)
copy(temp_terms_map[order].begin(), temp_terms_map[order].end(),
inserter(params_derivs_temporary_terms[order], params_derivs_temporary_terms[order].begin()));
for (int idx {0};
const auto &[order, tts] : params_derivs_temporary_terms)

View File

@ -833,8 +833,8 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool
ramsey_multipliers_derivatives.try_emplace({ eq, mult }, d);
// Compute the temporary terms
map<pair<int, int>, temporary_terms_t> temp_terms_map;
map<expr_t, pair<int, pair<int, int>>> reference_count;
map<pair<int, int>, unordered_set<expr_t>> temp_terms_map;
unordered_map<expr_t, pair<int, pair<int, int>>> reference_count;
for (const auto &[row_col, d] : ramsey_multipliers_derivatives)
d->computeTemporaryTerms({ 1, 0 }, temp_terms_map, reference_count, is_matlab);
/* If the user has specified the notmpterms option, clear all temporary
@ -844,7 +844,8 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool
for (auto &it : temp_terms_map)
erase_if(it.second,
[](expr_t e) { return !dynamic_cast<AbstractExternalFunctionNode *>(e); });
ramsey_multipliers_derivatives_temporary_terms = move(temp_terms_map[{ 1, 0 }]);
copy(temp_terms_map[{1, 0}].begin(), temp_terms_map[{1, 0}].end(),
inserter(ramsey_multipliers_derivatives_temporary_terms, ramsey_multipliers_derivatives_temporary_terms.begin()));
for (int idx {0};
auto it : ramsey_multipliers_derivatives_temporary_terms)
ramsey_multipliers_derivatives_temporary_terms_idxs[it] = idx++;