CppADCodeGen  2.3.0
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.setMaxAssigmentsPerFunction(_maxAssignPerFunc, &_sources);
118  langC.setParameterPrecision(_parameterPrecision);
119  _cache.str("");
120  _cache << _name << "_" << FUNCTION_SPARSE_FORWARD_ONE << "_indep" << j;
121  langC.setGenerateFunction(_cache.str());
122 
123  std::ostringstream code;
124  std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator("dy"));
125  LangCDefaultHessianVarNameGenerator<Base> nameGenHess(nameGen.get(), "dx", n);
126 
127  handler.generateCode(code, langC, dyCustom, nameGenHess, _atomicFunctions, subJobName);
128  }
129 }
130 
131 template<class Base>
132 void ModelCSourceGen<Base>::generateSparseForwardOneSourcesNoAtomics(const std::map<size_t, std::vector<size_t> >& elements) {
133  using std::vector;
134 
138  size_t n = _fun.Domain();
139 
140  CodeHandler<Base> handler;
141  handler.setJobTimer(_jobTimer);
142 
143  vector<CGBase> x(n);
144  handler.makeVariables(x);
145  if (_x.size() > 0) {
146  for (size_t i = 0; i < n; i++) {
147  x[i].setValue(_x[i]);
148  }
149  }
150 
151  CGBase dx;
152  handler.makeVariable(dx);
153  if (_x.size() > 0) {
154  dx.setValue(Base(1.0));
155  }
156 
157  vector<CGBase> jacFlat(_jacSparsity.rows.size());
158 
159  CppAD::sparse_jacobian_work work; // temporary structure for CPPAD
160  _fun.SparseJacobianForward(x, _jacSparsity.sparsity, _jacSparsity.rows, _jacSparsity.cols, jacFlat, work);
161 
165  std::map<size_t, vector<CGBase> > jac; // by column
166  std::map<size_t, std::map<size_t, size_t> > positions; // by column
167 
168  for (const auto& it : elements) {
169  size_t j = it.first;
170  const std::vector<size_t>& column = it.second;
171 
172  jac[j].resize(column.size());
173  std::map<size_t, size_t>& pos = positions[j];
174 
175  for (size_t e = 0; e < column.size(); e++) {
176  size_t i = column[e];
177  pos[i] = e;
178  }
179  }
180 
181  for (size_t el = 0; el < _jacSparsity.rows.size(); el++) {
182  size_t i = _jacSparsity.rows[el];
183  size_t j = _jacSparsity.cols[el];
184  size_t e = positions[j].at(i);
185 
186  vector<CGBase>& column = jac[j];
187  column[e] = jacFlat[el] * dx;
188  }
189 
193  typename std::map<size_t, vector<CGBase> >::iterator itJ;
194  for (itJ = jac.begin(); itJ != jac.end(); ++itJ) {
195  size_t j = itJ->first;
196  vector<CGBase>& dyCustom = itJ->second;
197 
198  _cache.str("");
199  _cache << "model (forward one, indep " << j << ")";
200  const std::string subJobName = _cache.str();
201 
202  LanguageC<Base> langC(_baseTypeName);
203  langC.setMaxAssigmentsPerFunction(_maxAssignPerFunc, &_sources);
204  langC.setParameterPrecision(_parameterPrecision);
205  _cache.str("");
206  _cache << _name << "_" << FUNCTION_SPARSE_FORWARD_ONE << "_indep" << j;
207  langC.setGenerateFunction(_cache.str());
208 
209  std::ostringstream code;
210  std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator("dy"));
211  LangCDefaultHessianVarNameGenerator<Base> nameGenHess(nameGen.get(), "dx", n);
212 
213  handler.generateCode(code, langC, dyCustom, nameGenHess, _atomicFunctions, subJobName);
214  }
215 }
216 
217 template<class Base>
219 
220  size_t m = _fun.Range();
221  size_t n = _fun.Domain();
222 
223  _cache.str("");
224  _cache << _name << "_" << FUNCTION_FORWARD_ONE;
225  std::string model_function(_cache.str());
226 
227  LanguageC<Base> langC(_baseTypeName);
228  std::string argsDcl = langC.generateDefaultFunctionArgumentsDcl();
229  std::string args = langC.generateDefaultFunctionArguments();
230 
231  _cache.str("");
232  _cache << "#include <stdlib.h>\n"
234  "\n"
235  "int " << _name << "_" << FUNCTION_SPARSE_FORWARD_ONE << "(unsigned long pos, " << argsDcl << ");\n"
236  "void " << _name << "_" << FUNCTION_FORWARD_ONE_SPARSITY << "(unsigned long pos, unsigned long const** elements, unsigned long* nnz);\n"
237  "\n";
238  LanguageC<Base>::printFunctionDeclaration(_cache, "int", model_function, {_baseTypeName + " const tx[]",
239  _baseTypeName + " ty[]",
240  langC.generateArgumentAtomicDcl()});
241  _cache << " {\n"
242  " unsigned long ePos, ej, i, j, nnz, nnzMax;\n"
243  " unsigned long const* pos;\n"
244  " unsigned long* txPos;\n"
245  " unsigned long* txPosTmp;\n"
246  " unsigned long nnzTx;\n"
247  " " << _baseTypeName << " const * in[2];\n"
248  " " << _baseTypeName << "* out[1];\n"
249  " " << _baseTypeName << " x[" << n << "];\n"
250  " " << _baseTypeName << "* compressed;\n"
251  " int ret;\n"
252  "\n"
253  " txPos = 0;\n"
254  " nnzTx = 0;\n"
255  " nnzMax = 0;\n"
256  " for (j = 0; j < " << n << "; j++) {\n"
257  " if (tx[j * 2 + 1] != 0.0) {\n"
258  " " << _name << "_" << FUNCTION_FORWARD_ONE_SPARSITY << "(j, &pos, &nnz);\n"
259  " if (nnz > nnzMax)\n"
260  " nnzMax = nnz;\n"
261  " else if (nnz == 0)\n"
262  " continue;\n"
263  " nnzTx++;\n"
264  " txPosTmp = (unsigned long*) realloc(txPos, nnzTx * sizeof(unsigned long));\n"
265  " if (txPosTmp != NULL) {\n"
266  " txPos = txPosTmp;\n"
267  " } else {\n"
268  " free(txPos);\n"
269  " return -1; // failure to allocate memory\n"
270  " }\n"
271  " txPos[nnzTx - 1] = j;\n"
272  " }\n"
273  " }\n"
274  " for (i = 0; i < " << m << "; i++) {\n"
275  " ty[i * 2 + 1] = 0;\n"
276  " }\n"
277  "\n"
278  " if (nnzTx == 0) {\n"
279  " free(txPos);\n"
280  " return 0; //nothing to do\n"
281  " }\n"
282  "\n"
283  " compressed = (" << _baseTypeName << "*) malloc(nnzMax * sizeof(" << _baseTypeName << "));\n"
284  "\n"
285  " for (j = 0; j < " << n << "; j++)\n"
286  " x[j] = tx[j * 2];\n"
287  "\n"
288  " for (ej = 0; ej < nnzTx; ej++) {\n"
289  " j = txPos[ej];\n"
290  " " << _name << "_" << FUNCTION_FORWARD_ONE_SPARSITY << "(j, &pos, &nnz);\n"
291  "\n"
292  " in[0] = x;\n"
293  " in[1] = &tx[j * 2 + 1];\n"
294  " out[0] = compressed;\n";
295  if (!_loopTapes.empty()) {
296  _cache << " for(ePos = 0; ePos < nnz; ePos++)\n"
297  " compressed[ePos] = 0;\n"
298  "\n";
299  }
300  _cache << " ret = " << _name << "_" << FUNCTION_SPARSE_FORWARD_ONE << "(j, " << args << ");\n"
301  "\n"
302  " if (ret != 0) {\n"
303  " free(compressed);\n"
304  " free(txPos);\n"
305  " return ret;\n"
306  " }\n"
307  "\n"
308  " for (ePos = 0; ePos < nnz; ePos++) {\n"
309  " ty[pos[ePos] * 2 + 1] += compressed[ePos];\n"
310  " }\n"
311  "\n"
312  " }\n"
313  " free(compressed);\n"
314  " free(txPos);\n"
315  " return 0;\n"
316  "}\n";
317  _sources[model_function + ".c"] = _cache.str();
318  _cache.str("");
319 }
320 
321 } // END cg namespace
322 } // END CppAD namespace
323 
324 #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)
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:489
void makeVariables(VectorCG &variables)
void makeVariable(AD< CGB > &variable)
virtual void setParameterPrecision(size_t p)
Definition: language_c.hpp:219
virtual void generateCode(std::ostream &out, Language< Base > &lang, CppAD::vector< CGB > &dependent, VariableNameGenerator< Base > &nameGen, const std::string &jobName="source")