macro_rules! get_spartial_derivative {
($f:ident, $func_name:ident) => { ... };
}
Expand description
Get a function that returns the partial derivative of the provided multivariate, scalar-valued function.
The partial derivative is computed using forward-mode automatic differentiation.
§Arguments
f
- Multivariate, scalar-valued function, $f:\mathbb{R}^{n}\to\mathbb{R}$.func_name
- Name of the function that will return the partial derivative of $f(\mathbf{x})$ with respect to $x_{k}$ at any point $\mathbf{x}\in\mathbb{R}^{n}$.
§Warning
f
cannot be defined as closure. It must be defined as a function.
§Note
The function produced by this macro will perform 1 evaluation of $f(\mathbf{x})$ to evaluate its partial derivative with respect to $x_{k}$.
§Example
Compute the partial derivative of
$$f(x)=x^{3}\sin{y}$$
with respect to $y$ at $(x,y)=(5,1)$, and compare the result to the true result of
$$\frac{\partial f}{\partial y}\bigg\rvert_{(x,y)=(5,1)}=5^{3}\cos{(1)}$$
First, note that we can rewrite this function as
$$f(\mathbf{x})=x_{0}^{3}\sin{x_{1}}$$
where $\mathbf{x}=(x_{0},x_{1})^{T}$ (note that we use 0-based indexing to aid with the computational implementation). We are then trying to find
$$\frac{\partial f}{\partial x_{1}}\bigg\rvert_{\mathbf{x}=\mathbf{x}_{0}}$$
where $\mathbf{x}_{0}=(5,1)^{T}$.
§Using standard vectors
use linalg_traits::{Scalar, Vector};
use numdiff::{get_spartial_derivative, Dual, DualVector};
// Define the function, f(x).
fn f<S: Scalar, V: Vector<S>>(x: &V) -> S {
x.vget(0).powi(3) * x.vget(1).sin()
}
// Define the evaluation point.
let x0 = vec![5.0, 1.0];
// Define the element of the vector (using 0-based indexing) we are differentiating with respect
// to.
let k = 1;
// Autogenerate the function "dfk" that can be used to compute the partial derivative of f(x)
// with respect to xₖ at any point x.
get_spartial_derivative!(f, dfk);
// Verify that the partial derivative function obtained using get_spartial_derivative! computes
// the partial derivative correctly.
assert_eq!(dfk(&x0, k), 5.0_f64.powi(3) * 1.0_f64.cos());
§Using other vector types
The function produced by get_spartial_derivative!
can accept any type for x0
, as long as
it implements the linalg_traits::Vector
trait.
use faer::Mat;
use linalg_traits::{Scalar, Vector};
use nalgebra::{dvector, DVector, SVector};
use ndarray::{array, Array1};
use numdiff::{get_spartial_derivative, Dual, DualVector};
// Define the function, f(x).
fn f<S: Scalar, V: Vector<S>>(x: &V) -> S {
x.vget(0).powi(3) * x.vget(1).sin()
}
// Define the element of the vector (using 0-based indexing) we are differentiating with respect
// to.
let k = 1;
// Autogenerate the function "dfk" that can be used to compute the partial derivative of f(x)
// with respect to xₖ at any point x.
get_spartial_derivative!(f, dfk);
// nalgebra::DVector
let x0: DVector<f64> = dvector![5.0, 1.0];
let dfk_eval: f64 = dfk(&x0, k);
// nalgebra::SVector
let x0: SVector<f64, 2> = SVector::from_slice(&[5.0, 1.0]);
let dfk_eval: f64 = dfk(&x0, k);
// ndarray::Array1
let x0: Array1<f64> = array![5.0, 1.0];
let dfk_eval: f64 = dfk(&x0, k);
// faer::Mat
let x0: Mat<f64> = Mat::from_slice(&[5.0, 1.0]);
let dfk_eval: f64 = dfk(&x0, k);