• Stars
    star
    370
  • Rank 115,405 (Top 3 %)
  • Language
    Haskell
  • License
    BSD 3-Clause "New...
  • Created over 14 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Automatic Differentiation

ad

Hackage Build Status

A package that provides an intuitive API for Automatic Differentiation (AD) in Haskell. Automatic differentiation provides a means to calculate the derivatives of a function while evaluating it. Unlike numerical methods based on running the program with multiple inputs or symbolic approaches, automatic differentiation typically only decreases performance by a small multiplier.

AD employs the fact that any program y = F(x) that computes one or more value does so by composing multiple primitive operations. If the (partial) derivatives of each of those operations is known, then they can be composed to derive the answer for the derivative of the entire program at a point.

This library contains at its core a single implementation that describes how to compute the partial derivatives of a wide array of primitive operations. It then exposes an API that enables a user to safely combine them using standard higher-order functions, just as you would with any other Haskell numerical type.

There are several ways to compose these individual Jacobian matrices. We hide the choice used by the API behind an explicit "Mode" type-class and universal quantification. This prevents users from confusing infinitesimals. If you want to risk infinitesimal confusion in order to get greater flexibility in how you curry, flip and generally combine the differential operators, then the Rank1.* modules are probably your cup of tea.

Features

  • Provides forward- and reverse- mode AD combinators with a common API.
  • Optional type-level "branding" is available to prevent the end user from confusing infinitesimals
  • Each mode has a separate module full of combinators, with a consistent look and feel.

Examples

You can compute derivatives of functions

Prelude Numeric.AD> diff sin 0 {- cos 0 -}
1.0

Or both the answer and the derivative of a function:

Prelude Numeric.AD> diff' (exp . log) 2
(2.0,1.0)

You can compute the derivative of a function with a constant parameter using auto:

Prelude Numeric.AD> let t = 2.0 :: Double
Prelude Numeric.AD> diff (\ x -> auto t * sin x) 0
2.0

You can use a symbolic numeric type, like the one from simple-reflect to obtain symbolic derivatives:

Prelude Debug.SimpleReflect Numeric.AD> diff atanh x
recip (1 - x * x) * 1

You can compute gradients for functions that take non-scalar values in the form of a Traversable functor full of AD variables.

Prelude Numeric.AD Debug.SimpleReflect> grad (\[x,y,z] -> x * sin (x + log y)) [x,y,z]
[ 0 + (0 + sin (x + log y) * 1 + 1 * (0 + cos (x + log y) * (0 + x * 1)))
, 0 + (0 + recip y * (0 + 1 * (0 + cos (x + log y) * (0 + x * 1))))
, 0
]

which one can simplify to:

[ sin (x + log y) + cos (x + log y) * x, recip y * cos (x + log y) * x, 0 ]

If you need multiple derivatives you can calculate them with diffs:

Prelude Numeric.AD> take 10 $ diffs sin 1
[0.8414709848078965,0.5403023058681398,-0.8414709848078965,-0.5403023058681398,0.8414709848078965,0.5403023058681398,-0.8414709848078965,-0.5403023058681398,0.8414709848078965,0.5403023058681398]

or if your function takes multiple inputs, you can use grads, which returns an 'f-branching stream' of derivatives, that you can inspect lazily. Somewhat more intuitive answers can be obtained by converting the stream into the polymorphically recursive Jet data type. With that we can look at a single "layer" of the answer at a time:

The answer:

Prelude Numeric.AD> headJet $ jet $  grads (\[x,y] -> exp (x * y)) [1,2]
7.38905609893065

The gradient:

Prelude Numeric.AD> headJet $ tailJet $ jet $  grads (\[x,y] -> exp (x * y)) [1,2]
[14.7781121978613,7.38905609893065]

The hessian (n * n matrix of 2nd derivatives)

Prelude Numeric.AD> headJet $ tailJet $ tailJet $ jet $  grads (\[x,y] -> exp (x * y)) [1,2]
[[29.5562243957226,22.16716829679195],[22.16716829679195,7.38905609893065]]

Or even higher order tensors of derivatives as a jet.

Prelude Numeric.AD> headJet $ tailJet $ tailJet $ tailJet $ jet $  grads (\[x,y] -> exp (x * y)) [1,2]
[[[59.1124487914452,44.3343365935839],[44.3343365935839,14.7781121978613]],[[44.3343365935839,14.7781121978613],[14.7781121978613,7.38905609893065]]]

Note the redundant values caused by the various symmetries in the tensors. The ad library is careful to compute each distinct derivative only once, lazily and to share the resulting computation.

Overview

