Skip to content

FATROP rejects scaled OCP defects because the next-state Jacobian is not identity #1091

Description

@mickaelbegon

Attribution

This issue and the linked technical audit were prepared by OpenAI Codex, at the request of @mickaelbegon. The proposed implementation is a Codex-generated prototype and should receive normal maintainer review before merging.

Problem

Bioptim currently dispatches FATROP constraints using scaled decision variables but physical dynamics. For a shooting defect,

$$x_{k+1} - \Phi(x_k, u_k) = 0,$$

with x = S x̄, the constraint received by FATROP is effectively

$$S x̄_{k+1} - \Phi(S x̄_k, u_k) = 0.$$

The Jacobian block with respect to the next scaled state is therefore S, not the identity. CasADi's FATROP structure detection explicitly checks that every entry of this block is exactly 1.0 and otherwise raises:

Structure mismatch: gap-closing constraints must be like this: x_{k+1}-F(xk,uk).

CasADi source: https://github.com/casadi/casadi/blob/3.7.2/casadi/interfaces/fatrop/fatrop_runtime.hpp

A separate prerequisite is that FATROP needs time-major decision-variable ordering ([x0, u0, x1, u1, ...]).

Proposed correction

Dispatch an equivalent, solver-specific form of each state gap:

$$x̄_{k+1} - S^{-1}\Phi(S x̄_k, u_k) = 0.$$

This preserves the feasible set while restoring the exact identity block required by FATROP.

The audit also found that sequential phase transitions were expressed with the opposite sign for FATROP's canonical gap form. They need both a sign change and normalization by the post-transition state scaling.

Prototype branch

A working implementation is available in @mickaelbegon's fork:

The branch currently includes:

  • a solver-interface transformation hook that is a no-op for other solvers;
  • S⁻¹ normalization of shooting state-continuity constraints for FATROP;
  • normalization of direct-collocation internal defects for QDDOT_EQUALS_FORWARD_DYNAMICS;
  • normalization of the duplicated first collocation state helper;
  • sign correction and normalization for sequential CONTINUOUS and IMPACT phase transitions;
  • an early error when FATROP is used with OrderingStrategy.VARIABLE_MAJOR;
  • an ordering_strategy argument in the variable-scaling example;
  • regression tests comparing IPOPT's physical defect Jacobian (S) with FATROP's normalized Jacobian (I).

The selected validation suite reports 18 passed, including scaled RK4, direct collocation, inverse-dynamics collocation, and a scaled two-phase problem.

For TAU_EQUALS_INVERSE_DYNAMICS, the prototype normalizes the shooting gap but deliberately leaves internal torque residuals in physical torque units. Dividing those rows by a state scaling would be dimensionally incorrect.

Constraint-tolerance implication

After normalization, FATROP's global constraint tolerance applies in scaled coordinates. A normalized tolerance τ corresponds to a component-wise physical state-gap tolerance

$$|r_i^{physical}| \le S_i τ.$$

For example, S_i = 85 and constr_viol_tol = 1e-4 permit a physical residual of 8.5e-3 for that component. Bioptim should document this explicitly and possibly provide a physical post-solve defect check. A single FATROP tolerance cannot independently preserve different physical tolerances for every constraint family.

Suggested next steps

  1. Review whether the generic solver transformation hook is the preferred architecture, or whether normalization should live in FATROP constraint dispatch only.
  2. Run the new tests in the Linux CI environment with the supported CasADi/FATROP build.
  3. Extend coverage to contact defects, fatigue states, nonuniform phase scalings, mapped states, and multithreaded collocation.
  4. Decide and document the tolerance policy in physical versus scaled coordinates; consider a post-solve physical-residual report.
  5. Define explicit behavior for cyclic/non-sequential/custom phase transitions, which do not fit FATROP's automatically detected stage chain.
  6. Benchmark representative scaled OCPs against the current unscaled FATROP path and IPOPT to quantify conditioning and performance changes.
  7. After maintainer review, turn the prototype branch into a focused pull request, potentially separating phase-transition support from the core scaling fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions