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_bridgesFunction
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.

source

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.LagrangeToMayerBridgeType
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.DynamicVariableIndex y_ℓ 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)
source

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.MultiPhaseToSinglePhaseBridgeType
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) = s

This 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.VariableIndex in MOI.Reals (scalar slack s)
  • DOI.NonlinearBoundaryFunction-in-MOI.EqualTo{T}: Final(y_f) - s = 0
  • DOI.NonlinearBoundaryFunction-in-MOI.EqualTo{T}: Initial(y_0) - s = 0
source

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.PhaseNormalizationBridgeType
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-S where S <: MOI.AbstractScalarSet and S is not MOI.EqualTo{T} (variable final boundary)

Target nodes

PhaseNormalizationBridge creates:

  • Two MOI.VariableIndex in MOI.Reals: t_0 and t_f
  • MOI.VariableIndex-in-S: bound constraint on t_f from the original set
  • Via final_touch: wraps each ExplicitDifferentialFunction constraint 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
source