Modules

  • Numeric.AD computes using whichever mode or combination thereof is suitable to each individual combinator. This mode is the default, re-exported by Numeric.AD
  • Numeric.AD.Mode.Forward provides basic forward-mode AD. It is good for computing simple derivatives.
  • Numeric.AD.Mode.Sparse computes a sparse forward-mode AD tower. It is good for higher derivatives or large numbers of outputs.
  • Numeric.AD.Mode.Kahn computes with reverse-mode AD. It is good for computing a few outputs given many inputs.
  • Numeric.AD.Mode.Reverse computes with reverse-mode AD. It is good for computing a few outputs given many inputs, when not using sparks heavily.
  • Numeric.AD.Mode.Tower computes a dense forward-mode AD tower useful for higher derivatives of single input functions.
  • Numeric.AD.Newton provides a number of combinators for root finding using Newton's method with quadratic convergence.
  • Numeric.AD.Halley provides a number of combinators for root finding using Halley's method with cubic convergence.
  • Numeric.AD.Rank1.* provides combinators for AD that are strictly rank-1. This makes it easier to flip and contort them with higher order functions at the expense of type safety when it comes to infinitsimal confusion.

Combinators

While not every mode can provide all operations, the following basic operations are supported, modified as appropriate by the suffixes below:

  • grad computes the gradient (vector of partial derivatives at a given point) of a function.
  • jacobian computes the Jacobian matrix of a function at a point.
  • diff computes the derivative of a function at a point.
  • du computes a directional derivative of a function at a point.
  • hessian computes the Hessian matrix (matrix of second partial derivatives) of a function at a point.

Combinator Suffixes

The following suffixes alter the meanings of the functions above as follows:

  • ' also return the answer
  • With lets the user supply a function to blend the input with the output
  • F is a version of the base function lifted to return a Traversable (or Functor) result
  • s means the function returns all higher derivatives in a list or f-branching Stream
  • T means the result is transposed with respect to the traditional formulation (usually to avoid paying for transposing back)
  • 0 means that the resulting derivative list is padded with 0s at the end.
  • NoEq means that an infinite list of converging values is returned rather than truncating the list when they become constant

Contact Information

Contributions and bug reports are welcome!

Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.

-Edward Kmett

More Repositories

1

lens

Lenses, Folds, and Traversals - Join us on web.libera.chat #haskell-lens
Haskell
2,030
star
2

machines

Networks of composable stream transducers
Haskell
340
star
3

trifecta

Parser combinators with highlighting, slicing, layout, literate comments, Clang-style diagnostics and the kitchen sink
Haskell
297
star
4

guanxi

Relational programming in Haskell. Mostly developed on twitch.
Haskell
253
star
5

quine

haskell, opengl, toy project
Haskell
210
star
6

linear

Low-dimensional linear algebra primitives for Haskell.
Haskell
198
star
7

propagators

The Art of the Propagator. See also:
Haskell
167
star
8

coda

A language experiment -- irc.freenode.net ##coda
Haskell
163
star
9

free

free monads
Haskell
161
star
10

hask

Category theory for Haskell with a lens flavor (you need GHC 7.8.3, not 7.8.2 to build this!)
Haskell
161
star
11

discrimination

Fast linear time sorting and discrimination for a large class of data types
Haskell
134
star
12

bound

Combinators for manipulating locally-nameless generalized de Bruijn terms
Haskell
121
star
13

reflection

Reifies arbitrary Haskell terms into types that can be reflected back into terms
Haskell
102
star
14

algebra

constructive abstract algebra
Haskell
98
star
15

succinct

playground for working with succinct data structures
Haskell
94
star
16

gl

Complete raw OpenGL bindings for Haskell
Haskell
93
star
17

parsers

Generic parser combinators
Haskell
88
star
18

linear-logic

Haskell
82
star
19

comonad

Haskell 98 comonads
Haskell
78
star
20

tables

Deprecated because of
Haskell
78
star
21

semigroupoids

Haskell
75
star
22

kan-extensions

Kan extensions, Kan lifts, the Yoneda lemma, and (co)monads generated by a functor
Haskell
74
star
23

contravariant

Haskell 98 contravariant functors
Haskell
72
star
24

constraints

Tools for programming with ConstraintKinds in GHC
Haskell
71
star
25

profunctors

Haskell 98 Profunctors
Haskell
69
star
26

cadenza

every day i'm truffling
Kotlin
67
star
27

codex

UI experiments for coda
Haskell
65
star
28

approximate

Approximate discrete values and numbers
Haskell
64
star
29

structures

A playground for working on advanced data structures in Haskell
Haskell
63
star
30

ersatz

A monad for interfacing with external SAT solvers
Haskell
63
star
31

semigroups

Haskell 98 semigroups
Haskell
62
star
32

bifunctors

Haskell 98 bifunctors, bifoldables and bitraversables
Haskell
57
star
33

either

the EitherT monad transformer
Haskell
55
star
34

unpacked-containers

Unpacked containers using backpack
Haskell
52
star
35

exceptions

mtl friendly exceptions
Haskell
49
star
36

structs

Exploring how to make a strict imperative universe in the GHC runtime system.
Haskell
48
star
37

