Verified Commit e89dd9cb authored by Sébastien Villemot's avatar Sébastien Villemot
Browse files

Make storage of derivatives ready for k-order

This is the first step towards computing k-order derivatives.

Ref dynare#217, #10
parent 3eff2b91
Pipeline #332 passed with stage
in 1 minute and 21 seconds
......@@ -245,8 +245,8 @@ DynamicModel::operator=(const DynamicModel &m)
void
DynamicModel::compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, int lag, const map_idx_t &map_idx) const
{
auto it = first_derivatives.find({ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, symb_id), lag) });
if (it != first_derivatives.end())
auto it = derivatives[1].find({ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, symb_id), lag) });
if (it != derivatives[1].end())
(it->second)->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
else
{
......@@ -274,7 +274,6 @@ DynamicModel::computeTemporaryTermsOrdered()
map<expr_t, pair<int, int>> first_occurence;
map<expr_t, int> reference_count;
BinaryOpNode *eq_node;
first_derivatives_t::const_iterator it;
first_chain_rule_derivatives_t::const_iterator it_chr;
ostringstream tmp_s;
v_temporary_terms.clear();
......@@ -1016,10 +1015,10 @@ DynamicModel::writeModelEquationsCode(const string &basename, const map_idx_t &m
map<pair< int, pair<int, int>>, expr_t> first_derivatives_reordered_endo;
map<pair< pair<int, SymbolType>, pair<int, int>>, expr_t> first_derivatives_reordered_exo;
for (const auto & first_derivative : first_derivatives)
for (const auto & first_derivative : derivatives[1])
{
int deriv_id = first_derivative.first.second;
unsigned int eq = first_derivative.first.first;
int deriv_id = first_derivative.first[1];
unsigned int eq = first_derivative.first[0];
int symb = getSymbIDByDerivID(deriv_id);
unsigned int var = symbol_table.getTypeSpecificID(symb);
int lag = getLagByDerivID(deriv_id);
......@@ -1103,24 +1102,24 @@ DynamicModel::writeModelEquationsCode(const string &basename, const map_idx_t &m
fjmp_if_eval.write(code_file, instruction_number);
int prev_instruction_number = instruction_number;
vector<vector<pair<pair<int, int>, int >>> derivatives;
derivatives.resize(symbol_table.endo_nbr());
vector<vector<pair<pair<int, int>, int >>> my_derivatives;
my_derivatives.resize(symbol_table.endo_nbr());
count_u = symbol_table.endo_nbr();
for (const auto & first_derivative : first_derivatives)
for (const auto & first_derivative : derivatives[1])
{
int deriv_id = first_derivative.first.second;
int deriv_id = first_derivative.first[1];
if (getTypeByDerivID(deriv_id) == SymbolType::endogenous)
{
expr_t d1 = first_derivative.second;
unsigned int eq = first_derivative.first.first;
unsigned int eq = first_derivative.first[0];
int symb = getSymbIDByDerivID(deriv_id);
unsigned int var = symbol_table.getTypeSpecificID(symb);
int lag = getLagByDerivID(deriv_id);
FNUMEXPR_ fnumexpr(FirstEndoDerivative, eq, var, lag);
fnumexpr.write(code_file, instruction_number);
if (!derivatives[eq].size())
derivatives[eq].clear();
derivatives[eq].emplace_back(make_pair(var, lag), count_u);
if (!my_derivatives[eq].size())
my_derivatives[eq].clear();
my_derivatives[eq].emplace_back(make_pair(var, lag), count_u);
d1->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
FSTPU_ fstpu(count_u);
......@@ -1132,10 +1131,10 @@ DynamicModel::writeModelEquationsCode(const string &basename, const map_idx_t &m
{
FLDR_ fldr(i);
fldr.write(code_file, instruction_number);
if (derivatives[i].size())
if (my_derivatives[i].size())
{
for (vector<pair<pair<int, int>, int>>::const_iterator it = derivatives[i].begin();
it != derivatives[i].end(); it++)
for (vector<pair<pair<int, int>, int>>::const_iterator it = my_derivatives[i].begin();
it != my_derivatives[i].end(); it++)
{
FLDU_ fldu(it->second);
fldu.write(code_file, instruction_number);
......@@ -1143,7 +1142,7 @@ DynamicModel::writeModelEquationsCode(const string &basename, const map_idx_t &m
fldv.write(code_file, instruction_number);
FBINARY_ fbinary{static_cast<int>(BinaryOpcode::times)};
fbinary.write(code_file, instruction_number);
if (it != derivatives[i].begin())
if (it != my_derivatives[i].begin())
{
FBINARY_ fbinary{static_cast<int>(BinaryOpcode::plus)};
fbinary.write(code_file, instruction_number);
......@@ -1722,7 +1721,7 @@ DynamicModel::writeDynamicCFile(const string &basename, const int order) const
string filename_mex = basename + "/model/src/dynamic_mex.c";
ofstream mDynamicModelFile, mDynamicMexFile;
int ntt = temporary_terms_mlv.size() + temporary_terms_res.size() + temporary_terms_g1.size() + temporary_terms_g2.size() + temporary_terms_g3.size();
int ntt = temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size() + temporary_terms_derivatives[2].size() + temporary_terms_derivatives[3].size();
mDynamicModelFile.open(filename, ios::out | ios::binary);
if (!mDynamicModelFile.is_open())
......@@ -1835,7 +1834,7 @@ DynamicModel::writeDynamicCFile(const string &basename, const int order) const
<< " if (nlhs >= 3)" << endl
<< " {" << endl
<< " /* Set the output pointer to the output matrix v2. */" << endl
<< " plhs[2] = mxCreateDoubleMatrix(" << NNZDerivatives[1] << ", " << 3
<< " plhs[2] = mxCreateDoubleMatrix(" << NNZDerivatives[2] << ", " << 3
<< ", mxREAL);" << endl
<< " double *v2 = mxGetPr(plhs[2]);" << endl
<< " dynamic_g2_tt(y, x, nb_row_x, params, steady_state, it_, T);" << endl
......@@ -1845,7 +1844,7 @@ DynamicModel::writeDynamicCFile(const string &basename, const int order) const
<< " if (nlhs >= 4)" << endl
<< " {" << endl
<< " /* Set the output pointer to the output matrix v3. */" << endl
<< " plhs[3] = mxCreateDoubleMatrix(" << NNZDerivatives[2] << ", " << 3 << ", mxREAL);" << endl
<< " plhs[3] = mxCreateDoubleMatrix(" << NNZDerivatives[3] << ", " << 3 << ", mxREAL);" << endl
<< " double *v3 = mxGetPr(plhs[3]);" << endl
<< " dynamic_g3_tt(y, x, nb_row_x, params, steady_state, it_, T);" << endl
<< " dynamic_g3(y, x, nb_row_x, params, steady_state, it_, T, v3);" << endl
......@@ -1893,9 +1892,9 @@ DynamicModel::printNonZeroHessianEquations(ostream &output) const
void
DynamicModel::setNonZeroHessianEquations(map<int, string> &eqs)
{
for (const auto &it : second_derivatives)
for (const auto &it : derivatives[2])
{
int eq = get<0>(it.first);
int eq = it.first[0];
if (nonzero_hessian_eqs.find(eq) == nonzero_hessian_eqs.end())
{
nonzero_hessian_eqs[eq] = "";
......@@ -2460,7 +2459,7 @@ DynamicModel::writeDynamicMatlabCompatLayer(const string &basename) const
cerr << "Error: Can't open file " << filename << " for writing" << endl;
exit(EXIT_FAILURE);
}
int ntt = temporary_terms_mlv.size() + temporary_terms_res.size() + temporary_terms_g1.size() + temporary_terms_g2.size() + temporary_terms_g3.size();
int ntt = temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size() + temporary_terms_derivatives[2].size() + temporary_terms_derivatives[3].size();
output << "function [residual, g1, g2, g3] = dynamic(y, x, params, steady_state, it_)" << endl
<< " T = NaN(" << ntt << ", 1);" << endl
......@@ -2514,11 +2513,11 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
writeModelLocalVariableTemporaryTerms(temp_term_union, temporary_terms_mlv,
model_tt_output, output_type, tef_terms);
writeTemporaryTerms(temporary_terms_res,
writeTemporaryTerms(temporary_terms_derivatives[0],
temp_term_union,
temporary_terms_idxs,
model_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_res.begin(), temporary_terms_res.end());
temp_term_union.insert(temporary_terms_derivatives[0].begin(), temporary_terms_derivatives[0].end());
writeModelEquations(model_output, output_type, temp_term_union);
......@@ -2526,18 +2525,18 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
int hessianColsNbr = dynJacobianColsNbr * dynJacobianColsNbr;
// Writing Jacobian
if (!first_derivatives.empty())
if (!derivatives[1].empty())
{
writeTemporaryTerms(temporary_terms_g1,
writeTemporaryTerms(temporary_terms_derivatives[1],
temp_term_union,
temporary_terms_idxs,
jacobian_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_g1.begin(), temporary_terms_g1.end());
temp_term_union.insert(temporary_terms_derivatives[1].begin(), temporary_terms_derivatives[1].end());
for (const auto & first_derivative : first_derivatives)
for (const auto & first_derivative : derivatives[1])
{
int eq, var;
tie(eq, var) = first_derivative.first;
tie(eq, var) = vectorToTuple<2>(first_derivative.first);
expr_t d1 = first_derivative.second;
jacobianHelper(jacobian_output, eq, getDynJacobianCol(var), output_type);
......@@ -2549,19 +2548,19 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
}
// Writing Hessian
if (!second_derivatives.empty())
if (!derivatives[2].empty())
{
writeTemporaryTerms(temporary_terms_g2,
writeTemporaryTerms(temporary_terms_derivatives[2],
temp_term_union,
temporary_terms_idxs,
hessian_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_g2.begin(), temporary_terms_g2.end());
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 : second_derivatives)
for (const auto & second_derivative : derivatives[2])
{
int eq, var1, var2;
tie(eq, var1, var2) = second_derivative.first;
tie(eq, var1, var2) = vectorToTuple<3>(second_derivative.first);
expr_t d2 = second_derivative.second;
int id1 = getDynJacobianCol(var1);
......@@ -2618,19 +2617,19 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
}
// Writing third derivatives
if (!third_derivatives.empty())
if (!derivatives[3].empty())
{
writeTemporaryTerms(temporary_terms_g3,
writeTemporaryTerms(temporary_terms_derivatives[3],
temp_term_union,
temporary_terms_idxs,
third_derivatives_tt_output, output_type, tef_terms);
temp_term_union.insert(temporary_terms_g3.begin(), temporary_terms_g3.end());
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 : third_derivatives)
for (const auto & third_derivative : derivatives[3])
{
int eq, var1, var2, var3;
tie(eq, var1, var2, var3) = third_derivative.first;
tie(eq, var1, var2, var3) = vectorToTuple<4>(third_derivative.first);
expr_t d3 = third_derivative.second;
int id1 = getDynJacobianCol(var1);
......@@ -2714,7 +2713,7 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
init_output << "residual = zeros(" << nrows << ", 1);";
writeDynamicModelHelper(basename, "dynamic_resid", "residual",
"dynamic_resid_tt",
temporary_terms_mlv.size() + temporary_terms_res.size(),
temporary_terms_mlv.size() + temporary_terms_derivatives[0].size(),
"", init_output, end_output,
model_output, model_tt_output);
......@@ -2723,7 +2722,7 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
init_output << "g1 = zeros(" << nrows << ", " << dynJacobianColsNbr << ");";
writeDynamicModelHelper(basename, "dynamic_g1", "g1",
"dynamic_g1_tt",
temporary_terms_mlv.size() + temporary_terms_res.size() + temporary_terms_g1.size(),
temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size(),
"dynamic_resid_tt",
init_output, end_output,
jacobian_output, jacobian_tt_output);
......@@ -2731,17 +2730,17 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
init_output.str(string());
init_output.clear();
if (second_derivatives.size())
if (derivatives[2].size())
{
init_output << "v2 = zeros(" << NNZDerivatives[1] << ",3);";
init_output << "v2 = zeros(" << NNZDerivatives[2] << ",3);";
end_output << "g2 = sparse(v2(:,1),v2(:,2),v2(:,3)," << nrows << "," << hessianColsNbr << ");";
}
else
init_output << "g2 = sparse([],[],[]," << nrows << "," << hessianColsNbr << ");";
writeDynamicModelHelper(basename, "dynamic_g2", "g2",
"dynamic_g2_tt",
temporary_terms_mlv.size() + temporary_terms_res.size() + temporary_terms_g1.size()
+ temporary_terms_g2.size(),
temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size()
+ temporary_terms_derivatives[2].size(),
"dynamic_g1_tt",
init_output, end_output,
hessian_output, hessian_tt_output);
......@@ -2752,17 +2751,17 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
end_output.str(string());
end_output.clear();
int ncols = hessianColsNbr * dynJacobianColsNbr;
if (third_derivatives.size())
if (derivatives[3].size())
{
init_output << "v3 = zeros(" << NNZDerivatives[2] << ",3);";
init_output << "v3 = zeros(" << NNZDerivatives[3] << ",3);";
end_output << "g3 = sparse(v3(:,1),v3(:,2),v3(:,3)," << nrows << "," << ncols << ");";
}
else
init_output << "g3 = sparse([],[],[]," << nrows << "," << ncols << ");";
writeDynamicModelHelper(basename, "dynamic_g3", "g3",
"dynamic_g3_tt",
temporary_terms_mlv.size() + temporary_terms_res.size() + temporary_terms_g1.size()
+ temporary_terms_g2.size() + temporary_terms_g3.size(),
temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size()
+ temporary_terms_derivatives[2].size() + temporary_terms_derivatives[3].size(),
"dynamic_g2_tt",
init_output, end_output,
third_derivatives_output, third_derivatives_tt_output);
......@@ -2878,10 +2877,10 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
// Write the number of temporary terms
output << "tmp_nbr = zeros(Int,4)" << endl
<< "tmp_nbr[1] = " << temporary_terms_mlv.size() + temporary_terms_res.size() << "# Number of temporary terms for the residuals" << endl
<< "tmp_nbr[2] = " << temporary_terms_g1.size() << "# Number of temporary terms for g1 (jacobian)" << endl
<< "tmp_nbr[3] = " << temporary_terms_g2.size() << "# Number of temporary terms for g2 (hessian)" << endl
<< "tmp_nbr[4] = " << temporary_terms_g3.size() << "# Number of temporary terms for g3 (third order derivates)" << endl << endl;
<< "tmp_nbr[1] = " << temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() << "# Number of temporary terms for the residuals" << endl
<< "tmp_nbr[2] = " << temporary_terms_derivatives[1].size() << "# Number of temporary terms for g1 (jacobian)" << endl
<< "tmp_nbr[3] = " << temporary_terms_derivatives[2].size() << "# Number of temporary terms for g2 (hessian)" << endl
<< "tmp_nbr[4] = " << temporary_terms_derivatives[3].size() << "# Number of temporary terms for g3 (third order derivates)" << endl << endl;
// dynamicResidTT!
output << "function dynamicResidTT!(T::Vector{Float64}," << endl
......@@ -2895,7 +2894,7 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
output << "function dynamicResid!(T::Vector{Float64}, residual::Vector{Float64}," << endl
<< " y::Vector{Float64}, x::Matrix{Float64}, "
<< "params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int, T_flag::Bool)" << endl
<< " @assert length(T) >= " << temporary_terms_mlv.size() + temporary_terms_res.size() << endl
<< " @assert length(T) >= " << temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() << endl
<< " @assert length(residual) == " << nrows << endl
<< " @assert length(y)+size(x, 2) == " << dynJacobianColsNbr << endl
<< " @assert length(params) == " << symbol_table.param_nbr() << endl
......@@ -2920,7 +2919,7 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
<< " y::Vector{Float64}, x::Matrix{Float64}, "
<< "params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int, T_flag::Bool)" << endl
<< " @assert length(T) >= "
<< temporary_terms_mlv.size() + temporary_terms_res.size() + temporary_terms_g1.size() << endl
<< temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size() << endl
<< " @assert size(g1) == (" << nrows << ", " << dynJacobianColsNbr << ")" << endl
<< " @assert length(y)+size(x, 2) == " << dynJacobianColsNbr << endl
<< " @assert length(params) == " << symbol_table.param_nbr() << endl
......@@ -2945,7 +2944,7 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
output << "function dynamicG2!(T::Vector{Float64}, g2::Matrix{Float64}," << endl
<< " y::Vector{Float64}, x::Matrix{Float64}, "
<< "params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int, T_flag::Bool)" << endl
<< " @assert length(T) >= " << temporary_terms_mlv.size() + temporary_terms_res.size() + temporary_terms_g1.size() + temporary_terms_g2.size() << endl
<< " @assert length(T) >= " << temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size() + temporary_terms_derivatives[2].size() << endl
<< " @assert size(g2) == (" << nrows << ", " << hessianColsNbr << ")" << endl
<< " @assert length(y)+size(x, 2) == " << dynJacobianColsNbr << endl
<< " @assert length(params) == " << symbol_table.param_nbr() << endl
......@@ -2972,7 +2971,7 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
<< " y::Vector{Float64}, x::Matrix{Float64}, "
<< "params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int, T_flag::Bool)" << endl
<< " @assert length(T) >= "
<< temporary_terms_mlv.size() + temporary_terms_res.size() + temporary_terms_g1.size() + temporary_terms_g2.size() + temporary_terms_g3.size() << endl
<< temporary_terms_mlv.size() + temporary_terms_derivatives[0].size() + temporary_terms_derivatives[1].size() + temporary_terms_derivatives[2].size() + temporary_terms_derivatives[3].size() << endl
<< " @assert size(g3) == (" << nrows << ", " << ncols << ")" << endl
<< " @assert length(y)+size(x, 2) == " << dynJacobianColsNbr << endl
<< " @assert length(params) == " << symbol_table.param_nbr() << endl
......@@ -3117,10 +3116,10 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de
<< modstruct << "ndynamic = " << npred+nboth+nfwrd << ";" << endl;
if (!julia)
output << modstruct << "dynamic_tmp_nbr = zeros(4,1); % Number of temporaries used for the dynamic model" << endl
<< modstruct << "dynamic_tmp_nbr(1) = " << temporary_terms_res.size() << "; % Number of temporaries used for the evaluation of the residuals" << endl
<< modstruct << "dynamic_tmp_nbr(2) = " << temporary_terms_g1.size() << "; % Number of temporaries used for the evaluation of g1 (jacobian)" << endl
<< modstruct << "dynamic_tmp_nbr(3) = " << temporary_terms_g2.size() << "; % Number of temporaries used for the evaluation of g2 (hessian)" << endl
<< modstruct << "dynamic_tmp_nbr(4) = " << temporary_terms_g3.size() << "; % Number of temporaries used for the evaluation of g3 (third order derivatives)" << endl;
<< modstruct << "dynamic_tmp_nbr(1) = " << temporary_terms_derivatives[0].size() << "; % Number of temporaries used for the evaluation of the residuals" << endl
<< modstruct << "dynamic_tmp_nbr(2) = " << temporary_terms_derivatives[1].size() << "; % Number of temporaries used for the evaluation of g1 (jacobian)" << endl
<< modstruct << "dynamic_tmp_nbr(3) = " << temporary_terms_derivatives[2].size() << "; % Number of temporaries used for the evaluation of g2 (hessian)" << endl
<< modstruct << "dynamic_tmp_nbr(4) = " << temporary_terms_derivatives[3].size() << "; % Number of temporaries used for the evaluation of g3 (third order derivatives)" << endl;
// Write equation tags
if (julia)
......@@ -3413,12 +3412,12 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de
state_equ.push_back(equation_reordered[variable_inv_reordered[*it - 1]]+1);
map<pair< int, pair<int, int>>, int> lag_row_incidence;
for (const auto & first_derivative : first_derivatives)
for (const auto & first_derivative : derivatives[1])
{
int deriv_id = first_derivative.first.second;
int deriv_id = first_derivative.first[1];
if (getTypeByDerivID(deriv_id) == SymbolType::endogenous)
{
int eq = first_derivative.first.first;
int eq = first_derivative.first[0];
int symb = getSymbIDByDerivID(deriv_id);
int var = symbol_table.getTypeSpecificID(symb);
int lag = getLagByDerivID(deriv_id);
......@@ -3625,14 +3624,14 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de
// Write number of non-zero derivatives
// Use -1 if the derivatives have not been computed
output << modstruct << (julia ? "nnzderivatives" : "NNZDerivatives")
<< " = [" << NNZDerivatives[0] << "; ";
<< " = [" << NNZDerivatives[1] << "; ";
if (order > 1)
output << NNZDerivatives[1] << "; ";
output << NNZDerivatives[2] << "; ";
else
output << "-1; ";
if (order > 2)
output << NNZDerivatives[2];
output << NNZDerivatives[3];
else
output << "-1";
output << "];" << endl;
......@@ -3646,13 +3645,13 @@ map<pair<int, pair<int, int >>, expr_t>
DynamicModel::collect_first_order_derivatives_endogenous()
{
map<pair<int, pair<int, int >>, expr_t> endo_derivatives;
for (auto & first_derivative : first_derivatives)
for (auto & first_derivative : derivatives[1])
{
if (getTypeByDerivID(first_derivative.first.second) == SymbolType::endogenous)
if (getTypeByDerivID(first_derivative.first[1]) == SymbolType::endogenous)
{
int eq = first_derivative.first.first;
int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(first_derivative.first.second));
int lag = getLagByDerivID(first_derivative.first.second);
int eq = first_derivative.first[0];
int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(first_derivative.first[1]));
int lag = getLagByDerivID(first_derivative.first[1]);
endo_derivatives[{ eq, { var, lag } }] = first_derivative.second;
}
}
......@@ -4718,7 +4717,7 @@ DynamicModel::computeChainRuleJacobian(blocks_derivatives_t &blocks_endo_derivat
int eqr = it_l.second.first;
int varr = it_l.second.second;
if (Deriv_type == 0)
first_chain_rule_derivatives[{ eqr, { varr, lag } }] = first_derivatives[{ eqr, getDerivID(symbol_table.getID(SymbolType::endogenous, varr), lag) }];
first_chain_rule_derivatives[{ eqr, { varr, lag } }] = derivatives[1][{ eqr, getDerivID(symbol_table.getID(SymbolType::endogenous, varr), lag) }];
else if (Deriv_type == 1)
first_chain_rule_derivatives[{ eqr, { varr, lag } }] = (equation_type_and_normalized_equation[eqr].second)->getChainRuleDerivative(getDerivID(symbol_table.getID(SymbolType::endogenous, varr), lag), recursive_variables);
else if (Deriv_type == 2)
......@@ -4763,16 +4762,16 @@ DynamicModel::collect_block_first_order_derivatives()
exo_max_leadlag_block = vector<pair<int, int>>(nb_blocks, { 0, 0 });
exo_det_max_leadlag_block = vector<pair<int, int>>(nb_blocks, { 0, 0 });
max_leadlag_block = vector<pair<int, int>>(nb_blocks, { 0, 0 });
for (auto & first_derivative : first_derivatives)
for (auto & first_derivative : derivatives[1])
{
int eq = first_derivative.first.first;
int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(first_derivative.first.second));
int lag = getLagByDerivID(first_derivative.first.second);
int eq = first_derivative.first[0];
int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(first_derivative.first[1]));
int lag = getLagByDerivID(first_derivative.first[1]);
int block_eq = equation_2_block[eq];
int block_var = 0;
derivative_t tmp_derivative;
lag_var_t lag_var;
switch (getTypeByDerivID(first_derivative.first.second))
switch (getTypeByDerivID(first_derivative.first[1]))
{
case SymbolType::endogenous:
block_var = variable_2_block[var];
......@@ -4783,7 +4782,7 @@ DynamicModel::collect_block_first_order_derivatives()
if (lag > 0 && lag > endo_max_leadlag_block[block_eq].second)
endo_max_leadlag_block[block_eq] = { endo_max_leadlag_block[block_eq].first, lag };
tmp_derivative = derivative_endo[block_eq];
tmp_derivative[{ lag, { eq, var } }] = first_derivatives[{ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, var), lag) }];
tmp_derivative[{ lag, { eq, var } }] = derivatives[1][{ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, var), lag) }];
derivative_endo[block_eq] = tmp_derivative;
}
else
......@@ -4807,7 +4806,7 @@ DynamicModel::collect_block_first_order_derivatives()
}
}
}
tmp_derivative[{ lag, { eq, var } }] = first_derivatives[{ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, var), lag) }];
tmp_derivative[{ lag, { eq, var } }] = derivatives[1][{ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, var), lag) }];
derivative_other_endo[block_eq] = tmp_derivative;
lag_var = other_endo_block[block_eq];
if (lag_var.find(lag) == lag_var.end())
......@@ -4836,7 +4835,7 @@ DynamicModel::collect_block_first_order_derivatives()
}
}
}
tmp_derivative[{ lag, { eq, var } }] = first_derivatives[{ eq, getDerivID(symbol_table.getID(SymbolType::exogenous, var), lag) }];
tmp_derivative[{ lag, { eq, var } }] = derivatives[1][{ eq, getDerivID(symbol_table.getID(SymbolType::exogenous, var), lag) }];
derivative_exo[block_eq] = tmp_derivative;
lag_var = exo_block[block_eq];
if (lag_var.find(lag) == lag_var.end())
......@@ -4864,7 +4863,7 @@ DynamicModel::collect_block_first_order_derivatives()
}
}
}
tmp_derivative[{ lag, { eq, var } }] = first_derivatives[{ eq, getDerivID(symbol_table.getID(SymbolType::exogenous, var), lag) }];
tmp_derivative[{ lag, { eq, var } }] = derivatives[1][{ eq, getDerivID(symbol_table.getID(SymbolType::exogenous, var), lag) }];
derivative_exo_det[block_eq] = tmp_derivative;
lag_var = exo_det_block[block_eq];
if (lag_var.find(lag) == lag_var.end())
......@@ -5378,11 +5377,7 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context
void
DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) const
{
if (!residuals_params_derivatives.size()
&& !residuals_params_second_derivatives.size()
&& !jacobian_params_derivatives.size()
&& !jacobian_params_second_derivatives.size()
&& !hessian_params_derivatives.size())
if (!params_derivatives.size())
return;
ExprNodeOutputType output_type = (julia ? ExprNodeOutputType::juliaDynamicModel : ExprNodeOutputType::matlabDynamicModel);
......@@ -5398,10 +5393,10 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con
writeTemporaryTerms(params_derivs_temporary_terms, {}, params_derivs_temporary_terms_idxs, model_output, output_type, tef_terms);
for (const auto & residuals_params_derivative : residuals_params_derivatives)
for (const auto & residuals_params_derivative : params_derivatives.find({ 0, 1 })->second)
{
int eq, param;
tie(eq, param) = residuals_params_derivative.first;
tie(eq, param) = vectorToTuple<2>(residuals_params_derivative.first);
expr_t d1 = residuals_params_derivative.second;
int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
......@@ -5412,10 +5407,10 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con
jacobian_output << ";" << endl;
}
for (const auto & jacobian_params_derivative : jacobian_params_derivatives)
for (const auto & jacobian_params_derivative : params_derivatives.find({ 1, 1 })->second)
{
int eq, var, param;
tie(eq, var, param) = jacobian_params_derivative.first;
tie(eq, var, param) = vectorToTuple<3>(jacobian_params_derivative.first);
expr_t d2 = jacobian_params_derivative.second;
int var_col = getDynJacobianCol(var) + 1;
......@@ -5428,10 +5423,10 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con
}
int i = 1;
for (const auto &it : residuals_params_second_derivatives)
for (const auto &it : params_derivatives.find({ 0, 2 })->second)
{
int eq, param1, param2;
tie(eq, param1, param2) = it.first;
tie(eq, param1, param2) = vectorToTuple<3>(it.first);
expr_t d2 = it.second;
int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1;
......@@ -5452,10 +5447,10 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con
}
i = 1;
for (const auto &it : jacobian_params_second_derivatives)
for (const auto &it : params_derivatives.find({ 1, 2 })->second)
{
int eq, var, param1, param2;
tie(eq, var, param1, param2) = it.first;
tie(eq, var, param1, param2) = vectorToTuple<4>(it.first);
expr_t d2 = it.second;
int var_col = getDynJacobianCol(var) + 1;
......@@ -5479,10 +5474,10 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con
}
i = 1;
for (const auto &it : hessian_params_derivatives)
for (const auto &it : params_derivatives.find({ 2, 1 })->second)
{
int eq, var1, var2, param;
tie(eq, var1, var2, param) = it.first;
tie(eq, var1, var2, param) = vectorToTuple<4>(it.first);
expr_t d2 = it.second;
int var1_col = getDynJacobianCol(var1) + 1;
......@@ -5579,13 +5574,13 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con
<< "gp = zeros(" << equations.size() << ", " << dynJacobianColsNbr << ", " << symbol_table.param_nbr() << ");" << endl
<< hessian_output.str()
<< "if nargout >= 3" << endl
<< "rpp = zeros(" << residuals_params_second_derivatives.size() << ",4);" << endl
<< "rpp = zeros(" << params_derivatives.find({ 0, 2 })->second.size() << ",4);" << endl
<< hessian1_output.str()
<< "gpp = zeros(" << jacobian_params_second_derivatives.size() << ",5);" << endl
<< "gpp = zeros(" << params_derivatives.find({ 1, 2 })->second.size() << ",5);" << endl
<< third_derivs_output.str()
<< "end" << endl
<< "if nargout >= 5" << endl
<< "hp = zeros(" << hessian_params_derivatives.size() << ",5);" << endl
<< "hp = zeros(" << params_derivatives.find({ 2, 1 })->second.size() << ",5);" << endl
<< third_derivs1_output.str()
<< "end" << endl
<< "end" << endl;
......@@ -5606,11 +5601,11 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con
<< jacobian_output.str()
<< "gp = zeros(" << equations.size() << ", " << dynJacobianColsNbr << ", " << symbol_table.param_nbr() << ");" << endl
<< hessian_output.str()
<< "rpp = zeros(" << residuals_params_second_derivatives.size() << ",4);" << endl
<< "rpp = zeros(" << params_derivatives.find({ 0, 2 })->second.size() << ",4);" << endl
<< hessian1_output.str()
<< "gpp = zeros(" << jacobian_params_second_derivatives.size() << ",5);" << endl
<< "gpp = zeros(" << params_derivatives.find({ 1, 2 })->second.size() << ",5);" << endl
<< third_derivs_output.str()
<< "hp = zeros(" << hessian_params_derivatives.size() << ",5);" << endl
<< "hp = zeros(" << params_derivatives.find({ 2, 1 })->second.size() << ",5);" << endl
<< third_derivs1_output.str()
<< "(rp, gp, rpp, gpp, hp)" << endl
<< "end" << endl
......@@ -6371,7 +6366,7 @@ DynamicModel::writeJsonComputingPassOutput(ostream &output, bool writeDetails) c
deriv_node_temp_terms_t tef_terms;
temporary_terms_t temp_term_empty;
temporary_terms_t temp_term_union = temporary_terms_res;
temporary_terms_t temp_term_union = temporary_terms_derivatives[0];
temporary_terms_t temp_term_union_m_1;
string concat = "";
......@@ -6379,27 +6374,27 @@ DynamicModel::writeJsonComputingPassOutput(ostream &output, bool writeDetails) c
writeJsonModelLocalVariables(model_local_vars_output, tef_terms);
writeJsonTemporaryTerms(temporary_terms_res, temp_term_union_m_1, model_output, tef_terms, concat);
writeJsonTemporaryTerms(temporary_terms_derivatives[0], temp_term_union_m_1, model_output, tef_terms, concat);
model_output << ", ";
writeJsonModelEquations(model_output, true);
// Writing Jacobian
temp_term_union_m_1 = temp_term_union;
temp_term_union.insert(temporary_terms_g1.begin(), temporary_terms_g1.end());
temp_term_union.insert(temporary_terms_derivatives[1].begin(), temporary_terms_derivatives[1].end());
concat = "jacobian";
writeJsonTemporaryTerms(temp_term_union, temp_term_union_m_1, jacobian_output, tef_terms, concat);
jacobian_output << ", \"jacobian\": {"
<< " \"nrows\": " << equations.size()
<< ", \"ncols\": " << dynJacobianColsNbr
<< ", \"entries\": [";
for (auto it = first_derivatives.begin();
it != first_derivatives.end(); it++)
for (auto it = derivatives[1].begin();
it != derivatives[1].end(); it++)
{
if (it != first_derivatives.begin())
if (it != derivatives[1].begin())
jacobian_output << ", ";
int eq, var;
tie(eq, var) = it->first;
tie(eq, var) = vectorToTuple<2>(it->first);
int col = getDynJacobianCol(var);
expr_t d1 = it->second;
......@@ -6422,21 +6417,21 @@ DynamicModel::writeJsonComputingPassOutput(ostream &output, bool writeDetails) c
// Writing Hessian
temp_term_union_m_1 = temp_term_union;
temp_term_union.insert(temporary_terms_g2.begin(), temporary_terms_g2.end());
temp_term_union.insert(temporary_terms_derivatives[2].begin(), temporary_terms_derivatives[2].end());
concat = "hessian";
writeJsonTemporaryTerms(temp_term_union, temp_term_union_m_1, hessian_output, tef_terms, concat);
hessian_output << ", \"hessian\": {"
<< " \"nrows\": " << equations.size()
<< ", \"ncols\": " << hessianColsNbr
<< ", \"entries\": [";
for (auto it = second_derivatives.begin();
it != second_derivatives.end(); it++)
for (auto it = derivatives[2].begin();
it != derivatives[2].end(); it++)
{
if (it != second_derivatives.begin())
if (it != derivatives[2].begin())
hessian_output << ", ";
int eq, var1, var2;
tie(eq, var1, var2) = it->first;
tie(eq, var1, var2) = vectorToTuple<3>(it->first);
expr_t d2 = it->second;
int id1 = getDynJacobianCol(var1);
int id2 = getDynJacobianCol(var2);
......@@ -6467,21 +6462,21 @@ DynamicModel::writeJsonComputingPassOutput(ostream &output, bool writeDetails) c
// Writing third derivatives
temp_term_union_m_1 = temp_term_union;
temp_term_union.insert(temporary_terms_g3.begin(), temporary_terms_g3.end());
temp_term_union.insert(temporary_terms_derivatives[3].begin(), temporary_terms_derivatives[3].end());
concat = "third_derivatives";
writeJsonTemporaryTerms(temp_term_union, temp_term_union_m_1, third_derivatives_output, tef_terms, concat);
third_derivatives_output << ", \"third_derivative\": {"
<< " \"nrows\": " << equations.size()
<< ", \"ncols\": " << hessianColsNbr * dynJacobianColsNbr
<< ", \"entries\": [";
for (auto it = third_derivatives.begin();
it != third_derivatives.end(); it++)
for (auto it = derivatives[3].begin();
it != derivatives[3].end(); it++)
{
if (it != third_derivatives.begin())
if (it != derivatives[3].begin())
third_derivatives_output << ", ";
int eq, var1, var2, var3;