This document describes the breaking changes when migrating from OptimalControl.jl v1.1.6 (last stable release) to v2.0.0.
!!! note "v2.0.4 Compatibility" v2.0.4 is fully backward compatible with v2.0.3. It contains documentation improvements (scalar/vector convention warning, :exa modeler incompatibility note) and build system changes (logger filter) with no breaking changes.
!!! note "v2.0.3 Compatibility" v2.0.3 is fully backward compatible with v2.0.2. It adds the functional API (macro-free) for defining optimal control problems programmatically and updates CTModels to v0.10, with no breaking changes to existing code.
!!! note "v2.0.2 Compatibility" v2.0.2 is fully backward compatible with v2.0.1. It contains a dependency update (UnoSolver v0.2 → v0.3) with no breaking changes.
!!! note "v2.0.1 Compatibility"
v2.0.1 is fully backward compatible with v2.0.0. It contains documentation improvements and an export change (build_initial_guess is now explicitly reexported) with no breaking changes.
Version 2.0.0 represents a major architectural redesign of OptimalControl.jl, introducing:
- Complete solve architecture redesign with descriptive and explicit modes
- GPU/CPU parameter system for heterogeneous computing
- Advanced option routing with introspection and disambiguation tools
- New solver integrations (Uno, MadNCL)
- Control-free problems support with augmented Hamiltonian approach
- CTFlows enhancements with
augment=trueand direct OCP flow creation - Modernized reexport system using
@reexport import
The following functions from v1.1.6 have been removed and replaced:
| v1.1.6 Function | v2.0.0 Replacement | Notes |
|---|---|---|
direct_transcription |
discretize |
New function from CTDirect.jl |
set_initial_guess |
@init macro |
Use the @init macro for initial guess construction |
build_OCP_solution |
ocp_solution |
New function from CTSolvers.jl |
Migration example:
# v1.1.6
docp = direct_transcription(ocp, grid_size=100)
set_initial_guess(docp, x_init, u_init)
sol = build_OCP_solution(docp, nlp_sol)
# v2.0.0
docp = discretize(ocp, Collocation(); grid_size=100)
init = @init ocp begin
x = x_init
u = u_init
end
sol = ocp_solution(docp, nlp_sol)Removed exports:
IncorrectMethodIncorrectOutputUnauthorizedCall
Added exports:
PreconditionError
These exceptions are still available via CTBase.IncorrectMethod, etc., but are no longer re-exported by OptimalControl.jl.
The following types are no longer exported (but still available via qualified access):
VectorField→ useOptimalControl.VectorFieldorCTFlows.VectorFieldHamiltonian→ useOptimalControl.HamiltonianorCTFlows.HamiltonianHamiltonianLift→ useOptimalControl.HamiltonianLiftorCTFlows.HamiltonianLiftHamiltonianVectorField→ useOptimalControl.HamiltonianVectorFieldorCTFlows.HamiltonianVectorField
Migration example:
# v1.1.6
X = VectorField(f)
# v2.0.0
X = OptimalControl.VectorField(f)
# or
using CTFlows: VectorField
X = VectorField(f)The solve function has been completely redesigned with two modes:
# Specify strategies using symbols
sol = solve(ocp, :collocation, :adnlp, :ipopt, :cpu)
# Partial specification (auto-completed)
sol = solve(ocp, :ipopt) # Uses first matching method
sol = solve(ocp, :gpu) # Uses first GPU method# Specify strategies using typed components
sol = solve(ocp;
discretizer=Collocation(),
modeler=ADNLP(),
solver=Ipopt()
)The methods() function now returns 4-tuples instead of 3-tuples:
# v1.1.6
methods() # Returns (discretizer, modeler, solver)
# v2.0.0
methods() # Returns (discretizer, modeler, solver, parameter)
# Example: (:collocation, :adnlp, :ipopt, :cpu)The 4th element is the parameter (:cpu or :gpu) for execution backend.
v2.0.0 introduces automatic option routing with new introspection tools:
describe(strategy)— Display available options for a strategyroute_to(strategy=value)— Disambiguate shared optionsbypass(option=value)— Pass undeclared options to strategies
Example:
# Inspect available options
describe(:ipopt)
describe(:collocation)
# Disambiguate shared options
sol = solve(ocp, :ipopt;
max_iter=100, # Shared option (auto-routed)
route_to(solver=:print_level=>0) # Explicitly route to solver
)
# Pass undeclared options
sol = solve(ocp, :ipopt;
bypass(solver=:custom_option=>42)
)v2.0.0 introduces the @init macro for constructing initial guesses:
# v2.0.0
init = @init ocp begin
u = 0.5
x = [1.0, 2.0]
end
sol = solve(ocp; initial_guess=init)
# or using alias
sol = solve(ocp; init=init)The old functional approach is no longer supported.
These features are new in v2.0.0 but don't break existing code:
Support for optimal control problems without control variables:
ocp = @def begin
tf ∈ R, variable
t ∈ [0, tf], time
x ∈ R², state
ẋ(t) == f(x(t)) # No control
∫(L(x(t))) → min
end- Uno: CPU-only nonlinear optimization solver
- MadNCL: GPU-capable solver
Total of 5 solvers: Ipopt, MadNLP, Uno, MadNCL, Knitro
Basic schemes:
:trapeze— Trapezoidal rule:midpoint— Midpoint rule:euler/:euler_explicit/:euler_forward— Explicit Euler:euler_implicit/:euler_backward— Implicit Euler
ADNLP-only schemes:
:gauss_legendre_2— 2-point Gauss-Legendre collocation:gauss_legendre_3— 3-point Gauss-Legendre collocation
Explicit GPU/CPU selection via parameter:
# CPU execution (default)
sol = solve(ocp, :collocation, :adnlp, :ipopt, :cpu)
# GPU execution (requires ExaModels + MadNLP/MadNCL)
using CUDA, MadNLPGPU
sol = solve(ocp, :collocation, :exa, :madnlp, :gpu)v2.0.0 introduces comprehensive support for control-free problems (optimal control without control variables) with enhanced CTFlows integration:
Augmented Hamiltonian approach:
# v1.1.6: Manual augmented Hamiltonian construction
function H_aug(t, x_, p_)
x, λ = x_
p, _ = p_
return H(t, x, p, λ)
end
f = Flow(Hamiltonian(H_aug))
# v2.0.0: Direct OCP flow creation
f = Flow(ocp)Automatic costate computation:
# v2.0.0: augment=true automatically computes p_λ(tf)
function shoot!(s, p0, λ)
_, px_tf, pλ_tf = f(t0, x0, p0, tf, λ; augment=true)
s[1] = px_tf # p(tf) = 0
s[2] = pλ_tf # p_λ(tf) = 0
endMathematical framework:
- Complete augmented system dynamics with proper transversality conditions
- Automatic handling of Lagrange costs:
$p_\lambda(t_f) = 0$ - Automatic handling of Mayer costs:
$p_\omega(t_f) = -2\omega$ - Initial conditions:
$p_\lambda(t_0) = 0$ by construction
v2.0.0 requires updated versions of CTX packages:
| Package | v1.1.6 | v2.0.0 |
|---|---|---|
| CTBase | 0.16-0.17 | 0.18 |
| CTModels | 0.6 | 0.9 |
| CTDirect | 0.x | 1.0 |
| CTSolvers | N/A | 0.4 |
| CTParser | 0.7-0.8 | 0.8 |
New dependency: CTSolvers.jl (handles NLP modeling and solving)
The main breaking changes are:
- Removed functions:
direct_transcription,set_initial_guess,build_OCP_solution - Changed exports: Some CTBase exceptions and CTFlows types no longer exported
- New solve architecture: Descriptive/explicit modes with 4-tuple methods
- Initial guess: Use
@initmacro instead of functional approach
For detailed usage examples, see the documentation.