Corleone.jl

Corleone turns differential equation solves into differentiable shooting layers for dynamic optimization. It combines SciML solvers with Lux parameter and state containers. You choose parameter schedules, state resets, an objective, and constraints; the layer supplies trajectories and continuity residuals.

Installation

For the introductory example, install Corleone, a solver, and LuxCore:

using Pkg
Pkg.add(["Corleone", "OrdinaryDiffEqTsit5", "LuxCore"])

Optimization and plotting packages are optional. Each tutorial lists its imports. To use a local checkout, develop its path with Pkg.develop(path = "path/to/Corleone.jl").

A first shooting layer

Consider $\dot{x}=p(t)$ with $x(0)=0$. The parameter is a control: it is $0.25$ before time 1 and $0.75$ afterward. One switching time defines two interval values.

using Corleone, LuxCore, OrdinaryDiffEqTsit5, Random

problem = ODEProblem((x, p, t) -> [p[1]], [0.0], (0.0, 2.0), [0.25])
control = Tunable(1; default = [0.25, 0.75],
    lowerbound = 0.0, upperbound = 1.0) => [1.0]
layer = ShootingLayer(problem, Tsit5(), control; controls = [1])
ps, st = LuxCore.setup(MersenneTwister(42), layer)
trajectory, next_st = layer(nothing, ps, st)

(; times = trajectory.t, states = round.(trajectory[:u₁]; digits = 6),
    controls = trajectory[:p₁])
(times = [0.0, 1.0, 2.0], states = [0.0, 0.25, 1.0], controls = [0.25, 0.75])

ps contains tunable values; st contains schedules, caches, and fixed values. The layer returns (trajectory, next_st). The default numerical symbols are :u₁ for the first state and :p₁ for the first parameter. State samples use the saved solution grid; parameter histories use their own change grid.

An optimization model adds a scalar objective. Here it penalizes deviation from a terminal target of 1.5 and retains the supplied parameters and state:

model = CorleoneDynamicOptProblem(layer,
    traj -> (last(traj.u)[1] - 1.5)^2; ps, st)
round(optimization_objective(model); digits = 6)
0.25

For a complete optimization, follow the linear quadratic regulator tutorial. For a symbolic model, start with the ModelingToolkit Lotka–Volterra tutorial.

Find the right guide

GoalStart here
Understand single and multiple shootingShooting formulation
Query samples and interpret reset jumpsTrajectories
Set initial guessesInitialization
Supply bounds, objectives, and constraintsOptimization contracts
Define dynamics and costs symbolicallyModelingToolkit
Choose a tested gradient configurationAutomatic differentiation
Run independent shooting blocks concurrentlyParallel shooting
Prepare, solve, and time benchmark problemsOptimal Control Benchmarks
Look up constructors and fieldsAPI reference

This manual covers Corleone, CorleoneOED, and OptimalControlBenchmarks. The sublibrary sections share their sources with the standalone documentation.