CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
model_c_source_gen_for1.hpp
1#ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_FOR1_INCLUDED
2#define CPPAD_CG_MODEL_C_SOURCE_GEN_FOR1_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2012 Ciengis
6 *
7 * CppADCodeGen is distributed under multiple licenses:
8 *
9 * - Eclipse Public License Version 1.0 (EPL1), and
10 * - GNU General Public License Version 3 (GPL3).
11 *
12 * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13 * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14 * ----------------------------------------------------------------------------
15 * Author: Joao Leal
16 */
17
18namespace CppAD {
19namespace cg {
20
21template<class Base>
23
24 determineJacobianSparsity();
25
26 // elements[var]{equations}
27 std::map<size_t, std::vector<size_t> > elements;
28 for (size_t e = 0; e < _jacSparsity.rows.size(); e++) {
29 elements[_jacSparsity.cols[e]].push_back(_jacSparsity.rows[e]);
30 }
31
32 if (!_loopTapes.empty()) {
36 prepareSparseForwardOneWithLoops(elements);
37 return;
38 }
39
43 startingJob("'model (forward one)'", JobTimer::SOURCE_GENERATION);
44
45 if (isAtomicsUsed()) {
46 generateSparseForwardOneSourcesWithAtomics(elements);
47 } else {
48 generateSparseForwardOneSourcesNoAtomics(elements);
49 }
50
51 finishedJob();
52
53 _cache.str("");
54
55 generateGlobalDirectionalFunctionSource(FUNCTION_SPARSE_FORWARD_ONE,
56 "indep",
57 FUNCTION_FORWARD_ONE_SPARSITY,
58 elements);
59}
60
61template<class Base>
62void ModelCSourceGen<Base>::generateSparseForwardOneSourcesWithAtomics(const std::map<size_t, std::vector<size_t> >& elements) {
63 using std::vector;
64
68 size_t n = _fun.Domain();
69
70 vector<CGBase> dxv(n);
71
72 const std::string jobName = "model (forward one)";
73 startingJob("'" + jobName + "'", JobTimer::SOURCE_GENERATION);
74
75 for (const auto& it : elements) {
76 size_t j = it.first;
77 const std::vector<size_t>& rows = it.second;
78
79 _cache.str("");
80 _cache << "model (forward one, indep " << j << ")";
81 const std::string subJobName = _cache.str();
82
83 startingJob("'" + subJobName + "'", JobTimer::GRAPH);
84
85 CodeHandler<Base> handler;
86 handler.setJobTimer(_jobTimer);
87
88 vector<CGBase> indVars(n);
89 handler.makeVariables(indVars);
90 if (_x.size() > 0) {
91 for (size_t i = 0; i < n; i++) {
92 indVars[i].setValue(_x[i]);
93 }
94 }
95
96 CGBase dx;
97 handler.makeVariable(dx);
98 if (_x.size() > 0) {
99 dx.setValue(Base(1.0));
100 }
101
102 // TODO: consider caching the zero order coefficients somehow between calls
103 _fun.Forward(0, indVars);
104 dxv[j] = dx;
105 vector<CGBase> dy = _fun.Forward(1, dxv);
106 dxv[j] = Base(0);
107 CPPADCG_ASSERT_UNKNOWN(dy.size() == _fun.Range());
108
109 vector<CGBase> dyCustom;
110 for (size_t it2 : rows) {
111 dyCustom.push_back(dy[it2]);
112 }
113
114 finishedJob();
115
116 LanguageC<Base> langC(_baseTypeName);
117 langC.setMaxAssignmentsPerFunction(_maxAssignPerFunc, &_sources);
118 langC.setMaxOperationsPerAssignment(_maxOperationsPerAssignment);
119 langC.setParameterPrecision(_parameterPrecision);
120 _cache.str("");
121 _cache << _name << "_" << FUNCTION_SPARSE_FORWARD_ONE << "_indep" << j;
122 langC.setGenerateFunction(_cache.str());
123
124 std::ostringstream code;
125 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator("dy"));
126 LangCDefaultHessianVarNameGenerator<Base> nameGenHess(nameGen.get(), "dx", n);
127
128 handler.generateCode(code, langC, dyCustom, nameGenHess, _atomicFunctions, subJobName);
129 }
130}
131
132template<class Base>
133void ModelCSourceGen<Base>::generateSparseForwardOneSourcesNoAtomics(const std::map<size_t, std::vector<size_t> >& elements) {
134 using std::vector;
135
139 size_t n = _fun.Domain();
140
141 CodeHandler<Base> handler;
142 handler.setJobTimer(_jobTimer);
143
144 vector<CGBase> x(n);
145 handler.makeVariables(x);
146 if (_x.size() > 0) {
147 for (size_t i = 0; i < n; i++) {
148 x[i].setValue(_x[i]);
149 }
150 }
151
152 CGBase dx;
153 handler.makeVariable(dx);
154 if (_x.size() > 0) {
155 dx.setValue(Base(1.0));
156 }
157
158 vector<CGBase> jacFlat(_jacSparsity.rows.size());
159
160 CppAD::sparse_jacobian_work work; // temporary structure for CPPAD
161 _fun.SparseJacobianForward(x, _jacSparsity.sparsity, _jacSparsity.rows, _jacSparsity.cols, jacFlat, work);
162
166 std::map<size_t, vector<CGBase> > jac; // by column
167 std::map<size_t, std::map<size_t, size_t> > positions; // by column
168
169 for (const auto& it : elements) {
170 size_t j = it.first;
171 const std::vector<size_t>& column = it.second;
172
173 jac[j].resize(column.size());
174 std::map<size_t, size_t>& pos = positions[j];
175
176 for (size_t e = 0; e < column.size(); e++) {
177 size_t i = column[e];
178 pos[i] = e;
179 }
180 }
181
182 for (size_t el = 0; el < _jacSparsity.rows.size(); el++) {
183 size_t i = _jacSparsity.rows[el];
184 size_t j = _jacSparsity.cols[el];
185 size_t e = positions[j].at(i);
186
187 vector<CGBase>& column = jac[j];
188 column[e] = jacFlat[el] * dx;
189 }
190
194 typename std::map<size_t, vector<CGBase> >::iterator itJ;
195 for (itJ = jac.begin(); itJ != jac.end(); ++itJ) {
196 size_t j = itJ->first;
197 vector<CGBase>& dyCustom = itJ->second;
198
199 _cache.str("");
200 _cache << "model (forward one, indep " << j << ")";
201 const std::string subJobName = _cache.str();
202
203 LanguageC<Base> langC(_baseTypeName);
204 langC.setMaxAssignmentsPerFunction(_maxAssignPerFunc, &_sources);
205 langC.setMaxOperationsPerAssignment(_maxOperationsPerAssignment);
206 langC.setParameterPrecision(_parameterPrecision);
207 _cache.str("");
208 _cache << _name << "_" << FUNCTION_SPARSE_FORWARD_ONE << "_indep" << j;
209 langC.setGenerateFunction(_cache.str());
210
211 std::ostringstream code;
212 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator("dy"));
213 LangCDefaultHessianVarNameGenerator<Base> nameGenHess(nameGen.get(), "dx", n);
214
215 handler.generateCode(code, langC, dyCustom, nameGenHess, _atomicFunctions, subJobName);
216 }
217}
218
219template<class Base>
221
222 size_t m = _fun.Range();
223 size_t n = _fun.Domain();
224
225 _cache.str("");
226 _cache << _name << "_" << FUNCTION_FORWARD_ONE;
227 std::string model_function(_cache.str());
228
229 LanguageC<Base> langC(_baseTypeName);
230 std::string argsDcl = langC.generateDefaultFunctionArgumentsDcl();
231 std::string args = langC.generateDefaultFunctionArguments();
232
233 _cache.str("");
234 _cache << "#include <stdlib.h>\n"
236 "\n"
237 "int " << _name << "_" << FUNCTION_SPARSE_FORWARD_ONE << "(unsigned long pos, " << argsDcl << ");\n"
238 "void " << _name << "_" << FUNCTION_FORWARD_ONE_SPARSITY << "(unsigned long pos, unsigned long const** elements, unsigned long* nnz);\n"
239 "\n";
240 LanguageC<Base>::printFunctionDeclaration(_cache, "int", model_function, {_baseTypeName + " const tx[]",
241 _baseTypeName + " ty[]",
242 langC.generateArgumentAtomicDcl()});
243 _cache << " {\n"
244 " unsigned long ePos, ej, i, j, nnz, nnzMax;\n"
245 " unsigned long const* pos;\n"
246 " unsigned long* txPos;\n"
247 " unsigned long* txPosTmp;\n"
248 " unsigned long nnzTx;\n"
249 " " << _baseTypeName << " const * in[2];\n"
250 " " << _baseTypeName << "* out[1];\n"
251 " " << _baseTypeName << " x[" << n << "];\n"
252 " " << _baseTypeName << "* compressed;\n"
253 " int ret;\n"
254 "\n"
255 " txPos = 0;\n"
256 " nnzTx = 0;\n"
257 " nnzMax = 0;\n"
258 " for (j = 0; j < " << n << "; j++) {\n"
259 " if (tx[j * 2 + 1] != 0.0) {\n"
260 " " << _name << "_" << FUNCTION_FORWARD_ONE_SPARSITY << "(j, &pos, &nnz);\n"
261 " if (nnz > nnzMax)\n"
262 " nnzMax = nnz;\n"
263 " else if (nnz == 0)\n"
264 " continue;\n"
265 " nnzTx++;\n"
266 " txPosTmp = (unsigned long*) realloc(txPos, nnzTx * sizeof(unsigned long));\n"
267 " if (txPosTmp != NULL) {\n"
268 " txPos = txPosTmp;\n"
269 " } else {\n"
270 " free(txPos);\n"
271 " return -1; // failure to allocate memory\n"
272 " }\n"
273 " txPos[nnzTx - 1] = j;\n"
274 " }\n"
275 " }\n"
276 " for (i = 0; i < " << m << "; i++) {\n"
277 " ty[i * 2 + 1] = 0;\n"
278 " }\n"
279 "\n"
280 " if (nnzTx == 0) {\n"
281 " free(txPos);\n"
282 " return 0; //nothing to do\n"
283 " }\n"
284 "\n"
285 " compressed = (" << _baseTypeName << "*) malloc(nnzMax * sizeof(" << _baseTypeName << "));\n"
286 "\n"
287 " for (j = 0; j < " << n << "; j++)\n"
288 " x[j] = tx[j * 2];\n"
289 "\n"
290 " for (ej = 0; ej < nnzTx; ej++) {\n"
291 " j = txPos[ej];\n"
292 " " << _name << "_" << FUNCTION_FORWARD_ONE_SPARSITY << "(j, &pos, &nnz);\n"
293 "\n"
294 " in[0] = x;\n"
295 " in[1] = &tx[j * 2 + 1];\n"
296 " out[0] = compressed;\n";
297 if (!_loopTapes.empty()) {
298 _cache << " for(ePos = 0; ePos < nnz; ePos++)\n"
299 " compressed[ePos] = 0;\n"
300 "\n";
301 }
302 _cache << " ret = " << _name << "_" << FUNCTION_SPARSE_FORWARD_ONE << "(j, " << args << ");\n"
303 "\n"
304 " if (ret != 0) {\n"
305 " free(compressed);\n"
306 " free(txPos);\n"
307 " return ret;\n"
308 " }\n"
309 "\n"
310 " for (ePos = 0; ePos < nnz; ePos++) {\n"
311 " ty[pos[ePos] * 2 + 1] += compressed[ePos];\n"
312 " }\n"
313 "\n"
314 " }\n"
315 " free(compressed);\n"
316 " free(txPos);\n"
317 " return 0;\n"
318 "}\n";
319 _sources[model_function + ".c"] = _cache.str();
320 _cache.str("");
321}
322
323} // END cg namespace
324} // END CppAD namespace
325
326#endif
void setValue(const Base &val)
Definition variable.hpp:54
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 generateSparseForwardOneSourcesWithAtomics(const std::map< size_t, std::vector< size_t > > &elements)
virtual void generateSparseForwardOneSourcesNoAtomics(const std::map< size_t, std::vector< size_t > > &elements)