Accessors
A flow keeps what it was built from: its Hamiltonian, its vector field, the pseudo-Hamiltonian and the control law, and its integrator. This page shows how to read them back, and on which flows.
using OptimalControl
using OrdinaryDiffEqTsit5We take the flow of the energy-minimal double integrator, built from the problem and the control law
ocp = @def begin
t ∈ [0, 1], time
x = (q, v) ∈ R², state
u ∈ R, control
x(0) == [-1, 0]
x(1) == [0, 0]
ẋ(t) == [v(t), u(t)]
0.5∫(u(t)^2) → min
end
f = Flow(ocp, (x, p) -> p[2])
x, p = [-1, 0], [12, 6]The Hamiltonian
hamiltonian(f) returns the maximised Hamiltonian
H = hamiltonian(f)
H(x, p) # 12 × 0 + 6²/218.0The Hamiltonian vector field
hamiltonian_vector_field(f) returns
Hv = hamiltonian_vector_field(f)
Hv(x, p)([0.0, 6.0], [-0.0, -12.0])The pseudo-Hamiltonian and the control law
pseudo_hamiltonian(f) returns control_law(f) the law you passed:
Hp = pseudo_hamiltonian(f)
u = control_law(f)
Hp(x, p, u(x, p)), u(x, p)(18.0, 6)These functions take the short form of their arguments, as above, or the full form with the time and the variable: H(t, x, p, v), Hv(t, x, p, v), Hp(t, x, p, u, v), u(t, x, p, v), with v = Float64[] for a problem without a variable.
Gradients
get_hamiltonian_gradient(f) returns the gradient of get_variable_gradient(f) its gradient with respect to the variable. get_pseudo_hamiltonian_gradient and get_pseudo_variable_gradient do the same for (t, x, p, v) (CTFlows#438):
∇H = get_hamiltonian_gradient(f)
∇H(0.0, x, p, Float64[]) # (∇ₓH, ∇ₚH) = ((0, 12), (0, 6))([0.0, 12.0], [0.0, 6.0])Without a flow
hamiltonian_vector_field also applies to a Hamiltonian, without building a flow:
Hv2 = hamiltonian_vector_field(Hamiltonian((x, p) -> p[1] * x[2] + p[2]^2 / 2))
Hv2(x, p)([0.0, 6.0], [-0.0, -12.0])On which flow
What a flow can give back depends on what it was built from:
| Flow built from | hamiltonian | hamiltonian_vector_field | pseudo_hamiltonian, control_law | vector_field |
|---|---|---|---|---|
ocp, law with a law u(x, p), or PseudoHamiltonian(Hp), law | ✓ | ✓ | ✓ | ✓ |
Hamiltonian(H) | ✓ | ✓ | ✗ | ✓ |
HamiltonianVectorField(Hv) | ✗ | ✓ | ✗ | ✓ |
VectorField(f), ControlledVectorField(f), law, ocp, OpenLoop(…) | ✗ | ✗ | ✗ | ✓ |
On a flow of the state, vector_field returns the vector field that is integrated:
Fx = vector_field(Flow(VectorField(x -> -x)))
Fx(2.0)-2.0An accessor that does not apply raises an error. For a Hamiltonian flow, the error says what the flow holds and what to use instead:
julia> hamiltonian(Flow(HamiltonianVectorField((x, p) -> ([x[2], p[2]], [0, -p[1]]))))
IncorrectArgument → top-level scope, REPL[1]:2
│
│ no scalar Hamiltonian available for a HamiltonianVectorFieldSystem
│
│ Got a HamiltonianVectorFieldSystem (stores the vector field directly, no AD)
│ Expected a HamiltonianSystem or PseudoHamiltonianSystem (built from a scalar Hamiltonian with AD)
│
│ Context hamiltonian(sys::HamiltonianVectorFieldSystem)
│ Hint use hamiltonian_vector_field(flow) to retrieve X_H, or build the flow from a scalar Hamiltonian
└─On a flow of the state, it is a MethodError for now (CTFlows#438).
The system and the integrator
A flow is made of a system, the mathematical object it integrates, and an integrator. Both are reached with qualified names, since they are not exported:
CTFlows.Flows.integrator(f)SciML{CPU} (instance, id=:sciml)
├─ internalnorm = real_norm [default]
├─ alg = Tsit5 [default]
├─ reltol = 1.0e-8 [default]
├─ save_everystep = auto [default]
├─ abstol = 1.0e-8 [default]
├─ save_start = auto [default]
└─ dense = auto [default]
Tip: use describe(SciML{CPU}) to see all available options.The options of the integrator are those of Flows overview, given when the flow is built.
See also
From an OCP: the flow used on this page.
From Hamiltonians: every constructor in the table above.
Geometry overview: Lie derivatives and brackets of these Hamiltonians and vector fields.