Skip to content

Commit

Permalink
build: upgrade autodiff version (#1136)
Browse files Browse the repository at this point in the history
This PR upgrades the bundled `autodiff` version to 0.6.4, and sets the minimum required version to 0.6 (which introduced breaking changes).

This should resolve issue #1135
  • Loading branch information
benjaminhuth committed Jan 18, 2022
1 parent 7a4814b commit ea8312b
Show file tree
Hide file tree
Showing 29 changed files with 3,469 additions and 956 deletions.
12 changes: 10 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR
# minimal dependency versions. they are defined here in a single place so
# they can be easily upgraded, although they might not be used if the
# dependency is included via `add_subdirectory(...)`.
set(_acts_autodiff_version 0.5.11)
set(_acts_autodiff_version 0.6)
set(_acts_boost_version 1.71.0)
set(_acts_dd4hep_version 1.11)
set(_acts_doxygen_version 1.8.15)
Expand Down Expand Up @@ -197,8 +197,16 @@ if(ACTS_BUILD_PLUGIN_AUTODIFF)
find_package(autodiff ${_acts_autodiff_version} CONFIG REQUIRED)
message(STATUS "Using system installation of autodiff")
else()
# This policy allows to set the options outside without changing autodiff's CMakeLists.txt
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(AUTODIFF_BUILD_TESTS OFF)
set(AUTODIFF_BUILD_PYTHON OFF)
set(AUTODIFF_BUILD_EXAMPLES OFF)
set(AUTODIFF_BUILD_DOCS OFF)
add_subdirectory(thirdparty/autodiff)
add_library(autodiff::autodiff ALIAS autodiff)
# Mark autodiff as system include directories so that no warnings trigger
get_target_property(_autodiff_includes autodiff INTERFACE_INCLUDE_DIRECTORIES)
set_target_properties(autodiff PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_autodiff_includes}")
message(STATUS "Using bundled autodiff")
endif()
endif()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
#include "Acts/Definitions/TrackParametrization.hpp"
#include "Acts/Utilities/Helpers.hpp"

#include <autodiff/forward.hpp>
#include <autodiff/forward/eigen.hpp>
#include <autodiff/forward/dual.hpp>
#include <autodiff/forward/dual/eigen.hpp>

namespace Acts {

Expand Down Expand Up @@ -124,8 +124,6 @@ struct AutodiffExtensionWrapper {
const auto& sd = state.stepping.stepData;

// Compute jacobian
using namespace autodiff::forward;

D = jacobian([&](const auto& in) { return RKN4step(in, sd, fstate, h); },
wrt(initial_params), at(initial_params))
.template cast<double>();
Expand Down
8 changes: 5 additions & 3 deletions thirdparty/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,17 @@ following folders removed:

## autodiff

A copy of [autodiff](https://github.com/autodiff/autodiff), v0.5.12 (however, the
A copy of [autodiff](https://github.com/autodiff/autodiff), v0.6.4 (however, the
version given in the `CMakeLists.txt` of autodiff has not been changed by the maintainers
and is still v0.5.11). In the `CMakeLists.txt` the commands `add_subdirectory(tests)` and
and is still v0.6.3). In the `CMakeLists.txt` the commands `add_subdirectory(tests)` and
`add_subdirectory(examples)` have been commented out. All folders/files have been
removed except the following ones:

- autodiff (contains the header files)
- cmake
- CMakeLists.txt
- LICENSE
- README.md

## boost

Expand All @@ -63,4 +65,4 @@ the minimum required version of [Eigen](https://eigen.tuxfamily.org)
the examples. The following files/directories are removed:
- docs
- tests
- .github
- .github
53 changes: 40 additions & 13 deletions thirdparty/autodiff/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,35 +1,62 @@
# The minimum required cmake version
cmake_minimum_required(VERSION 3.0)

# Set the cmake module path of the project
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# Add cmake modules of this project to the module path
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

# Use ccache to speed up repeated compilations
include(CCache)

# Name and details of the project
project(autodiff VERSION 0.5.11 LANGUAGES CXX)
project(autodiff VERSION 0.6.3 LANGUAGES CXX)

# Enable parallel build if MSVC is used
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)

# Include the cmake variables with values for installation directories
include(GNUInstallDirs)

# Ensure proper configuration if in a conda environment
include(CondaAware)

# Find Eigen3 if its include path is not given
if(NOT DEFINED EIGEN3_INCLUDE_DIR)
find_package(Eigen3 3.3 REQUIRED NO_MODULE)
endif()
# Define build options
option(AUTODIFF_BUILD_TESTS "Enable the compilation of the test files." ON)
option(AUTODIFF_BUILD_PYTHON "Enable the compilation of the python bindings." ON)
option(AUTODIFF_BUILD_EXAMPLES "Enable the compilation of the example files." ON)
option(AUTODIFF_BUILD_DOCS "Enable the build of the documentation and website." ON)

# Show message stating path to Eigen3
message(STATUS "Using Eigen3 library found at ${EIGEN3_INCLUDE_DIR}")
# Find eigen library
find_package(Eigen3 REQUIRED)

# autodiff requires a c++17 enabled compiler
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 17) # ensure cmake instructs compiler to use C++17
set(CMAKE_CXX_STANDARD_REQUIRED ON) # ensure the C++ standard given before is actually used
set(CMAKE_CXX_EXTENSIONS OFF) # avoid compile flags of the type -std=gnu++1z added by cmake

# Build the library (actually, just provide details about the library target, specify required compile options, etc. because autodiff is header-only)
add_subdirectory(autodiff)
# add_subdirectory(examples)
# add_subdirectory(test)

# Install the cmake config files that permit users to use find_package(Reaktoro)
# Build the tests
if(AUTODIFF_BUILD_TESTS)
add_subdirectory(tests)
endif()

# Build the python wrappers
if(AUTODIFF_BUILD_PYTHON)
set(PYBIND11_CPP_STANDARD -std=c++17) # Ensure pybind11 uses C++17 standard
find_package(pybind11 REQUIRED)
add_subdirectory(python)
endif()

# Build the examples
if(AUTODIFF_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()

# Build the docs
if(AUTODIFF_BUILD_DOCS)
add_subdirectory(docs)
endif()

# Install the cmake config files that permit users to use find_package(autodiff)
include(autodiffInstallCMakeConfigFiles)
21 changes: 21 additions & 0 deletions thirdparty/autodiff/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018–2021 Allan Leal

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
189 changes: 189 additions & 0 deletions thirdparty/autodiff/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<a href="https://autodiff.github.io" target="_blank">
<img src='art/autodiff-header.svg' width='100%'>
</a>

[![Gitter chat](https://badges.gitter.im/autodiff/gitter.png)](https://gitter.im/autodiff/community)
![Linux build status](https://github.com/autodiff/autodiff/workflows/linux/badge.svg?branch=master)
![macOS build status](https://github.com/autodiff/autodiff/workflows/osx/badge.svg?branch=master)
![Windows build status](https://github.com/autodiff/autodiff/workflows/windows/badge.svg?branch=master)

# Overview

**autodiff** is a C++17 library that uses modern and advanced programming
techniques to enable automatic computation of derivatives in an efficient, easy,
and intuitive way.

We welcome you to use **autodiff** and recommend us any improvements you think
it is necessary. You may want to do so by chatting with us on our [Gitter
Community Channel][gitter] and/or by making proposals by creating a [GitHub
issue][issues].

## Demonstration

Consider the following function *f(x, y, z)*:

```c++
double f(double x, double y, double z)
{
return (x + y + z) * exp(x * y * z);
}
```
which we use use to evaluate the variable *u = f(x, y, z)*:
```c++
double x = 1.0;
double y = 2.0;
double z = 3.0;
double u = f(x, y, z);
```

How can we minimally transform this code so that not only *u*, but also its
derivatives *∂u/∂x*, *∂u/∂y*, and *∂u/∂z*, can be computed?

The next two sections present how this can be achieved using two automatic
differentiation algorithms implemented in **autodiff**: **forward mode** and
**reverse mode**.

### Forward mode

In a *forward mode automatic differentiation* algorithm, both output variables
and one or more of their derivatives are computed together. For example, the
function evaluation *f(x, y, z)* can be transformed in a way that it will not
only produce the value of *u*, *the output variable*, but also one or more of
its derivatives *(∂u/∂x, ∂u/∂y, ∂u/∂z)* with respect to the *input
variables* *(x, y, z)*.

Enabling forward automatic differentiation for the calculation of derivatives
using **autodiff** is relatively simple. For our previous function *f*, we only
need to replace the floating-point type `double` with `autodiff::dual` for both
input and output variables:

```c++
dual f(const dual& x, const dual& y, const dual& z)
{
return (x + y + z) * exp(x * y * z);
}
```
We can now compute the derivatives *∂u/∂x*, *∂u/∂y*, and *∂u/∂z* as follows:
```c++
dual x = 1.0;
dual y = 2.0;
dual z = 3.0;
dual u = f(x, y, z);
double dudx = derivative(f, wrt(x), at(x, y, z));
double dudy = derivative(f, wrt(y), at(x, y, z));
double dudz = derivative(f, wrt(z), at(x, y, z));
```

The auxiliary function `autodiff::wrt`, an acronym for **with respect to**,
is used to indicate which input variable *(x, y, z)* is the selected one to
compute the partial derivative of *f*. The auxiliary function `autodiff::at`
is used to indicate where (at which values of its parameters) the derivative
of *f* is evaluated.

### Reverse mode

In a *reverse mode automatic differentiation* algorithm, the output variable of
a function is evaluated first. During this function evaluation, all
mathematical operations between the input variables are *"recorded"* in an
*expression tree*. By traversing this tree from top-level (output variable as
the root node) to bottom-level (input variables as the leaf nodes), it is
possible to compute the contribution of each branch on the derivatives of the
output variable with respect to input variables.

<img
src='art/expression-tree-diagram.svg'
style='max-width:100%;'
title='Expression tree diagram.'>

Thus, a single pass in a reverse mode calculation **computes all derivatives**,
in contrast with forward mode, which requires one pass for each input variable.
Note, however, that it is possible to change the behavior of a forward pass so
that many (perhaps even all) derivatives of an output variable are computed
simultaneously (e.g., in a single forward pass, *∂u/∂x*, *∂u/∂y*, and *∂u/∂z*
are evaluated together with *u*, in contrast with three forward passes, each
one computing the individual derivatives).

Similar as before, we can use **autodiff** to enable reverse automatic
differentiation for our function *f* by simply replacing type `double` with
`autodiff::var` as follows:

```c++
var f(var x, var y, var z)
{
return (x + y + z) * exp(x * y * z);
}
```
The code below demonstrates how the derivatives *∂u/∂x*, *∂u/∂y*, and *∂u/∂z*
can be calculated:
```c++
var x = 1.0;
var y = 2.0;
var z = 3.0;
var u = f(x, y, z);
Derivatives dud = derivatives(u);
double dudx = dud(x);
double dudy = dud(y);
double dudz = dud(z);
```

The function `autodiff::derivatives` will traverse the expression tree stored
in variable `u` and compute all its derivatives with respect to the input
variables *(x, y, z)*, which are then stored in the object `dud`. The
derivative of `u` with respect to input variable `x` (i.e., *∂u/∂x*) can then
be extracted from `dud` using `dud(x)`. The operations `dud(x)`, `dud(y)`,
`dud(z)` involve no computations! Just extraction of derivatives previously
computed with a call to function `autodiff::derivatives`.

## Development status

**autodiff** is planned to be a long-term maintained automatic differentiation
C++ project. This means that more algorithms and number types will still be
implemented and that the currently existing ones will be further enhanced.
Please have in mind, however, that **autodiff** is still in a relatively early
stage of development, which implies that minor breaking changes in API may be
introduced to simplify its use and make it more intuitive and consistent with
new library additions.

## Documentation

Check the documentation website for more details:

<a href="https://autodiff.github.io" target="_blank">
<img src='art/autodiff.github.io.svg' width='100%'>
</a>

# License

MIT License

Copyright (c) 2018–2021 Allan Leal

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

[gitter]: https://gitter.im/autodiff/community
[issues]: https://github.com/autodiff/autodiff/issues/new
13 changes: 8 additions & 5 deletions thirdparty/autodiff/autodiff/BUILD
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
cc_library(
name = "common",
hdrs = glob(["common/eigen.hpp", "common/meta.hpp"]),
hdrs = glob(["common/*.hpp"]),
deps = ["@com_github_eigen_eigen//:eigen"],
visibility = ["//visibility:public"],
)

cc_library(
name = "reverse",
hdrs = glob(["reverse.hpp", "reverse/*.hpp"]),
hdrs = glob(["reverse.hpp", "reverse/**/*.hpp"]),
deps = ["@com_github_eigen_eigen//:eigen",
":common"],
visibility = ["//visibility:public"],
)

cc_library(
name = "forward",
hdrs = glob(["forward.hpp", "forward/*.hpp"]),
deps = ["@com_github_eigen_eigen//:eigen"],
hdrs = glob(["forward.hpp", "forward/**/*.hpp"]),
deps = [
"@com_github_eigen_eigen//:eigen",
":common",
],
visibility = ["//visibility:public"],
)
)

0 comments on commit ea8312b

Please sign in to comment.