Skip to content
João Rui Leal edited this page Feb 8, 2020 · 25 revisions

Welcome to the CppADCodeGen wiki!

CppADCodeGen aims to extend the CppAD library in order to perform hybrid automatic differentiation, that is, to use operator overloading and produce source code.

Some of the key features of this library include:

  • source code generation for any CppAD method;
  • production of human-readable source code;
  • source code generation for multiple languages;
  • elimination of any unneeded operation/variable.

Currently, there is support for the C language, Latex, MathML, and Dot, however additional languages can be easily added in the future. A graph like representation of operations is generated independently from the source code generation methods which allows producing source code for different languages.

There are some additional classes that help generate and compile source code for Linux. Please see the Linux page for an example.

Sources for execution

C language

The C source generator aims at producing not only efficient source code but also a source code that leads to faster compilations. This is achieved by reducing the total number of temporary variables, including variable reuse, and having very short variable names.

A generic program used to generate C source code can be written as:

#include <iosfwd>
#include <vector>
#include <cppad/cg.hpp>

using namespace CppAD;
using namespace CppAD::cg;

int main() {
    // use a special object for source code generation
    typedef CG<double> CGD;
    typedef AD<CGD> ADCG;

    /***************************************************************************
     *                               the model
     **************************************************************************/

    // independent variable vector
    CppAD::vector<ADCG> x(2);
    x[0] = 2.;
    x[1] = 3.;
    Independent(x);

    // dependent variable vector 
    CppAD::vector<ADCG> y(1);

    // the model
    ADCG a = x[0] / 1. + x[1] * x[1];
    y[0] = a / 2;

    ADFun<CGD> fun(x, y); // the model tape

    /***************************************************************************
     *                        Generate the C source code
     **************************************************************************/

    /**
     * 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);

    LanguageC<double> langC("double");
    LangCDefaultVariableNameGenerator<double> nameGen;

    std::ostringstream code;
    handler.generateCode(code, langC, jac, nameGen);
    std::cout << code.str();
}

The output of this function is:

   y[1] = 0.5 * x[1] + 0.5 * x[1];
   // dependent variables without operations
   y[0] = 0.5;

Make sure to check out the Linux page which is also applicable to macOS.

Sources for documentation

CppADCodegen, in addition to the highly optimized C sources, is also capable of generating documentation oriented sources. These include:

  • LATEX sources, which can be used to compile PDF files,
  • HTML documents with presentation MathML markup and Javascript, and
  • Dot-files to generate a graph of operations.

HTML/MathML/Javascript

#include <iosfwd>
#include <cppad/cg.hpp>
#include <cppad/cg/lang/mathml/mathml.hpp>

using namespace CppAD;
using namespace CppAD::cg;

int main(void) {
    // use a special object for source code generation
    using CGD = CG<double>;
    using ADCG = AD<CGD>;

    // independent variable vector
    CppAD::vector<ADCG> x(2);
    x[0] = 2.;
    x[1] = 3.;
    Independent(x);

    // dependent variable vector 
    CppAD::vector<ADCG> y(8);

    /***************************************************************************
     *                               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];
    y[2] = CondExpLt(ADCG(1.0), x[0], x[1], b);
    y[3] = CondExpLe(x[0], ADCG(2.0), x[1], b);
    y[4] = CondExpEq(x[0], x[1], x[1], b);
    ADCG c = CondExpGe(ADCG(3.0), x[0], a, b);
    y[5] = CondExpGt(ADCG(4.0), x[0], ADCG(5.0), c);
    y[6] = 5 * pow(4, x[0]);
    y[7] = 3;

    ADFun<CGD> fun(x, y); // the model tape
    /***************************************************************************
     *                    Generate the HTML/MathML source code
     **************************************************************************/
    CodeHandler<double> handler;

    CppAD::vector<CGD> indVars(2);
    handler.makeVariables(indVars);

    CppAD::vector<CGD> vals = fun.Forward(0, indVars);

    LanguageMathML<double> langMathML;
    LangMathMLDefaultVariableNameGenerator<double> nameGen;

    langMathML.setSaveVariableRelations(true);

    // add some additional code to select variables
    langMathML.setStyle(langMathML.getStyle() + "\n.selectedProp{background-color: #ccc;}"
                                                "\n.faded{\n"
                                                "    opacity: 0.2;\n"
                                                "    filter: alpha(opacity=20); /* For IE8 and earlier */\n"
                                                "}\n"
                                                "\n.faded2{\n"
                                                "    opacity: 0.5;\n"
                                                "    filter: alpha(opacity=50); /* For IE8 and earlier */\n"
                                                "}");

    // use block display
    langMathML.setEquationMarkup("<math display=\"block\" class=\"equation\">", "</math>");

    // use MathJax (and align to the left)
    langMathML.setHeadExtraMarkup("<script type=\"text/x-mathjax-config\">\n"
                                  //"MathJax.Hub.Config({    MMLorHTML: { prefer: { Firefox: \"MML\" } }  });\n" // use this to define a prefered browser renderer
                                  "MathJax.Hub.Config({\n"
                                  "    jax: [\"input/TeX\",\"output/HTML-CSS\"],\n"
                                  "    displayAlign: \"left\"\n"
                                  "});\n"
                                  "</script>\n"
                                  "<script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML\"></script>");

    std::ifstream jsFile;
    jsFile.open("variableSelection.js");

    std::stringstream strStream;
    strStream << jsFile.rdbuf();

    langMathML.setJavascript(strStream.str());

    // create the HMTL file
    std::ofstream htmlFile;
    htmlFile.open("algorithm.html");

    handler.setReuseVariableIDs(false);
    handler.generateCode(htmlFile, langMathML, vals, nameGen);

    htmlFile.close();
}

This program creates an HTML file for the model that can be used to navigate and inspect your model. The javascript file variableSelection.js is available in the test folder.

Here is a screenshot of the result (the variable x0 was selected):

Clone this wiki locally