Repository navigation
Replies: 6 comments 1 reply
|
Documentation page, once the choices are made: #1015. Tracking issues: control-toolbox/CTFlows.jl#472, control-toolbox/CTDirect.jl#639. |
|
As a remark, on the direct side, the min/max question is deferred to the NLP modeler, so we get multipliers according to their implementation. This of course still allows us to perform post treatment. Do we know what convention other optimisation tools use ? |
|
Where the sign of the duals will be implemented: control-toolbox/CTSolvers.jl#288 (solver-independent convention for the multipliers; evidence in control-toolbox/CTSolvers.jl#287). The scaling by the node weights stays in control-toolbox/CTDirect.jl#639. |
Multiplier signs of the NLP solvers:
|
| Package | Version |
|---|---|
CTSolvers |
0.6.2 |
NLPModels |
0.21.12 |
ADNLPModels |
0.8.15 |
ExaModels |
0.12.1 |
NLPModelsIpopt |
0.11.3 |
MadNLP |
0.10.2 |
MadNCL |
0.2.3 |
UnoSolver |
0.3.9 |
Ipopt_jll |
300.1400.1902+0 |
Uno_jll |
2.9.2+0 |
Problem
F = f (min) or F = -f (max), f(x) = (x₁ - 3)² + (x₂ - 1)² - x₃ + x₄ + 2x₅
c(x) = x₁ + x₂ - 3 = 0
g(x) = x₁² + x₂² - 6 ≤ 0 written g ≤ 0 or -g ≥ 0 (active)
x₃ ≤ 1 written as a bound, or as the row -x₃ ≥ -1 (active)
x₄ ≥ 0 a bound (active)
x₅ = 1/2 a fixed variable (lvar = uvar)
x* = ((3 + √3)/2, (3 - √3)/2, 1, 0, 1/2)
Eight ways of writing it (max -f is the same problem as min f):
| # | Case |
|---|---|
| 1 | min f · g ≤ 0 · x₃ ≤ a |
| 2 | min f · -g ≥ 0 · x₃ ≤ a |
| 3 | max -f · g ≤ 0 · x₃ ≤ a |
| 4 | max -f · -g ≥ 0 · x₃ ≤ a |
| 5 | min f · g ≤ 0 · -x₃ ≥ -a |
| 6 | min f · -g ≥ 0 · -x₃ ≥ -a |
| 7 | max -f · g ≤ 0 · -x₃ ≥ -a |
| 8 | max -f · -g ≥ 0 · -x₃ ≥ -a |
Notation and conventions
F is the objective as written in the model (F = -f for max -f), and the solvers maximise it by minimising -F. y gathers the multipliers of the rows lcon ≤ c(x) ≤ ucon, i.e. of the equality c, of the inequality g and, in the row form, of -x₃ ≥ -a: one signed value per row, y = μU − μL, where μL, μU are the multipliers of the lower and upper side of the row, at most one being nonzero. So Jᵀy = Jᵀ(μU − μL), J being the Jacobian of the rows, and an equality has a single signed y. zL and zU are the same thing for the bounds of the variables lvar ≤ x ≤ uvar, stored in two vectors; x₅, fixed, has a single net multiplier.
A convention is the choice of three things:
- the stationarity of the Lagrangian at the solution, for
Fas written, i.e. the signs of the multipliers in∇F + Jᵀy ± zL + zU = 0; - the dual feasibility, i.e. which multipliers are nonnegative for a minimisation (
μL,μU,zU, andzLor-zLaccording to its sign in the stationarity); - the rule for a maximisation: the solver reports either the multipliers of
Fas written (as written: every multiplier changes sign with the sense, and so does dual feasibility), or those of the equivalent minimisationmin(-F)(min-equiv.: nothing changes sign). For a minimisation the two rules coincide.
That gives four conventions:
| Convention | Stationarity and dual feasibility (minimisation) | Maximisation |
|---|---|---|
| A, as written | ∇F + Jᵀy − zL + zU = 0, with μL, μU, zL, zU ≥ 0 for a minimisation |
multipliers of F as written: all flip |
| A, min-equiv. | ∇F + Jᵀy − zL + zU = 0, with μL, μU, zL, zU ≥ 0 for a minimisation |
multipliers of min(-F): none flips |
| B, as written | ∇F + Jᵀy + zL + zU = 0, with μL, μU, zU ≥ 0 and zL ≤ 0 for a minimisation |
multipliers of F as written: all flip |
| B, min-equiv. | ∇F + Jᵀy + zL + zU = 0, with μL, μU, zU ≥ 0 and zL ≤ 0 for a minimisation |
multipliers of min(-F): none flips |
With the active set above the multipliers are unique, so each convention gives one expected value per multiplier, computed from the gradient and Jacobian of the model at x*. A solver follows a convention if all its multipliers match.
Expected values
Convention A, as written
| # | y_c (equality) | y_g (inequality) | x₃ | zL(x₄) | net(x₅) |
|---|---|---|---|---|---|
| 1 | +0.5359 | +0.1547 | zU(x₃) = +1.0000 | +1.0000 | -2.0000 |
| 2 | +0.5359 | -0.1547 | zU(x₃) = +1.0000 | +1.0000 | -2.0000 |
| 3 | -0.5359 | -0.1547 | zU(x₃) = -1.0000 | -1.0000 | +2.0000 |
| 4 | -0.5359 | +0.1547 | zU(x₃) = -1.0000 | -1.0000 | +2.0000 |
| 5 | +0.5359 | +0.1547 | y₃ = -1.0000 | +1.0000 | -2.0000 |
| 6 | +0.5359 | -0.1547 | y₃ = -1.0000 | +1.0000 | -2.0000 |
| 7 | -0.5359 | -0.1547 | y₃ = +1.0000 | -1.0000 | +2.0000 |
| 8 | -0.5359 | +0.1547 | y₃ = +1.0000 | -1.0000 | +2.0000 |
Convention A, min-equiv.
| # | y_c (equality) | y_g (inequality) | x₃ | zL(x₄) | net(x₅) |
|---|---|---|---|---|---|
| 1 | +0.5359 | +0.1547 | zU(x₃) = +1.0000 | +1.0000 | -2.0000 |
| 2 | +0.5359 | -0.1547 | zU(x₃) = +1.0000 | +1.0000 | -2.0000 |
| 3 | +0.5359 | +0.1547 | zU(x₃) = +1.0000 | +1.0000 | -2.0000 |
| 4 | +0.5359 | -0.1547 | zU(x₃) = +1.0000 | +1.0000 | -2.0000 |
| 5 | +0.5359 | +0.1547 | y₃ = -1.0000 | +1.0000 | -2.0000 |
| 6 | +0.5359 | -0.1547 | y₃ = -1.0000 | +1.0000 | -2.0000 |
| 7 | +0.5359 | +0.1547 | y₃ = -1.0000 | +1.0000 | -2.0000 |
| 8 | +0.5359 | -0.1547 | y₃ = -1.0000 | +1.0000 | -2.0000 |
Convention B, as written
| # | y_c (equality) | y_g (inequality) | x₃ | zL(x₄) | net(x₅) |
|---|---|---|---|---|---|
| 1 | +0.5359 | +0.1547 | zU(x₃) = +1.0000 | -1.0000 | -2.0000 |
| 2 | +0.5359 | -0.1547 | zU(x₃) = +1.0000 | -1.0000 | -2.0000 |
| 3 | -0.5359 | -0.1547 | zU(x₃) = -1.0000 | +1.0000 | +2.0000 |
| 4 | -0.5359 | +0.1547 | zU(x₃) = -1.0000 | +1.0000 | +2.0000 |
| 5 | +0.5359 | +0.1547 | y₃ = -1.0000 | -1.0000 | -2.0000 |
| 6 | +0.5359 | -0.1547 | y₃ = -1.0000 | -1.0000 | -2.0000 |
| 7 | -0.5359 | -0.1547 | y₃ = +1.0000 | +1.0000 | +2.0000 |
| 8 | -0.5359 | +0.1547 | y₃ = +1.0000 | +1.0000 | +2.0000 |
Convention B, min-equiv.
| # | y_c (equality) | y_g (inequality) | x₃ | zL(x₄) | net(x₅) |
|---|---|---|---|---|---|
| 1 | +0.5359 | +0.1547 | zU(x₃) = +1.0000 | -1.0000 | -2.0000 |
| 2 | +0.5359 | -0.1547 | zU(x₃) = +1.0000 | -1.0000 | -2.0000 |
| 3 | +0.5359 | +0.1547 | zU(x₃) = +1.0000 | -1.0000 | -2.0000 |
| 4 | +0.5359 | -0.1547 | zU(x₃) = +1.0000 | -1.0000 | -2.0000 |
| 5 | +0.5359 | +0.1547 | y₃ = -1.0000 | -1.0000 | -2.0000 |
| 6 | +0.5359 | -0.1547 | y₃ = -1.0000 | -1.0000 | -2.0000 |
| 7 | +0.5359 | +0.1547 | y₃ = -1.0000 | -1.0000 | -2.0000 |
| 8 | +0.5359 | -0.1547 | y₃ = -1.0000 | -1.0000 | -2.0000 |
The expected values satisfy the dual feasibility of their convention in every case: true.
What each solver returns
A cell is the convention the solver follows when all its multipliers match it: A or B for a minimisation (the two rules for a maximisation coincide there), and A, as written / A, min-equiv. (or B) for a maximisation. If they match none of the considered conventions, the cell is none, and the multipliers that disagree are listed below. ⚠ status marks a solve that did not converge.
ADNLPModels
| Solver | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| Ipopt | A | A | A, as written | A, as written | A | A | A, as written | A, as written |
| MadNLP | A | A | none | none | A | A | none | none |
| Uno | B | B | B, as written | B, as written | B | B | B, as written | B, as written |
| CTSolvers.Ipopt | A | A | A, as written | A, as written | A | A | A, as written | A, as written |
| CTSolvers.MadNLP | A | A | none | none | A | A | none | none |
| CTSolvers.MadNCL | A | A | none | none | A | A | none | none |
| CTSolvers.Uno | B | B | B, as written | B, as written | B | B | B, as written | B, as written |
ExaModels
| Solver | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| Ipopt | A | A | A, as written | A, as written | A | A | A, as written | A, as written |
| MadNLP | A | A | none | none | A | A | none | none |
| Uno | B | B | B, as written | B, as written | B | B | B, as written | B, as written |
| CTSolvers.Ipopt | A | A | A, as written | A, as written | A | A | A, as written | A, as written |
| CTSolvers.MadNLP | A | A | none | none | A | A | none | none |
| CTSolvers.MadNCL | A | A | none | none | A | A | none | none |
| CTSolvers.Uno | B | B | B, as written | B, as written | B | B | B, as written | B, as written |
Does the multiplier change sign from min f to max -f?
Independent of any convention: the same problem is written as min f and as max -f (cases 1/3, 2/4, 5/7, 6/8), and each multiplier of the second is compared with the one of the first. A solver that reports the multipliers of the objective as written should show flips everywhere (the objective is -f, so every multiplier changes sign). same means the multiplier is reported for the equivalent minimisation. Read it together with the verdicts above: a solver whose bound multipliers do not flip can look like the other convention on some cases.
| Solver | rows y |
upper bound zU(x₃) |
lower bound zL(x₄) |
fixed variable, net(x₅) |
|---|---|---|---|---|
| Ipopt | flips | flips | flips | flips |
| MadNLP | flips | same | same | same |
| Uno | flips | flips | flips | flips |
| CTSolvers.Ipopt | flips | flips | flips | flips |
| CTSolvers.MadNLP | flips | same | same | same |
| CTSolvers.MadNCL | flips | same | same | same |
| CTSolvers.Uno | flips | flips | flips | flips |
Same on both modelers, and CTSolvers vs the raw solver
- ADNLPModels and ExaModels give the same verdicts: true.
CTSolvers.Ipoptreturns the same multipliers as the rawIpopt: true.CTSolvers.MadNLPreturns the same multipliers as the rawMadNLP: true.CTSolvers.Unoreturns the same multipliers as the rawUno: true.
Multipliers that disagree with the conventions
For the cases where a solver follows none of the conventions (ADNLPModels; ExaModels is identical), its multipliers next to the expected ones for its own stationarity convention (the one it follows on every minimisation), under both rules for a maximisation. The solver's value is in bold when it matches neither rule.
MadNLP (stationarity A)
| # | multiplier | solver | A, as written | A, min-equiv. |
|---|---|---|---|---|
| 3 | y_c | -0.5359 | -0.5359 | +0.5359 |
| 3 | y_g | -0.1547 | -0.1547 | +0.1547 |
| 3 | z_x3 | +1.0000 | -1.0000 | +1.0000 |
| 3 | z_x4 | +1.0000 | -1.0000 | +1.0000 |
| 3 | z_x5 | -2.0000 | +2.0000 | -2.0000 |
| 4 | y_c | -0.5359 | -0.5359 | +0.5359 |
| 4 | y_g | +0.1547 | +0.1547 | -0.1547 |
| 4 | z_x3 | +1.0000 | -1.0000 | +1.0000 |
| 4 | z_x4 | +1.0000 | -1.0000 | +1.0000 |
| 4 | z_x5 | -2.0000 | +2.0000 | -2.0000 |
| 7 | y_c | -0.5359 | -0.5359 | +0.5359 |
| 7 | y_g | -0.1547 | -0.1547 | +0.1547 |
| 7 | y_x3 | +1.0000 | +1.0000 | -1.0000 |
| 7 | z_x4 | +1.0000 | -1.0000 | +1.0000 |
| 7 | z_x5 | -2.0000 | +2.0000 | -2.0000 |
| 8 | y_c | -0.5359 | -0.5359 | +0.5359 |
| 8 | y_g | +0.1547 | +0.1547 | -0.1547 |
| 8 | y_x3 | +1.0000 | +1.0000 | -1.0000 |
| 8 | z_x4 | +1.0000 | -1.0000 | +1.0000 |
| 8 | z_x5 | -2.0000 | +2.0000 | -2.0000 |
CTSolvers.MadNCL (stationarity A)
| # | multiplier | solver | A, as written | A, min-equiv. |
|---|---|---|---|---|
| 3 | y_c | -0.5359 | -0.5359 | +0.5359 |
| 3 | y_g | -0.1547 | -0.1547 | +0.1547 |
| 3 | z_x3 | +1.0000 | -1.0000 | +1.0000 |
| 3 | z_x4 | +1.0000 | -1.0000 | +1.0000 |
| 3 | z_x5 | -2.0000 | +2.0000 | -2.0000 |
| 4 | y_c | -0.5359 | -0.5359 | +0.5359 |
| 4 | y_g | +0.1547 | +0.1547 | -0.1547 |
| 4 | z_x3 | +1.0000 | -1.0000 | +1.0000 |
| 4 | z_x4 | +1.0000 | -1.0000 | +1.0000 |
| 4 | z_x5 | -2.0000 | +2.0000 | -2.0000 |
| 7 | y_c | -0.5359 | -0.5359 | +0.5359 |
| 7 | y_g | -0.1547 | -0.1547 | +0.1547 |
| 7 | y_x3 | +1.0000 | +1.0000 | -1.0000 |
| 7 | z_x4 | +1.0000 | -1.0000 | +1.0000 |
| 7 | z_x5 | -2.0000 | +2.0000 | -2.0000 |
| 8 | y_c | -0.5359 | -0.5359 | +0.5359 |
| 8 | y_g | +0.1547 | +0.1547 | -0.1547 |
| 8 | y_x3 | +1.0000 | +1.0000 | -1.0000 |
| 8 | z_x4 | +1.0000 | -1.0000 | +1.0000 |
| 8 | z_x5 | -2.0000 | +2.0000 | -2.0000 |
Conclusion
| Solver | Stationarity (read on min f) |
Maximisation (max -f) |
|---|---|---|
| Ipopt | A | A, as written — every multiplier changes sign |
| MadNLP | A | none, inconsistent: the rows follow as written, the bounds and fixed variable min-equiv. |
| Uno | B | B, as written — every multiplier changes sign |
| CTSolvers.Ipopt | A | A, as written — every multiplier changes sign |
| CTSolvers.MadNLP | A | none, inconsistent: the rows follow as written, the bounds and fixed variable min-equiv. |
| CTSolvers.MadNCL | A | none, inconsistent: the rows follow as written, the bounds and fixed variable min-equiv. |
| CTSolvers.Uno | B | B, as written — every multiplier changes sign |
- Stationarity A:
Ipopt,MadNLP,CTSolvers.Ipopt,CTSolvers.MadNLP,CTSolvers.MadNCL. - Stationarity B:
Uno,CTSolvers.Uno.
A solver marked none has the stationarity of its family on min f, but on max -f it mixes the two rules: some multipliers change sign between min f and max -f (those of the rows), others do not (those of the bounds and of fixed variables). No single convention, as defined above, describes its output.
Proposed conventionPrinciple: a multiplier belongs to a constraint and to a problem, not to the way they are written.
Stationarity, for the equivalent minimisation of What it gives on the cases of the probeThe 8 ways of writing the problem of control-toolbox/CTSolvers.jl#287 (
With the signed The same convention in the indirect method: always maximise the pseudo-HamiltonianThe maximum principle, as written in the OptimalControl documentation (Formulation → Notation and conventions), reads and along an optimal trajectory the control maximises Then This is the indirect counterpart of the rule of the direct method: there, The other possible convention, the multipliers of the criterion as written, would keep Consequences
|
The convention is defined in ct-conventionsThe convention discussed here is now written as rules
Implementation (draft PRs):
|
Uh oh!
There was an error while loading. Please reload this page.
Sign conventions across the ecosystem:
minvsmax,p⁰, inequality constraints, and the signs ofpand of the dualsThis is a request to think about and settle one convention for the whole ecosystem (CTDirect, CTFlows, CTModels, OptimalControl docs). Nothing is decided here; the aim is to list the choices, their consequences, and what the code does today.
Why now
Three pieces of work all depend on these signs:
Flow(ocp, law)Solution: reconstruct the constraint duals from the multipliers CTFlows.jl#472:Flow(ocp, law)should return the constraint duals, comparable with the ones of a direct solve. Its sign rule depends on the choices below.H̃ + μ·g); the label is the key that links them todual(sol, ocp, label).Past related threads: control-toolbox/CTDirect.jl#515 and #663 (for
max f(x)Ipopt returnedfand MadNLP-f; solved on the CTDirect side), control-toolbox/CTDirect.jl#405 (scaling of the path duals).What the code does today (probed, 2026-10-21)
Probes with OptimalControl 2.2.1-beta (CTDirect 1.1.8-beta) with Ipopt and MadNLP, and CTFlows
main, on problems with a closed form. A constraint is writteng = sign·(c − bound) ≥ 0(sign = +1lower side or equality,−1upper side), and the CTFlows pseudo-Hamiltonian isH̃ = p·f + sp0·ℓ + μ·gwithsp0 = −1for:min,+1for:max.:min, path constraintμ ≥ 0forg ≥ 0dual = −sign·μ(for all sides, Ipopt = MadNLP):min, box constraintμdual = −sign·μ·h(not divided byh; opposite sign to a path constraint):maxinstead of:min(same problem written−ℓ)pandμ:H̃is identical (sp0·ℓis unchanged), and the control is stillargmax H̃pand the duals change sign (p⁰stays−1, soH = p·f − ℓ)On the problem
ẋ = u,x(0) = −1,x + u ≤ 0,∫(−u) → min(and the same with∫u → max): CTDirect givesp = −0.63…in:minand+0.63…in:max, anddual(:mixed) = ±e^{t−1}respectively. CTFlows gives the samepfor both.Questions to settle
minandmax. If the user changesmin Jintomax −J, shouldpand the duals change sign or not?p⁰ = −1always,H = p·f − ℓ, andmaxmeansargmin H). It is the convention of CTDirect today.His always maximised;sp0 = s·p⁰flips with the criterion). It is the convention of CTFlows today, and the control lawu = argmax Hdoes not depend on the criterion.p⁰.−1(OptimalControl docs, "Notation and conventions") with a signsfor min/max, or+1? Isp⁰normalised, or free (abnormal extremals)?H̃ = p·f + p⁰ℓ + μ·cwithc ≥ 0andμ ≥ 0, orc ≤ 0andμ ≥ 0(writtenμ·gwithg ≤ 0in the older CTFlows)? And for a two-sided constraintlb ≤ c ≤ ub: two multipliersμ_l, μ_u ≥ 0withμ = μ_l − μ_u(as in CTDirect#639), or the active side given explicitly (asconstraint = :label => :upperin CTFlows)?p(t_f) = ∓∇g + ∂b'β: sign ofβand of the dual of a boundary constraint (CTDirect#639:dual(:target) = −p(t_f)today).maxgap, now gone): which tests keep this true?What is asked
Please give your view on 1, 2 and 3 first (the others follow). I propose to decide, then:
Flow(ocp, law)Solution: reconstruct the constraint duals from the multipliers CTFlows.jl#472) on it, and add a test that comparesdual(sol, ocp, label)of a direct and of an indirect solve;pflips withmin/maxand, if so, change it in CTFlows, which affects the sign ofp0in shooting functions written for:maxproblems.All reactions