reducers

Semigroups, specialized containers and a general map/reduce framework
Haskell
46
star
38

adjunctions

Simple adjunctions
Haskell
44
star
39

auth

Haskell
41
star
40

distributive

Dual Traversable
Haskell
41
star
41

graphs

a monadic graph library
Haskell
39
star
42

zippers

Zippers based on lenses and traversals
Haskell
38
star
43

tagged

phantom types
Haskell
37
star
44

unboxed

experimenting with unlifted classes via backpack
Haskell
36
star
45

perhaps

A monad, perhaps.
Haskell
33
star
46

rounded

MPFR bindings for Haskell
Haskell
33
star
47

hyphenation

Knuth-Liang Hyphenation for Haskell based on TeX hyphenation files
Haskell
33
star
48

categories

categories from category-extras
Haskell
33
star
49

transients

Clojure-style transients for Haskell
Haskell
32
star
50

concurrent

Yet another concurrent playground
Haskell
32
star
51

abelian

Commutative Applicatives and Semigroups
Haskell
31
star
52

hkd

higher-kinded data
Haskell
30
star
53

speculation

Safe, programmable, speculative evaluation for Haskell
Haskell
29
star
54

rts

spmd-on-simd stuff
C++
28
star
55

placeholder

todo and unimplemented, robustly implemented
Haskell
28
star
56

promises

lazy promises
Haskell
27
star
57

intervals

Interval Arithmetic
Haskell
27
star
58

heaps

Asymptotically optimal Brodal/Okasaki heaps
Haskell
26
star
59

intern

Hash consing for arbitrary Haskell data types
Haskell
25
star
60

hyperloglog

A constant-memory approximation of set membership
Haskell
24
star
61

magpie

an exploration of subtyping-based category theory in scala
Scala
24
star
62

lca

Improves the known complexity of online lowest common ancestor search to O(log h) persistently, and without preprocessing
Haskell
24
star
63

sparse

sparse matrices in Morton order
Haskell
23
star
64

indexed

Indexed Functors for GHC 7.6
Haskell
22
star
65

streams

Haskell 2010 stream comonads
Haskell
22
star
66

keys

keyed functors
Haskell
22
star
67

bytes

Serialization primitives that work with both cereal and binary.
Haskell
22
star
68

pointed

pointed and copointed data
Haskell
21
star
69

scala-ad

Forward- and Reverse-Mode Automatic Differentiation for Scala
Scala
21
star
70

vr

nothing to see here
C++
20
star
71

name

nominal sets in haskell
Haskell
20
star
72

rope

Fingertrees of Bytestrings
Haskell
19
star
73

jitplusplus

a tracing jit for c++ based on tracing and compiling from x86-64 assembly to x86-64 assembly
C
19
star
74

void

Provides Data.Void, which is in base since ghc 7.8 or so
Haskell
19
star
75

scheme-monads

minimalist polymorphic scheme-(co)monads, written to avoid use of any advanced language features except hygienic macros
Scheme
18
star
76

fractions

lazy continued fractions
Haskell
18
star
77

parsnip

Haskell
18
star
78

folds

Folds and sequence algebras
Haskell
18
star
79

concurrent-supply

A fast globally unique variable supply with a pure API
Haskell
17
star
80

category-extras

category-theoretic goodness for Haskell
Haskell
17
star
81

thc

An experimental "Turbo" Haskell Runtime - Nothing really to see here yet
C++
17
star
82

lens-action

Control.Lens.Action
Haskell
17
star
83

bad

a playground for working with fully static tensors and automatic differentiation
C++
17
star
84

homotopy

Coq
17
star
85

rcu

experimenting with STM-backed read-copy-update in Haskell
Haskell
16
star
86

multicategories

Playing around with multicategories and operads
Haskell
16
star
87

gc

Poor Richard's Memory Manager
Haskell
15
star
88

scala-attoparsec

A port of Bryan O'Sullivan's attoparsec from Haskell to Scala
Scala
15
star
89

kanso

just a place to throw some coding experiements while i re-re-re-learn rust
Rust
15
star
90

hyperfunctions

playing with hyperfunctions
Haskell
15
star
91

succinct-binary

Succinct binary serialization
Haskell
15
star
92

half

half-precision floating-point
Haskell
14
star
93

time-series

Playing with time series
Haskell
14
star
94

codebruijn

experiments with pext/pdep and codebruijn syntax
Haskell
14
star
95

haskell

An unimaginatively named monorepo for misc. side-projects that are annoying to maintain separately.
Haskell
14
star
96

keep

playing with resumable computations
Haskell
13
star
97

compensated

Compensated floating-point arithmetic
Haskell
13
star
98

eq

Leibnizian type equality
Haskell
13
star
99

nbe-in-java-19

a throwaway implementation of normalization by evaluation
Java
13
star
100

bits

Bit twiddling and bitwise serialization primitives
Haskell
13
star