CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
model_c_source_gen_hes.hpp
1 #ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_HES_INCLUDED
2 #define CPPAD_CG_MODEL_C_SOURCE_GEN_HES_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>
22 void ModelCSourceGen<Base>::generateHessianSource() {
23  using std::vector;
24 
25  const std::string jobName = "Hessian";
26 
27  startingJob("'" + jobName + "'", JobTimer::GRAPH);
28 
29  CodeHandler<Base> handler;
30  handler.setJobTimer(_jobTimer);
31 
32  size_t m = _fun.Range();
33  size_t n = _fun.Domain();
34 
35 
36  // independent variables
37  vector<CGBase> indVars(n);
38  handler.makeVariables(indVars);
39  if (_x.size() > 0) {
40  for (size_t i = 0; i < n; i++) {
41  indVars[i].setValue(_x[i]);
42  }
43  }
44 
45  // multipliers
46  vector<CGBase> w(m);
47  handler.makeVariables(w);
48  if (_x.size() > 0) {
49  for (size_t i = 0; i < m; i++) {
50  w[i].setValue(Base(1.0));
51  }
52  }
53 
54  vector<CGBase> hess = _fun.Hessian(indVars, w);
55 
56  // make use of the symmetry of the Hessian in order to reduce operations
57  for (size_t i = 0; i < n; i++) {
58  for (size_t j = 0; j < i; j++) {
59  hess[i * n + j] = hess[j * n + i];
60  }
61  }
62 
63  finishedJob();
64 
65  LanguageC<Base> langC(_baseTypeName);
66  langC.setMaxAssignmentsPerFunction(_maxAssignPerFunc, &_sources);
67  langC.setMaxOperationsPerAssignment(_maxOperationsPerAssignment);
68  langC.setParameterPrecision(_parameterPrecision);
69  langC.setGenerateFunction(_name + "_" + FUNCTION_HESSIAN);
70 
71  std::ostringstream code;
72  std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator("hess"));
73  LangCDefaultHessianVarNameGenerator<Base> nameGenHess(nameGen.get(), n);
74 
75  handler.generateCode(code, langC, hess, nameGenHess, _atomicFunctions, jobName);
76 }
77 
78 template<class Base>
79 void ModelCSourceGen<Base>::generateSparseHessianSource(MultiThreadingType multiThreadingType) {
83  determineHessianSparsity();
84 
85  if (_sparseHessianReusesRev2 && _reverseTwo) {
86  generateSparseHessianSourceFromRev2(multiThreadingType);
87  } else {
88  generateSparseHessianSourceDirectly();
89  }
90 }
91 
92 template<class Base>
94  using std::vector;
95 
96  const std::string jobName = "sparse Hessian";
97  size_t m = _fun.Range();
98  size_t n = _fun.Domain();
99 
104  std::vector<size_t> evalRows, evalCols;
105  determineSecondOrderElements4Eval(evalRows, evalCols);
106 
107  std::map<size_t, std::map<size_t, size_t> > locations;
108  for (size_t e = 0; e < evalRows.size(); e++) {
109  size_t j1 = evalRows[e];
110  size_t j2 = evalCols[e];
111  std::map<size_t, std::map<size_t, size_t> >::iterator itJ1 = locations.find(j1);
112  if (itJ1 == locations.end()) {
113  locations[j1][j2] = e;
114  } else {
115  std::map<size_t, size_t>& j22e = itJ1->second;
116  if (j22e.find(j2) == j22e.end()) {
117  j22e[j2] = e; // OK
118  } else {
119  // repeated elements not allowed
120  throw CGException("Repeated Hessian element requested: ", j1, " ", j2);
121  }
122  }
123  }
124 
125  // make use of the symmetry of the Hessian in order to reduce operations
126  std::vector<size_t> lowerHessRows, lowerHessCols, lowerHessOrder;
127  lowerHessRows.reserve(_hessSparsity.rows.size() / 2);
128  lowerHessCols.reserve(lowerHessRows.size());
129  lowerHessOrder.reserve(lowerHessRows.size());
130 
131  std::map<size_t, size_t> duplicates; // the elements determined using symmetry
132  std::map<size_t, std::map<size_t, size_t> >::const_iterator itJ;
133  std::map<size_t, size_t>::const_iterator itI;
134  for (size_t e = 0; e < evalRows.size(); e++) {
135  bool add = true;
136  size_t i = evalRows[e];
137  size_t j = evalCols[e];
138  if (i < j) {
139  // find the symmetric value
140  itJ = locations.find(j);
141  if (itJ != locations.end()) {
142  itI = itJ->second.find(i);
143  if (itI != itJ->second.end()) {
144  size_t eSim = itI->second;
145  duplicates[e] = eSim;
146  add = false; // symmetric value being determined
147  }
148  }
149  }
150 
151  if (add) {
152  lowerHessRows.push_back(i);
153  lowerHessCols.push_back(j);
154  lowerHessOrder.push_back(e);
155  }
156  }
157 
161  startingJob("'" + jobName + "'", JobTimer::GRAPH);
162 
163  CodeHandler<Base> handler;
164  handler.setJobTimer(_jobTimer);
165 
166  // independent variables
167  vector<CGBase> indVars(n);
168  handler.makeVariables(indVars);
169  if (_x.size() > 0) {
170  for (size_t i = 0; i < n; i++) {
171  indVars[i].setValue(_x[i]);
172  }
173  }
174 
175  // multipliers
176  vector<CGBase> w(m);
177  handler.makeVariables(w);
178  if (_x.size() > 0) {
179  for (size_t i = 0; i < m; i++) {
180  w[i].setValue(Base(1.0));
181  }
182  }
183 
184  vector<CGBase> hess(_hessSparsity.rows.size());
185  if (_loopTapes.empty()) {
186  CppAD::sparse_hessian_work work;
187  // "cppad.symmetric" may have missing values for functions using atomic
188  // functions which only provide half of the elements
189  // (some values could be zeroed)
190  work.color_method = "cppad.general";
191  vector<CGBase> lowerHess(lowerHessRows.size());
192  _fun.SparseHessian(indVars, w, _hessSparsity.sparsity, lowerHessRows, lowerHessCols, lowerHess, work);
193 
194  for (size_t i = 0; i < lowerHessOrder.size(); i++) {
195  hess[lowerHessOrder[i]] = lowerHess[i];
196  }
197 
198  // make use of the symmetry of the Hessian in order to reduce operations
199  for (const auto& it2 : duplicates) {
200  hess[it2.first] = hess[it2.second];
201  }
202  } else {
206  hess = prepareSparseHessianWithLoops(handler, indVars, w,
207  lowerHessRows, lowerHessCols, lowerHessOrder,
208  duplicates);
209  }
210 
211  finishedJob();
212 
213  LanguageC<Base> langC(_baseTypeName);
214  langC.setMaxAssignmentsPerFunction(_maxAssignPerFunc, &_sources);
215  langC.setMaxOperationsPerAssignment(_maxOperationsPerAssignment);
216  langC.setParameterPrecision(_parameterPrecision);
217  langC.setGenerateFunction(_name + "_" + FUNCTION_SPARSE_HESSIAN);
218 
219  std::ostringstream code;
220  std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator("hess"));
221  LangCDefaultHessianVarNameGenerator<Base> nameGenHess(nameGen.get(), n);
222 
223  handler.generateCode(code, langC, hess, nameGenHess, _atomicFunctions, jobName);
224 }
225 
226 template<class Base>
227 void ModelCSourceGen<Base>::generateSparseHessianSourceFromRev2(MultiThreadingType multiThreadingType) {
228  using namespace std;
229 
234  std::vector<size_t> evalRows, evalCols;
235  determineSecondOrderElements4Eval(evalRows, evalCols);
236 
237  std::map<size_t, CompressedVectorInfo> hessInfo;
238 
239  // elements[var]{var}
240  for (size_t e = 0; e < evalRows.size(); e++) {
241  hessInfo[evalRows[e]].indexes.push_back(evalCols[e]);
242  }
243 
244  // maps each element to its position in the user hessian
245  for (auto& it : hessInfo) {
246  it.second.locations = determineOrderByRow(it.first, it.second.indexes, evalRows, evalCols);
247  }
248 
253  for (auto& it : hessInfo) {
254  const std::vector<size_t>& els = it.second.indexes;
255  const std::vector<set<size_t> >& location = it.second.locations;
256  CPPADCG_ASSERT_UNKNOWN(els.size() == location.size());
257  CPPADCG_ASSERT_UNKNOWN(els.size() > 0);
258 
259  bool passed = true;
260  size_t hessRowStart = *location[0].begin();
261  for (size_t e = 0; e < els.size(); e++) {
262  if (location[e].size() > 1) {
263  passed = false; // too many elements
264  break;
265  }
266  if (*location[e].begin() != hessRowStart + e) {
267  passed = false; // wrong order
268  break;
269  }
270  }
271  it.second.ordered = passed;
272  }
273 
277  size_t maxCompressedSize = 0;
278 
279  for (const auto& it : hessInfo) {
280  if (it.second.indexes.size() > maxCompressedSize && !it.second.ordered)
281  maxCompressedSize = it.second.indexes.size();
282  }
283 
284  if (!_loopTapes.empty()) {
288  generateSparseHessianWithLoopsSourceFromRev2(hessInfo, maxCompressedSize);
289  return;
290  }
291 
292  string functionName = _name + "_" + FUNCTION_SPARSE_HESSIAN;
293  string functionRev2 = _name + "_" + FUNCTION_SPARSE_REVERSE_TWO;
294  string rev2Suffix = "indep";
295 
296  if (!_multiThreading || multiThreadingType == MultiThreadingType::NONE) {
297  _sources[functionName + ".c"] = generateSparseHessianRev2SingleThreadSource(functionName, hessInfo, maxCompressedSize, functionRev2, rev2Suffix);
298  } else {
299  _sources[functionName + ".c"] = generateSparseHessianRev2MultiThreadSource(functionName, hessInfo, maxCompressedSize, functionRev2, rev2Suffix, multiThreadingType);
300  }
301  _cache.str("");
302 }
303 
304 template<class Base>
305 std::string ModelCSourceGen<Base>::generateSparseHessianRev2SingleThreadSource(const std::string& functionName,
306  std::map<size_t, CompressedVectorInfo> hessInfo,
307  size_t maxCompressedSize,
308  const std::string& functionRev2,
309  const std::string& rev2Suffix) {
310  LanguageC<Base> langC(_baseTypeName);
311  std::string argsDcl = langC.generateDefaultFunctionArgumentsDcl();
312  std::vector<std::string> argsDcl2 = langC.generateDefaultFunctionArgumentsDcl2();
313 
314  _cache.str("");
315  _cache << "#include <stdlib.h>\n"
317  generateFunctionDeclarationSource(_cache, functionRev2, rev2Suffix, hessInfo, argsDcl);
318  _cache << "\n";
319  LanguageC<Base>::printFunctionDeclaration(_cache, "void", functionName, argsDcl2);
320  _cache << " {\n"
321  " " << _baseTypeName << " const * inLocal[3];\n"
322  " " << _baseTypeName << " inLocal1 = 1;\n"
323  " " << _baseTypeName << " * outLocal[1];\n";
324  if (maxCompressedSize > 0) {
325  _cache << " " << _baseTypeName << " compressed[" << maxCompressedSize << "];\n";
326  }
327  _cache << " " << _baseTypeName << " * hess = out[0];\n"
328  "\n"
329  " inLocal[0] = in[0];\n"
330  " inLocal[1] = &inLocal1;\n"
331  " inLocal[2] = in[1];\n";
332  if (maxCompressedSize > 0) {
333  _cache << " outLocal[0] = compressed;";
334  }
335 
336  langC.setArgumentIn("inLocal");
337  langC.setArgumentOut("outLocal");
338  std::string argsLocal = langC.generateDefaultFunctionArguments();
339  bool previousCompressed = true;
340  for (auto& it : hessInfo) {
341  size_t index = it.first;
342  const std::vector<size_t>& els = it.second.indexes;
343  const std::vector<std::set<size_t> >& location = it.second.locations;
344  CPPADCG_ASSERT_UNKNOWN(els.size() == location.size());
345  CPPADCG_ASSERT_UNKNOWN(els.size() > 0);
346 
347  _cache << "\n";
348  bool compressed = !it.second.ordered;
349  if (!compressed) {
350  _cache << " outLocal[0] = &hess[" << *location[0].begin() << "];\n";
351  } else if (!previousCompressed) {
352  _cache << " outLocal[0] = compressed;\n";
353  }
354  _cache << " " << functionRev2 << "_" << rev2Suffix << index << "(" << argsLocal << ");\n";
355  if (compressed) {
356  for (size_t e = 0; e < els.size(); e++) {
357  _cache << " ";
358  for (size_t itl : location[e]) {
359  _cache << "hess[" << itl << "] = ";
360  }
361  _cache << "compressed[" << e << "];\n";
362  }
363  }
364  previousCompressed = compressed;
365  }
366 
367  _cache << "\n"
368  "}\n";
369  return _cache.str();
370 }
371 
372 
373 template<class Base>
374 std::string ModelCSourceGen<Base>::generateSparseHessianRev2MultiThreadSource(const std::string& functionName,
375  std::map<size_t, CompressedVectorInfo> hessInfo,
376  size_t maxCompressedSize,
377  const std::string& functionRev2,
378  const std::string& rev2Suffix,
379  MultiThreadingType multiThreadingType) {
380  CPPADCG_ASSERT_UNKNOWN(_multiThreading);
381  CPPADCG_ASSERT_UNKNOWN(multiThreadingType != MultiThreadingType::NONE);
382 
383  LanguageC<Base> langC(_baseTypeName);
384  std::string argsDcl = langC.generateDefaultFunctionArgumentsDcl();
385  std::vector<std::string> argsDcl2 = langC.generateDefaultFunctionArgumentsDcl2();
386 
387  _cache.str("");
388  _cache << "#include <stdlib.h>\n"
390  generateFunctionDeclarationSource(_cache, functionRev2, rev2Suffix, hessInfo, argsDcl);
391 
392 
393  langC.setArgumentIn("inLocal");
394  langC.setArgumentOut("outLocal");
395  std::string argsLocal = langC.generateDefaultFunctionArguments();
396 
400  for (const auto& it : hessInfo) {
401  size_t index = it.first;
402  const std::vector<size_t>& els = it.second.indexes;
403  const std::vector<std::set<size_t> >& location = it.second.locations;
404  CPPADCG_ASSERT_UNKNOWN(els.size() == location.size());
405 
406  bool compressed = !it.second.ordered;
407  if (!compressed) {
408  continue;
409  }
410 
411  std::string functionNameWrap = functionRev2 + "_" + rev2Suffix + std::to_string(index) + "_wrap";
412  LanguageC<Base>::printFunctionDeclaration(_cache, "void", functionNameWrap, argsDcl2);
413  _cache << " {\n"
414  " " << _baseTypeName << " const * inLocal[3];\n"
415  " " << _baseTypeName << " inLocal1 = 1;\n"
416  " " << _baseTypeName << " * outLocal[1];\n"
417  " " << _baseTypeName << " compressed[" << it.second.indexes.size() << "];\n"
418  " " << _baseTypeName << " * hess = out[0];\n"
419  "\n"
420  " inLocal[0] = in[0];\n"
421  " inLocal[1] = &inLocal1;\n"
422  " inLocal[2] = in[1];\n"
423  " outLocal[0] = compressed;\n";
424  _cache << " " << functionRev2 << "_" << rev2Suffix << index << "(" << argsLocal << ");\n";
425  for (size_t e = 0; e < els.size(); e++) {
426  _cache << " ";
427  for (size_t itl : location[e]) {
428  _cache << "hess[" << itl << "] = ";
429  }
430  _cache << "compressed[" << e << "];\n";
431  }
432  _cache << "}\n";
433  }
434 
435  _cache << "\n"
436  "typedef void (*cppadcg_function_type) (" << argsDcl << ");\n";
437 
438 
439  if (multiThreadingType == MultiThreadingType::OPENMP) {
440  _cache << "\n";
441  printFileStartOpenMP(_cache);
442  _cache << "\n";
443 
444  } else {
448  assert(multiThreadingType == MultiThreadingType::PTHREADS);
449 
450  printFileStartPThreads(_cache, _baseTypeName);
451  }
452 
456  _cache << "\n"
457  "void " << functionName << "(" << argsDcl << ") {\n"
458  " static const cppadcg_function_type p[" << hessInfo.size() << "] = {";
459  for (const auto& it : hessInfo) {
460  size_t index = it.first;
461  if (index != hessInfo.begin()->first) _cache << ", ";
462  if (it.second.ordered) {
463  _cache << functionRev2 << "_" << rev2Suffix << index;
464  } else {
465  _cache << functionRev2 << "_" << rev2Suffix << index << "_wrap";
466  }
467  }
468  _cache << "};\n"
469  " static const long offset["<< hessInfo.size() <<"] = {";
470  for (const auto& it : hessInfo) {
471  if (it.first != hessInfo.begin()->first) _cache << ", ";
472  if (it.second.ordered) {
473  _cache << *it.second.locations[0].begin();
474  } else {
475  _cache << "0";
476  }
477  }
478  _cache << "};\n"
479  " " << _baseTypeName << " inLocal1 = 1;\n"
480  " " << _baseTypeName << " const * inLocal[3] = {in[0], &inLocal1, in[1]};\n"
481  " " << _baseTypeName << " * outLocal[1];\n";
482  _cache << " " << _baseTypeName << " * hess = out[0];\n"
483  " long i;\n"
484  "\n";
485 
486  if(multiThreadingType == MultiThreadingType::OPENMP) {
487  printFunctionStartOpenMP(_cache, hessInfo.size());
488  _cache << "\n";
489  printLoopStartOpenMP(_cache, hessInfo.size());
490  _cache << " outLocal[0] = &hess[offset[i]];\n"
491  " (*p[i])(" << argsLocal << ");\n";
492  printLoopEndOpenMP(_cache, hessInfo.size());
493  _cache << "\n";
494 
495  } else {
496  assert(multiThreadingType == MultiThreadingType::PTHREADS);
497 
498  printFunctionStartPThreads(_cache, hessInfo.size());
499  _cache << "\n"
500  " for(i = 0; i < " << hessInfo.size() << "; ++i) {\n"
501  " args[i] = (ExecArgStruct*) malloc(sizeof(ExecArgStruct));\n"
502  " args[i]->func = p[i];\n"
503  " args[i]->in = inLocal;\n"
504  " args[i]->out[0] = &hess[offset[i]];\n"
505  " args[i]->atomicFun = " << langC .getArgumentAtomic() << ";\n"
506  " }\n"
507  "\n";
508  printFunctionEndPThreads(_cache, hessInfo.size());
509  }
510 
511  _cache << "\n"
512  "}\n";
513  return _cache.str();
514 }
515 
516 template<class Base>
518  std::vector<size_t>& evalCols) {
524  evalRows.reserve(_hessSparsity.rows.size());
525  evalCols.reserve(_hessSparsity.cols.size());
526 
527  for (size_t e = 0; e < _hessSparsity.rows.size(); e++) {
528  size_t i = _hessSparsity.rows[e];
529  size_t j = _hessSparsity.cols[e];
530  if (_hessSparsity.sparsity[i].find(j) == _hessSparsity.sparsity[i].end() &&
531  _hessSparsity.sparsity[j].find(i) != _hessSparsity.sparsity[j].end()) {
532  // only the symmetric value is available
533  // (it can be caused by atomic functions which may only be providing a partial hessian)
534  evalRows.push_back(j);
535  evalCols.push_back(i);
536  } else {
537  evalRows.push_back(i);
538  evalCols.push_back(j);
539  }
540  }
541 }
542 
543 template<class Base>
545  if (_hessSparsity.sparsity.size() > 0) {
546  return;
547  }
548 
549  size_t m = _fun.Range();
550  size_t n = _fun.Domain();
551 
555  SparsitySetType r(n); // identity matrix
556  for (size_t j = 0; j < n; j++)
557  r[j].insert(j);
558  SparsitySetType jac = _fun.ForSparseJac(n, r);
559 
560  SparsitySetType s(1);
561  for (size_t i = 0; i < m; i++) {
562  s[0].insert(i);
563  }
564  _hessSparsity.sparsity = _fun.RevSparseHes(n, s, false);
565  //printSparsityPattern(_hessSparsity.sparsity, "hessian");
566 
567  if (_hessianByEquation || _reverseTwo) {
572  std::set<size_t> customVarsInHess;
573  if (_custom_hess.defined) {
574  customVarsInHess.insert(_custom_hess.row.begin(), _custom_hess.row.end());
575  customVarsInHess.insert(_custom_hess.col.begin(), _custom_hess.col.end());
576 
577  r = SparsitySetType(n); //clear r
578  for (size_t j : customVarsInHess) {
579  r[j].insert(j);
580  }
581  jac = _fun.ForSparseJac(n, r);
582  }
583 
587  const std::vector<Color> colors = colorByRow(customVarsInHess, jac);
588 
592  _hessSparsities.resize(m);
593  for (size_t i = 0; i < m; i++) {
594  _hessSparsities[i].sparsity.resize(n);
595  }
596 
597  for (size_t c = 0; c < colors.size(); c++) {
598  const Color& color = colors[c];
599 
600  // first-order
601  r = SparsitySetType(n); //clear r
602  for (size_t j : color.forbiddenRows) {
603  r[j].insert(j);
604  }
605  _fun.ForSparseJac(n, r);
606 
607  // second-order
608  s[0].clear();
609  const std::set<size_t>& equations = color.rows;
610  for (size_t i : equations) {
611  s[0].insert(i);
612  }
613 
614  SparsitySetType sparsityc = _fun.RevSparseHes(n, s, false);
615 
619  const std::map<size_t, size_t>& var2Eq = color.column2Row;
620  for (size_t j : color.forbiddenRows) { //used variables
621  if (sparsityc[j].size() > 0) {
622  size_t i = var2Eq.at(j);
623  _hessSparsities[i].sparsity[j].insert(sparsityc[j].begin(),
624  sparsityc[j].end());
625  }
626  }
627 
628  }
629 
630  for (size_t i = 0; i < m; i++) {
631  LocalSparsityInfo& hessSparsitiesi = _hessSparsities[i];
632 
633  if (!_custom_hess.defined) {
634  generateSparsityIndexes(hessSparsitiesi.sparsity,
635  hessSparsitiesi.rows, hessSparsitiesi.cols);
636 
637  } else {
638  size_t nnz = _custom_hess.row.size();
639  for (size_t e = 0; e < nnz; e++) {
640  size_t i1 = _custom_hess.row[e];
641  size_t i2 = _custom_hess.col[e];
642  if (hessSparsitiesi.sparsity[i1].find(i2) != hessSparsitiesi.sparsity[i1].end()) {
643  hessSparsitiesi.rows.push_back(i1);
644  hessSparsitiesi.cols.push_back(i2);
645  }
646  }
647  }
648  }
649 
650  }
651 
652  if (!_custom_hess.defined) {
653  generateSparsityIndexes(_hessSparsity.sparsity,
654  _hessSparsity.rows, _hessSparsity.cols);
655 
656  } else {
657  _hessSparsity.rows = _custom_hess.row;
658  _hessSparsity.cols = _custom_hess.col;
659  }
660 }
661 
662 template<class Base>
664  determineHessianSparsity();
665 
666  generateSparsity2DSource(_name + "_" + FUNCTION_HESSIAN_SPARSITY, _hessSparsity);
667  _sources[_name + "_" + FUNCTION_HESSIAN_SPARSITY + ".c"] = _cache.str();
668  _cache.str("");
669 
670  if (_hessianByEquation || _reverseTwo) {
671  generateSparsity2DSource2(_name + "_" + FUNCTION_HESSIAN_SPARSITY2, _hessSparsities);
672  _sources[_name + "_" + FUNCTION_HESSIAN_SPARSITY2 + ".c"] = _cache.str();
673  _cache.str("");
674  }
675 }
676 
677 } // END cg namespace
678 } // END CppAD namespace
679 
680 #endif
std::set< size_t > rows
all row with this color
STL namespace.
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
std::map< size_t, size_t > column2Row
maps column indexes to the corresponding row
virtual void generateSparseHessianSourceDirectly()
virtual std::string generateSparseHessianRev2MultiThreadSource(const std::string &functionName, std::map< size_t, CompressedVectorInfo > hessInfo, size_t maxCompressedSize, const std::string &functionRev2, const std::string &rev2Suffix, MultiThreadingType multiThreadingType)
virtual void generateSparseHessianSourceFromRev2(MultiThreadingType multiThreadingType)
void makeVariables(VectorCG &variables)
virtual void determineSecondOrderElements4Eval(std::vector< size_t > &userRows, std::vector< size_t > &userCols)
virtual void setMaxAssignmentsPerFunction(size_t maxAssignmentsPerFunction, std::map< std::string, std::string > *sources)
Definition: language_c.hpp:252
virtual void setParameterPrecision(size_t p)
Definition: language_c.hpp:237
virtual void generateSparseHessianSource(MultiThreadingType multiThreadingType)
std::set< size_t > forbiddenRows
used columns
virtual void generateCode(std::ostream &out, Language< Base > &lang, CppAD::vector< CGB > &dependent, VariableNameGenerator< Base > &nameGen, const std::string &jobName="source")