1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUTOMATIC DIFFERENTIATION MODULE
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//! Reverse mode automatic differentation.
//! Currently only gradients can be computed.
//! Suggestions on how to extend the functionality to Hessian matrices are
//! definitely welcome.
//!
//! Additionally, only functions $f: \mathbb{R}^n \rightarrow \mathbb{R}$
//! (scalar output) are supported. However, you can manually apply the
//! differentiation to multiple functions that could represent a vector output.
//!
//! - [x] Reverse (Adjoint) Mode
//! - Implementation via Operator and Function Overloading.
//! - Useful when number of outputs is *smaller* than number of inputs.
//! - i.e for functions $f:\mathbb{R}^n \rightarrow \mathbb{R}^m$, where $m \ll n$
//! - [ ] Forward (Tangent) Mode
//! - Implementation via Dual Numbers.
//! - Useful when number of outputs is *larger* than number of inputs.
//! - i.e. for functions $f:\mathbb{R}^n \rightarrow \mathbb{R}^m$, where $m \gg n$
//!
//! ```
//! # use RustQuant_autodiff::*;
//!
//! // Create a new Graph to store the computations.
//! let g = Graph::new();
//!
//! // Assign variables.
//! let x = g.var(69.);
//! let y = g.var(420.);
//!
//! // Define a function.
//! let f = {
//! let a = x.powi(2);
//! let b = y.powi(2);
//!
//! a + b + (x * y).exp()
//! };
//!
//! // Accumulate the gradient.
//! let gradient = f.accumulate();
//!
//! println!("Function = {}", f);
//! println!("Gradient = {:?}", gradient.wrt([x, y]));
//! ```
//!
//! You can also generate Graphviz (dot) code to visualize the computation graphs:
//!
//! ```ignore
//! println!("{}", graphviz(&graph, &variables));
//! ```
//!
//! The computation graph from computing Black-Scholes Greeks is shown at the
//! following link:
//!
//! [Black-Scholes Greeks tape.](https://github.com/avhz/RustQuant/blob/main/images/black_scholes_tape.png)
//!
//! It is clearly a work in progress, but gives a general idea of how the
//! computation graph is structured.
//!
//! If you want to improve the visualization, please feel free to submit a PR!
/// [`Accumulate`] trait.
pub use *;
/// Implements the gradient computation.
pub use *;
/// The Graph (aka. tape or Wengert List).
pub use *;
/// Visualisation of the [`Graph`].
pub use *;
/// Implements [`Vertex`] (nodes) for the `Graph`.
pub use *;
/// Operator/function overloading.
/// This module contains the overloaded operators and primitive functions.
/// In Griewank and Walther - Evaluating Derivatives, they refer to this
/// as the "elemental library".
/// Operations such as `+` and `*` are redefined, along with primitive
/// functions such as `sin`, `exp`, and `log`.
/// Each overload has an associated test to ensure functionality.
pub use *;
/// `Variable`s for `autodiff`.
pub use *;