Bridges
DynOptInterface bridges are automatic reformulation rules that convert DOP formulations unsupported by a solver into equivalent ones that are supported. They follow the same design as MathOptInterface bridges, subtyping either MOI.Bridges.Objective.AbstractBridge or MOI.Bridges.Constraint.AbstractBridge.
Bridges are registered on a MOI.Bridges.LazyBridgeOptimizer and fire automatically: before each solve, MOI computes the shortest reformulation path through the registered bridges and applies only those needed for the attached solver. A bridge does nothing if the solver already supports the target formulation natively.
DynOptInterface.Bridges.add_all_bridges — Function
add_all_bridges(model, ::Type{T}) where {T}Add all DOP bridges defined in this module to model for coefficient type T.
Solvers that wrap their inner optimizer with MOI.Bridges.full_bridge_optimizer and implement MOI.get(::Optimizer, ::MOI.Bridges.ListOfNonstandardBridges{T}) to return these bridge types will have DOP reformulations applied automatically along the shortest path in the bridge graph.
Objective Bridges
Objective bridges reformulate the objective function into a form the solver can accept, while preserving equivalence of the optimal solution.
Lagrange to Mayer
The Lagrange-to-Mayer bridge converts a Bolza objective — a Mayer terminal cost plus a MultiPhaseIntegral running cost — into a pure Mayer objective.
For each phase integral $\int_{t_0}^{t_f} \ell(y,t)\,\mathrm{d}t$, the bridge introduces an augmented state variable $y_\ell$ governed by
\[\dot{y}_\ell(t) = \ell(y(t), t), \qquad y_\ell(t_0) = 0.\]
By the fundamental theorem of calculus, $y_\ell(t_f)$ equals the running integral, so the original objective is recovered as the terminal cost $\phi(y(t_f)) + y_\ell(t_f)$. The solver therefore receives a pure Mayer problem expressed entirely in terms of NonlinearBoundaryFunction.
DynOptInterface.Bridges.LagrangeToMayerBridge — Type
LagrangeToMayerBridge{T, NDF<:DOI.AbstractDynamicFunction}Bridges a Bolza objective with a MultiPhaseIntegral Lagrange term to a pure Mayer form by introducing one augmented dynamic variable y_ℓ per phase.
Source node
LagrangeToMayerBridge supports:
DOI.Bolza{BF, DOI.MultiPhaseIntegral{NDF}}-in-ObjectiveFunction
Target nodes
LagrangeToMayerBridge creates per phase:
- One
DOI.DynamicVariableIndexy_ℓon the same phase as the Lagrange integrand - One
DOI.ExplicitDifferentialFunction{NDF}-in-MOI.EqualTo{T}: ẏℓ = do - One
DOI.Initial{DOI.LinearDynamicFunction{T}}-in-MOI.EqualTo{T}: y_ℓ(t₀) = 0 DOI.NonlinearBoundaryFunction-in-ObjectiveFunction(Mayer-only)
Constraint Bridges
Constraint bridges reformulate individual constraints into equivalent forms that the solver supports.
Multi-Phase to Single-Phase
Multi-phase problems require continuity between phases: the final state of one phase must equal the initial state of the next. This is expressed compactly by a Linkage constraint, but some solvers only accept individual Initial and Final boundary constraints.
The multi-phase-to-single-phase bridge splits each Linkage constraint into two separate boundary constraints sharing a scalar slack variable $s$:
\[\mathrm{Final}(y_f) = s, \qquad \mathrm{Initial}(y_0) = s.\]
DynOptInterface.Bridges.MultiPhaseToSinglePhaseBridge — Type
MultiPhaseToSinglePhaseBridge{T, DF<:DOI.AbstractDynamicFunction}Bridges a Linkage{DF}-in-EqualTo{T} constraint, which encodes inter-phase continuity as Final(y_f) - Initial(y_0) = 0, into two separate boundary constraints sharing a scalar slack variable s:
Final(y_f) = s
Initial(y_0) = sThis allows solvers that support Initial/Final boundary constraints but not the compact Linkage representation to handle multi-phase continuity.
Source node
MultiPhaseToSinglePhaseBridge supports:
DOI.Linkage{DF}-in-MOI.EqualTo{T}
Target nodes
MultiPhaseToSinglePhaseBridge creates:
- One
MOI.VariableIndexinMOI.Reals(scalar slacks) DOI.NonlinearBoundaryFunction-in-MOI.EqualTo{T}: Final(y_f) - s = 0DOI.NonlinearBoundaryFunction-in-MOI.EqualTo{T}: Initial(y_0) - s = 0
Phase Normalization
When the final time $t_f$ is a free optimization variable (i.e., the Final{PhaseIndex} constraint is not an equality), the phase normalization bridge maps the problem onto a fixed normalized domain $\tau \in [0,1]$ via
\[\tau^{(i)} = \frac{t^{(i)} - t_0^{(i)}}{t_f^{(i)} - t_0^{(i)}}.\]
The bridge promotes $t_0$ and $t_f$ to MOI.VariableIndex entries and rescales every ExplicitDifferentialFunction constraint on the phase by $(t_f - t_0)$:
\[\dot{y}_j - d(y,\tau,x) = 0 \;\longrightarrow\; \dot{y}_j - (t_f - t_0)\,d(y,\tau,x) = 0.\]
This rescaling is applied lazily via MOI.Bridges.final_touch, which fires immediately before MOI.optimize!, ensuring all differential constraints added after bridge registration are captured.
DynOptInterface.Bridges.PhaseNormalizationBridge — Type
PhaseNormalizationBridge{T}Bridges a Final{PhaseIndex}-in-S constraint where S is any set other than EqualTo (i.e., the final phase boundary is a free optimization variable) to a normalized phase on [0, 1].
Concretely, t_0^(i) and t_f^(i) are promoted to MOI.VariableIndex entries in x, constrained to the bounds given by the original set S on the final time and by any existing Initial{PhaseIndex} constraint on the initial time. Then, via final_touch, every ExplicitDifferentialFunction constraint on the same phase is scaled by (t_f - t_0), implementing
τ^(i) := (t^(i) - t_0^(i)) / (t_f^(i) - t_0^(i)), τ^(i) ∈ [0, 1].Source node
PhaseNormalizationBridge supports:
DOI.Final{DOI.PhaseIndex}-in-SwhereS <: MOI.AbstractScalarSetandSis notMOI.EqualTo{T}(variable final boundary)
Target nodes
PhaseNormalizationBridge creates:
- Two
MOI.VariableIndexinMOI.Reals:t_0andt_f MOI.VariableIndex-in-S: bound constraint ont_ffrom the original set- Via
final_touch: wraps eachExplicitDifferentialFunctionconstraint on the phase with a(t_f - t_0)scaling factor, i.e. ẏj - d(ẏ, y, τ, x) = 0 → ẏj - (tf - t0)·d(ẏ, y, τ, x) = 0