1 #ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_REV1_INCLUDED 2 #define CPPAD_CG_MODEL_C_SOURCE_GEN_REV1_INCLUDED 24 determineJacobianSparsity();
27 std::map<size_t, std::vector<size_t> > elements;
28 for (
size_t e = 0; e < _jacSparsity.rows.size(); e++) {
29 elements[_jacSparsity.rows[e]].push_back(_jacSparsity.cols[e]);
32 if (!_loopTapes.empty()) {
36 prepareSparseReverseOneWithLoops(elements);
43 startingJob(
"'model (reverse one)'", JobTimer::SOURCE_GENERATION);
45 if (isAtomicsUsed()) {
46 generateSparseReverseOneSourcesWithAtomics(elements);
48 generateSparseReverseOneSourcesNoAtomics(elements);
55 generateGlobalDirectionalFunctionSource(FUNCTION_SPARSE_REVERSE_ONE,
57 FUNCTION_REVERSE_ONE_SPARSITY,
68 size_t m = _fun.Range();
69 size_t n = _fun.Domain();
76 const std::string jobName =
"model (reverse one)";
77 startingJob(
"'" + jobName +
"'", JobTimer::SOURCE_GENERATION);
79 for (
const auto& it : elements) {
81 const std::vector<size_t>& cols = it.second;
84 _cache <<
"model (reverse one, dep " << i <<
")";
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 indVars[i].setValue(_x[i]);
107 _fun.Forward(0, indVars);
111 CPPADCG_ASSERT_UNKNOWN(dw.size() == n);
115 for (
size_t it2 : cols) {
116 dwCustom.push_back(dw[it2]);
122 langC.setMaxAssigmentsPerFunction(_maxAssignPerFunc, &_sources);
125 _cache << _name <<
"_" << FUNCTION_SPARSE_REVERSE_ONE <<
"_dep" << i;
126 langC.setGenerateFunction(_cache.str());
128 std::ostringstream code;
129 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"dw"));
132 handler.
generateCode(code, langC, dwCustom, nameGenHess, _atomicFunctions, subJobName);
143 size_t m = _fun.Range();
144 size_t n = _fun.Domain();
147 handler.setJobTimer(_jobTimer);
152 for (
size_t i = 0; i < n; i++) {
153 x[i].setValue(_x[i]);
165 CppAD::sparse_jacobian_work work;
166 _fun.SparseJacobianReverse(x, _jacSparsity.sparsity, _jacSparsity.rows, _jacSparsity.cols, jacFlat, work);
171 std::map<size_t, vector<CGBase> > jac;
172 std::vector<std::map<size_t, size_t> > positions(m);
174 for (
const auto& it : elements) {
176 const std::vector<size_t>& row = it.second;
178 jac[i].resize(row.size());
179 std::map<size_t, size_t>& pos = positions[i];
181 for (
size_t e = 0; e < row.size(); e++) {
187 for (
size_t el = 0; el < _jacSparsity.rows.size(); el++) {
188 size_t i = _jacSparsity.rows[el];
189 size_t j = _jacSparsity.cols[el];
190 size_t e = positions[i].at(j);
193 row[e] = jacFlat[el] * py;
199 typename std::map<size_t, vector<CGBase> >::iterator itI;
200 for (itI = jac.begin(); itI != jac.end(); ++itI) {
201 size_t i = itI->first;
205 _cache <<
"model (reverse one, dep " << i <<
")";
206 const std::string subJobName = _cache.str();
209 langC.setMaxAssigmentsPerFunction(_maxAssignPerFunc, &_sources);
212 _cache << _name <<
"_" << FUNCTION_SPARSE_REVERSE_ONE <<
"_dep" << i;
213 langC.setGenerateFunction(_cache.str());
215 std::ostringstream code;
216 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"dw"));
219 handler.
generateCode(code, langC, dwCustom, nameGenHess, _atomicFunctions, subJobName);
225 size_t m = _fun.Range();
226 size_t n = _fun.Domain();
229 _cache << _name <<
"_" << FUNCTION_REVERSE_ONE;
230 std::string model_function(_cache.str());
234 std::string argsDcl = langC.generateDefaultFunctionArgumentsDcl();
235 std::string args = langC.generateDefaultFunctionArguments();
237 _cache <<
"#include <stdlib.h>\n" 240 "int " << _name <<
"_" << FUNCTION_SPARSE_REVERSE_ONE <<
"(unsigned long pos, " << argsDcl <<
");\n" 241 "void " << _name <<
"_" << FUNCTION_REVERSE_ONE_SPARSITY <<
"(unsigned long pos, unsigned long const** elements, unsigned long* nnz);\n" 244 _baseTypeName +
" const ty[]",
245 _baseTypeName +
" px[]",
246 _baseTypeName +
" const py[]",
247 langC.generateArgumentAtomicDcl()});
249 " unsigned long ei, ePos, i, j, nnz, nnzMax;\n" 250 " unsigned long const* pos;\n" 251 " unsigned long* pyPos;\n" 252 " unsigned long* pyPosTmp;\n" 253 " unsigned long nnzPy;\n" 254 " " << _baseTypeName <<
" const * in[2];\n" 255 " " << _baseTypeName <<
"* out[1];\n" 256 " " << _baseTypeName <<
"* compressed;\n" 262 " for (i = 0; i < " << m <<
"; i++) {\n" 263 " if (py[i] != 0.0) {\n" 264 " " << _name <<
"_" << FUNCTION_REVERSE_ONE_SPARSITY <<
"(i, &pos, &nnz);\n" 265 " if (nnz > nnzMax)\n" 267 " else if (nnz == 0)\n" 270 " pyPosTmp = (unsigned long*) realloc(pyPos, nnzPy * sizeof(unsigned long));\n" 271 " if (pyPosTmp != NULL) {\n" 272 " pyPos = pyPosTmp;\n" 275 " return -1; // failure to allocate memory\n" 277 " pyPos[nnzPy - 1] = i;\n" 280 " for (j = 0; j < " << n <<
"; j++) {\n" 284 " if (nnzPy == 0) {\n" 286 " return 0; //nothing to do\n" 289 " compressed = (" << _baseTypeName <<
"*) malloc(nnzMax * sizeof(" << _baseTypeName <<
"));\n" 291 " for (ei = 0; ei < nnzPy; ei++) {\n" 293 " " << _name <<
"_" << FUNCTION_REVERSE_ONE_SPARSITY <<
"(i, &pos, &nnz);\n" 297 " out[0] = compressed;\n";
298 if (!_loopTapes.empty()) {
299 _cache <<
" for(ePos = 0; ePos < nnz; ePos++)\n" 300 " compressed[ePos] = 0;\n" 303 _cache <<
" ret = " << _name <<
"_" << FUNCTION_SPARSE_REVERSE_ONE <<
"(i, " << args <<
");\n" 306 " free(compressed);\n" 311 " for (ePos = 0; ePos < nnz; ePos++) {\n" 312 " px[pos[ePos]] += compressed[ePos];\n" 316 " free(compressed);\n" 320 _sources[model_function +
".c"] = _cache.str();
void setValue(const Base &val)
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 makeVariables(VectorCG &variables)
virtual void generateSparseReverseOneSources()
void makeVariable(AD< CGB > &variable)
virtual void setParameterPrecision(size_t p)
virtual void generateSparseReverseOneSourcesWithAtomics(const std::map< size_t, std::vector< size_t > > &elements)
virtual void generateCode(std::ostream &out, Language< Base > &lang, CppAD::vector< CGB > &dependent, VariableNameGenerator< Base > &nameGen, const std::string &jobName="source")
virtual void generateSparseReverseOneSourcesNoAtomics(const std::map< size_t, std::vector< size_t > > &elements)