1 #ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_REV2_INCLUDED
2 #define CPPAD_CG_MODEL_C_SOURCE_GEN_REV2_INCLUDED
24 determineHessianSparsity();
30 std::vector<size_t> evalRows, evalCols;
31 determineSecondOrderElements4Eval(evalRows, evalCols);
34 std::map<size_t, std::vector<size_t> > elements;
35 for (
size_t e = 0; e < evalCols.size(); e++) {
36 elements[evalRows[e]].push_back(evalCols[e]);
39 if (!_loopTapes.empty()) {
43 prepareSparseReverseTwoWithLoops(elements);
47 if (!evalRows.empty()) {
49 startingJob(
"'model (reverse two)'", JobTimer::SOURCE_GENERATION);
51 if (isAtomicsUsed()) {
52 generateSparseReverseTwoSourcesWithAtomics(elements);
54 generateSparseReverseTwoSourcesNoAtomics(elements, evalRows, evalCols);
62 generateGlobalDirectionalFunctionSource(FUNCTION_SPARSE_REVERSE_TWO,
64 FUNCTION_REVERSE_TWO_SPARSITY,
72 const size_t m = _fun.Range();
73 const size_t n = _fun.Domain();
79 for (
const auto& it : elements) {
81 const std::vector<size_t>& cols = it.second;
84 _cache <<
"model (reverse two, indep " << j <<
")";
85 const std::string subJobName = _cache.str();
87 startingJob(
"'" + subJobName +
"'", JobTimer::GRAPH);
90 handler.setJobTimer(_jobTimer);
95 for (
size_t i = 0; i < n; i++) {
96 tx0[i].setValue(_x[i]);
103 tx1.setValue(Base(1.0));
106 vector<CGBase> py(m);
109 for (
size_t i = 0; i < m; i++) {
110 py[i].setValue(Base(1.0));
114 _fun.Forward(0, tx0);
117 _fun.Forward(1, tx1v);
119 vector<CGBase> px = _fun.Reverse(2, py);
120 CPPADCG_ASSERT_UNKNOWN(px.size() == 2 * n);
122 vector<CGBase> pxCustom;
123 for (
size_t jj : cols) {
124 pxCustom.push_back(px[jj * p + 1]);
129 LanguageC<Base> langC(_baseTypeName);
130 langC.setMaxAssignmentsPerFunction(_maxAssignPerFunc, &_sources);
131 langC.setMaxOperationsPerAssignment(_maxOperationsPerAssignment);
132 langC.setParameterPrecision(_parameterPrecision);
134 _cache << _name <<
"_" << FUNCTION_SPARSE_REVERSE_TWO <<
"_indep" << j;
135 langC.setGenerateFunction(_cache.str());
137 std::ostringstream code;
138 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"px"));
139 LangCDefaultReverse2VarNameGenerator<Base> nameGenRev2(nameGen.get(), n, 1);
141 handler.
generateCode(code, langC, pxCustom, nameGenRev2, _atomicFunctions, subJobName);
147 const std::vector<size_t>& evalRows,
148 const std::vector<size_t>& evalCols) {
151 const size_t m = _fun.Range();
152 const size_t n = _fun.Domain();
155 std::map<size_t, std::map<size_t, size_t> > positions;
156 for (
const auto& itJ1 : elements) {
157 size_t j1 = itJ1.first;
158 const std::vector<size_t>& row = itJ1.second;
159 std::map<size_t, size_t>& pos = positions[j1];
161 for (
size_t e = 0; e < row.size(); e++) {
169 handler.setJobTimer(_jobTimer);
174 for (
size_t i = 0; i < n; i++) {
175 tx0[i].setValue(_x[i]);
188 for (
size_t i = 0; i < m; i++) {
189 py[i].setValue(Base(1.0));
195 CppAD::sparse_hessian_work work;
198 work.color_method =
"cppad.symmetric";
199 _fun.SparseHessian(tx0, py, _hessSparsity.sparsity, evalRows, evalCols, hessFlat, work);
201 std::map<size_t, vector<CGBase> > hess;
202 for (
const auto& itJ1 : elements) {
203 size_t j1 = itJ1.first;
204 hess[j1].resize(itJ1.second.size());
208 for (
size_t el = 0; el < evalRows.size(); el++) {
209 size_t j1 = evalRows[el];
210 size_t j2 = evalCols[el];
211 size_t e = positions[j1][j2];
213 hess[j1][e] = hessFlat[el];
219 for (
const auto& it : hess) {
224 _cache <<
"model (reverse two, indep " << j <<
")";
225 const std::string subJobName = _cache.str();
228 for (
size_t e = 0; e < row.size(); e++) {
229 pxCustom[e] = row[e] * tx1;
237 _cache << _name <<
"_" << FUNCTION_SPARSE_REVERSE_TWO <<
"_indep" << j;
238 langC.setGenerateFunction(_cache.str());
240 std::ostringstream code;
241 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"px"));
244 handler.
generateCode(code, langC, pxCustom, nameGenRev2, _atomicFunctions, subJobName);
250 size_t m = _fun.Range();
251 size_t n = _fun.Domain();
254 _cache << _name <<
"_" << FUNCTION_REVERSE_TWO;
255 std::string model_function(_cache.str());
259 std::string argsDcl = langC.generateDefaultFunctionArgumentsDcl();
260 std::string args = langC.generateDefaultFunctionArguments();
262 _cache <<
"#include <stdlib.h>\n"
265 "int " << _name <<
"_" << FUNCTION_SPARSE_REVERSE_TWO <<
"(unsigned long pos, " << argsDcl <<
");\n"
266 "void " << _name <<
"_" << FUNCTION_REVERSE_TWO_SPARSITY <<
"(unsigned long pos, unsigned long const** elements, unsigned long* nnz);\n"
269 _baseTypeName +
" const ty[]",
270 _baseTypeName +
" px[]",
271 _baseTypeName +
" const py[]",
272 langC.generateArgumentAtomicDcl()});
274 " unsigned long ej, ePos, i, j, nnz, nnzMax;\n"
275 " unsigned long const* pos;\n"
276 " unsigned long* txPos;\n"
277 " unsigned long* txPosTmp;\n"
278 " unsigned long nnzTx;\n"
279 " " << _baseTypeName <<
" const * in[3];\n"
280 " " << _baseTypeName <<
"* out[1];\n"
281 " " << _baseTypeName <<
" x[" << n <<
"];\n"
282 " " << _baseTypeName <<
" w[" << m <<
"];\n"
283 " " << _baseTypeName <<
"* compressed;\n"
288 " for (i = 0; i < " << m <<
"; i++) {\n"
289 " if (py[i * 2] != 0.0) {\n"
290 " return 1; // error\n"
292 " w[i] = py[i * 2 + 1];\n"
293 " if(w[i] != 0.0) nonZeroW++;\n"
296 " for (j = 0; j < " << n <<
"; j++) {\n"
300 " if (nonZeroW == 0)\n"
301 " return 0; //nothing to do\n"
306 " for (j = 0; j < " << n <<
"; j++) {\n"
307 " if (tx[j * 2 + 1] != 0.0) {\n"
308 " " << _name <<
"_" << FUNCTION_REVERSE_TWO_SPARSITY <<
"(j, &pos, &nnz);\n"
309 " if (nnz > nnzMax)\n"
311 " else if (nnz == 0)\n"
314 " txPosTmp = (unsigned long*) realloc(txPos, nnzTx * sizeof(unsigned long));\n"
315 " if (txPosTmp != NULL) {\n"
316 " txPos = txPosTmp;\n"
319 " return -1; // failure to allocate memory\n"
321 " txPos[nnzTx - 1] = j;\n"
325 " if (nnzTx == 0) {\n"
327 " return 0; // nothing to do\n"
330 " for (j = 0; j < " << n <<
"; j++)\n"
331 " x[j] = tx[j * 2];\n"
333 " compressed = (" << _baseTypeName <<
"*) malloc(nnzMax * sizeof(" << _baseTypeName <<
"));\n"
335 " for (ej = 0; ej < nnzTx; ej++) {\n"
337 " " << _name <<
"_" << FUNCTION_REVERSE_TWO_SPARSITY <<
"(j, &pos, &nnz);\n"
340 " in[1] = &tx[j * 2 + 1];\n"
342 " out[0] = compressed;\n";
343 if (!_loopTapes.empty()) {
344 _cache <<
" for (ePos = 0; ePos < nnz; ePos++)\n"
345 " compressed[ePos] = 0;\n"
348 _cache <<
" ret = " << _name <<
"_" << FUNCTION_SPARSE_REVERSE_TWO <<
"(j, " << args <<
");\n"
351 " free(compressed);\n"
356 " for (ePos = 0; ePos < nnz; ePos++) {\n"
357 " px[pos[ePos] * 2] += compressed[ePos];\n"
361 " free(compressed);\n"
366 _sources[model_function +
".c"] = _cache.str();
void setValue(const Base &val)
void makeVariables(VectorCG &variables)
void makeVariable(AD< CGB > &variable)
virtual void generateCode(std::ostream &out, Language< Base > &lang, CppAD::vector< CGB > &dependent, VariableNameGenerator< Base > &nameGen, const std::string &jobName="source")
virtual void setParameterPrecision(size_t p)
static void printFunctionDeclaration(std::ostringstream &out, const std::string &returnType, const std::string &functionName, const std::vector< std::string > &arguments, const std::vector< std::string > &arguments2={})
void setMaxOperationsPerAssignment(size_t maxOperationsPerAssignment)
virtual void setMaxAssignmentsPerFunction(size_t maxAssignmentsPerFunction, std::map< std::string, std::string > *sources)
virtual void generateSparseReverseTwoSourcesNoAtomics(const std::map< size_t, std::vector< size_t > > &elements, const std::vector< size_t > &evalRows, const std::vector< size_t > &evalCols)
virtual void generateSparseReverseTwoSources()