CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
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 
18 namespace CppAD {
19 namespace cg {
20 
21 template<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 
61 template<class Base>
62 void 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 
132 template<class Base>
133 void 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 
219 template<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
virtual void generateSparseForwardOneSourcesNoAtomics(const std::map< size_t, std::vector< size_t > > &elements)
void setValue(const Base &val)
Definition: variable.hpp:54
virtual void generateSparseForwardOneSourcesWithAtomics(const std::map< size_t, std::vector< size_t > > &elements)
void setMaxOperationsPerAssignment(size_t maxOperationsPerAssignment)
Definition: language_c.hpp:273
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={})
Definition: language_c.hpp:538
void makeVariables(VectorCG &variables)
virtual void setMaxAssignmentsPerFunction(size_t maxAssignmentsPerFunction, std::map< std::string, std::string > *sources)
Definition: language_c.hpp:252
void makeVariable(AD< CGB > &variable)
virtual void setParameterPrecision(size_t p)
Definition: language_c.hpp:237
virtual void generateCode(std::ostream &out, Language< Base > &lang, CppAD::vector< CGB > &dependent, VariableNameGenerator< Base > &nameGen, const std::string &jobName="source")