TEST(CppADCGLatexTest, latex) { // use a special object for source code generation typedef CG<double> CGD; typedef AD<CGD> ADCG; // independent variable vector CppAD::vector<ADCG> x(2); x[0] = 2.; x[1] = 3.; Independent(x); // dependent variable vector CppAD::vector<ADCG> y(2); // the model ADCG a = x[0] / 1. + x[1] * x[1]; ADCG b = a / 2e-6; y[0] = b + 1 / (sign(b)*5 * a); y[1] = x[1]; ADFun<CGD> fun(x, y); // the model tape /** * start the special steps for source code generation * for a Jacobian */ CodeHandler<double> handler; CppAD::vector<CGD> indVars(2); handler.makeVariables(indVars); //CppAD::vector<CGD> jac = fun.SparseJacobian(indVars); CppAD::vector<CGD> vals = fun.Forward(0, indVars); LanguageLatex<double> langLatex; LangLatexDefaultVariableNameGenerator<double> nameGen; std::ofstream texfile; texfile.open("algorithm.tex"); handler.generateCode(texfile, langLatex, vals, nameGen); texfile.close(); std::string dir = system::getWorkingDirectory(); ASSERT_NO_THROW(system::callExecutable(PDFLATEX_COMPILER,{"-halt-on-error", "-shell-escape", system::createPath(dir, "latexTemplate.tex")})); }
TEST_F(CppADCGEvaluatorTest, Print) { CodeHandler<double> handler; std::vector<CG<double>> x(3); handler.makeVariables(x); std::vector<CG<double>> y(3); y[0] = makePrintValue("y[0]=", x[0] + x[1] + x[2], "\n"); y[1] = makePrintValue("x[0]=", x[0], "\n") * 2; y[2] = makePrintValue("y[2]=", y[1], "\n") * 2; CppAD::cg::Evaluator<double, double, CppAD::AD<double>> evaluator(handler); std::vector<CppAD::AD<double>> xNew(x.size()); CppAD::Independent(xNew); std::vector<CppAD::AD<double>> yNew(y.size()); std::cout << "Evaluating..."<<std::endl; evaluator.evaluate(xNew, yNew, y); std::cout << "Using tape..."<<std::endl; CppAD::ADFun<double> fun(xNew, yNew); std::vector<double> x2(x.size()); for(size_t i = 0; i< x2.size(); ++i) x2[i] = i + 1; std::vector<double> y2 = fun.Forward(0, x2); // validate results ASSERT_EQ(y2[0], x2[0] + x2[1] + x2[2]); ASSERT_EQ(y2[1], x2[0] * 2); ASSERT_EQ(y2[2], y2[1] * 2); }
std::vector<CG<Base> > prepareGraphForward0WithLoops(CodeHandler<Base>& handler, size_t m, /// range const std::vector<CG<Base>>& x, /// independent variables LoopFreeModel<Base>* funNoLoops, /// possibly null const std::set<LoopModel<Base>*>& loopTapes) { using namespace std; using namespace loops; using CGBase = CG<Base>; std::vector<CGBase> y(m); // temporaries std::vector<CGBase> tmps; /** * original equations outside the loops */ if (funNoLoops != nullptr) { const std::vector<size_t>& origEq = funNoLoops->getOrigDependentIndexes(); std::vector<CGBase> depNL = funNoLoops->getTape().Forward(0, x); // original equations for (size_t e = 0; e < origEq.size(); e++) { y[origEq[e]] = depNL[e]; } tmps.resize(depNL.size() - origEq.size()); for (size_t i = origEq.size(); i < depNL.size(); i++) tmps[i - origEq.size()] = depNL[i]; } /** * equations in loops */ OperationNode<Base>* iterationIndexDcl = handler.makeIndexDclrNode(LoopModel<Base>::ITERATION_INDEX_NAME); for (LoopModel<Base>* itl : loopTapes) { LoopModel<Base>& lModel = *itl; size_t nIterations = lModel.getIterationCount(); const std::vector<std::vector<LoopPosition> >& dependents = lModel.getDependentIndexes(); /** * make the loop start */ LoopStartOperationNode<Base>* loopStart = handler.makeLoopStartNode(*iterationIndexDcl, nIterations); IndexOperationNode<Base>* iterationIndexOp = handler.makeIndexNode(*loopStart); std::set<IndexOperationNode<Base>*> indexesOps; indexesOps.insert(iterationIndexOp); std::vector<IfElseInfo<Base> > ifElses; /** * evaluate the loop body */ std::vector<CGBase> indexedIndeps = createIndexedIndependents(handler, lModel, *iterationIndexOp); std::vector<CGBase> xl = createLoopIndependentVector(handler, lModel, indexedIndeps, x, tmps); if (xl.size() == 0) { xl.resize(1); // does not depend on any variable but CppAD requires at least one xl[0] = Base(0); } std::vector<CGBase> yl = lModel.getTape().Forward(0, xl); /** * make the loop end */ size_t assignOrAdd = 0; const std::vector<IndexPattern*>& depPatterns = lModel.getDependentIndexPatterns(); std::vector<std::pair<CGBase, IndexPattern*> > indexedLoopResults(yl.size()); for (size_t i = 0; i < yl.size(); i++) { std::map<size_t, size_t> locationsIter2Pos; for (size_t it = 0; it < nIterations; it++) { if (dependents[i][it].original < m) { locationsIter2Pos[it] = dependents[i][it].original; } } indexedLoopResults[i] = createLoopResult(handler, locationsIter2Pos, nIterations, yl[i], depPatterns[i], assignOrAdd, *iterationIndexOp, ifElses); } LoopEndOperationNode<Base>* loopEnd = createLoopEnd(handler, *loopStart, indexedLoopResults, indexesOps, assignOrAdd); for (size_t i = 0; i < dependents.size(); i++) { for (size_t it = 0; it < nIterations; it++) { // an additional alias variable is required so that each dependent variable can have its own ID size_t e = dependents[i][it].original; if (e < m) { // some equations are not present in all iteration y[e] = handler.createCG(*handler.makeNode(CGOpCode::DependentRefRhs,{e}, {*loopEnd})); } } } /** * move non-indexed expressions outside loop */ moveNonIndexedOutsideLoop(handler, *loopStart, *loopEnd); } return y; }