Skip to content

Lie derivative and Lie bracket ​

ad(X, g) differentiates along a vector field . It computes the Lie derivative of when returns a scalar, and the Lie bracket when returns a vector.

julia
using OptimalControl

Lie derivative ​

The Lie derivative of a function    along a vector field is the derivative of in the direction of :

For the harmonic oscillator,   , and its energy   ,    : the energy is constant along the trajectories.

julia
X(x) = [x[2], -x[1]]
f(x) = x[1]^2 + x[2]^2

Xf = ad(X, f)
Xf([1.0, 2.0])
0.0

Lie bracket ​

The Lie bracket of two vector fields and is the vector field

where is the Jacobian matrix of at . With  ,    and   , so       :

julia
Y(x) = [x[1]^2, x[2]^2]

Z = ad(X, Y)
Z([1.0, 2.0])
2-element Vector{Float64}:
  0.0
 -3.0

Typed operands and nested brackets ​

On VectorFields, ad returns a VectorField, which can be bracketed again. The bracket at   is  :

julia
XV = VectorField(x -> [x[2], -x[1]])
YV = VectorField(x -> [x[1]^2, x[2]^2])

ZV = ad(XV, YV)
ZV isa VectorField, ad(ZV, YV)([1.0, 2.0])
(true, [4.0, -2.0])

The macro @Lie writes the same bracket @Lie [[XV, YV], YV].

Time and variable ​

The derivatives are taken with respect to only. For a vector field and a function , pass is_autonomous=false. With     and    ,     , which is at  ,  :

julia
Xt(t, x) = [t + x[2], -x[1]]
ft(t, x) = t + x[1]^2 + x[2]^2

ad(Xt, ft; is_autonomous=false)(1.0, [1.0, 2.0])
2.0

For a vector field and a function , pass is_variable=true. With     and    ,  :

julia
Xv(x, v) = [x[2] + v, -x[1]]
fv(x, v) = x[1]^2 + x[2]^2 + v

ad(Xv, fv; is_variable=true)([1.0, 2.0], 1.0)
2.0

Typed operands carry these traits, and must agree:

julia
julia> Xa = VectorField(x -> [x[2], -x[1]]);

julia> Xb = VectorField((t, x) -> [t + x[2], -x[1]]; is_autonomous=false);

julia> ad(Xa, Xb)
PreconditionError → top-level scope, REPL[3]:2
│
│  ad: TD/VD mismatch between X and Y
│
│  Reason   X: CTBase.Traits.Autonomous/CTBase.Traits.Fixed ≠ Y: CTBase.Traits.NonAutonomous/CTBase.Traits.Fixed — both arguments must share the same TimeDependence and VariableDependence
│
│  Context  ad on AbstractVectorField
│  Hint     Ensure both vector fields have the same time and variable dependence traits
└─

Partial time derivative ​

For a function , ∂ₜ(f) computes the partial derivative with respect to time:

With   ,    at  :

julia
g(t, x) = t^2 + x[1] * x[2]
dg = ∂ₜ(g)
dg(3.0, [1.0, 2.0])
6.0

∂ₜ also applies to a VectorField or a Hamiltonian. Its result always depends on time, even when the input does not, and is then zero:

julia
dXV = ∂ₜ(XV)
dXV(1.0, [1.0, 2.0])
2-element Vector{Float64}:
 0.0
 0.0

Together with the Poisson bracket, ∂ₜ gives the time derivative of a function along an extremal (see Poisson bracket).

Errors ​

SituationException
a Hamiltonian given to adIncorrectArgument, pointing to Poisson
operands with different dependences on time or on the variablePreconditionError
an in-place VectorFieldNotImplemented
a HamiltonianVectorFieldNotImplemented
julia
julia> H = Hamiltonian((x, p) -> x[1] + p[1]);

julia> ad(H, x -> x)
IncorrectArgument → top-level scope, REPL[2]:2
│
│  ad is not defined for AbstractHamiltonian operands
│
│  Context  ad on AbstractHamiltonian
│  Hint     Use Poisson(H, G) for the Poisson bracket of Hamiltonians
└─
julia
julia> Xip = VectorField((dx, x) -> (dx .= [x[2], -x[1]]); is_inplace=true);

julia> ad(Xip, x -> x[1]^2)
NotImplemented → top-level scope, REPL[2]:2
│
│  ad is not implemented for InPlace vector fields
│
│  Method   Use an OutOfPlace VectorField
│
│  Context  ad on AbstractVectorField
│  Hint     Reconstruct the VectorField without in-place flag
└─

See also ​