LeninGrad is the people's auto-differentiation library, providing easy autodifferentiation for first and higher-order derivatives!
Essentially, LeninGrad provides drop-in types dfloat
and ddouble
which automatically allow for analytical differentiation.
Clone this repository and build
git clone https://github.com/abhaybd/LeninGrad.git
cd LeninGrad
mkdir build
cd build
cmake ..
sudo cmake --build . --target install --config Release -- -j $(nproc)
Add the following to your CMakeLists.txt
find_package(LeninGrad CONFIG REQUIRED)
target_link_libraries(<target> INTERFACE LeninGrad)
For example, if your code is:
double a = ..., b = ...;
double c = std::cos(a) * std::sin(b);
Getting the derivative of c
wrt a
and b
is as easy as changing the above to:
using leningrad::ddouble;
ddouble a = ..., b = ...;
ddouble c = leningrad::cos(a) * leningrad::sin(b);
auto dc = differentiate(c);
ddouble dcda = dc.wrt(a);
ddouble dcdb = dc.wrt(b);
You can also calculate higher order derivatives!
// d^2c/da^2
ddouble d2cda2 = differentiate(c, a, 2);
Cross derivatives are easy too:
// d^2c/dadb
ddouble d2cdadb = differentiate(c, {a, b});
Derivatives are themselves differentiable too:
ddouble dcda = differentiate(c).wrt(a);
ddouble foo = 2 * leningrad::exp(dcda);
ddouble bar = differentiate(foo).wrt(dcda);
Auto-Differentiation is available out of the box for floats as well, just use dfloat
.
If you want differentiation on custom types, you can use DiffValue<T>
with your custom type.