[Doc] Examples for the sign convention of duals and costate (min/max, writing of constraints, direct vs indirect)

Đang mở
#1,016 1 bình luận 0 reaction 1 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@ocots đang làm issue này rồi.

Từ ngày 23/10/2026.

Đánh giá

Issue này chưa được đánh giá.

Mô tả

Follow-up of #1014 (the convention) and companion of #1015 (the page that states it). This issue lists the examples to add to the documentation, so that a user can see that the signs do not depend on the solver, on the sense of the criterion, or on the way a constraint is written. Each example should also become a test: run in a docs page, it fails loudly if a convention moves.

The implementation is in three draft PRs:

  • control-toolbox/CTSolvers.jl#289: one multiplier convention for every NLP solver. min f and max -f have the same multipliers; a constraint with a single bound has a nonnegative multiplier; equalities keep their sign.
  • control-toolbox/CTFlows.jl#494: the solution of Flow(ocp, law; constraint=:label, multiplier=μ) carries dual(sol, ocp, :label), in the same convention.
  • control-toolbox/CTModels.jl#483: dual on a solution that holds the duals of some constraints only, and the jumps of the duals in the plots of a multi-phase solution.

The convention, as the user should read it (for #1015)

  • The dual of an inequality constraint is nonnegative, whatever the constraint and the sense of the criterion. g(x) ≤ 0 and -g(x) ≥ 0, or x(t) ≥ 0.1 and 0.1 - x(t) ≤ 0, are the same constraint and have the same dual.
  • An equality keeps its sign: c = 0 and -c = 0 have opposite duals.
  • min J and max -J are the same problem: they have the same duals and the same costate p. Only the objective changes sign.
  • Indirect method: the pseudo-Hamiltonian H = p·f + p⁰ℓ + μ·g (g ≥ 0, μ ≥ 0) is always maximised, with p⁰ = -1 for a minimisation and +1 for a maximisation. dual(sol, ocp, :label) of a flow solution is the μ given to the flow (0 off the boundary arc).
  • A constraint with two finite bounds, lb ≤ c ≤ ub, has a signed dual: +μ when the upper side is active, -μ when the lower side is.

Examples to add

  1. The signs do not change with min/max. Solve ẋ = u, x(0) = -1, x(t) + u(t) ≤ 0, 0 ≤ u(t):

    • once as ∫ -u(t) dt → min, once as ∫ u(t) dt → max;
    • with Ipopt and with MadNLP.

    Show that costate(sol) and dual(sol, ocp, :mixed) are the same in the four cases. The closed form is p(t) = e^{t-1} - 1 and dual = e^{t-1}.

  2. The signs do not change with the way a constraint is written. The same problem with x(t) + u(t) ≤ 0 written as -x(t) - u(t) ≥ 0: the same dual.

  3. Direct and indirect give the same duals. Rebuild the solution of example 1 with Flow(ocp, (x, p) -> -x; constraint=:mixed, multiplier=(x, p) -> p + 1), then compare dual(sol_direct, ocp, :mixed) and dual(sol_flow, ocp, :mixed) on one plot. They agree up to the discretisation error.

  4. A boundary arc in a multi-phase indirect solution. The problem of control-toolbox/CTFlows.jl#440 (x ≥ 0.1, three arcs). plot(sol) shows the dual, 0 then 2x = 0.2 on the boundary arc then 0, with its jumps at the junctions and the phase labels. Compare with a direct solve of the same problem.

  5. Why the label matters. In a flow, a constraint given as a function has no label: its dual cannot be placed in the solution, the flow warns, and dual throws. Show the labelled form, constraint=:label or :label => :upper.

Possible tests (OptimalControl test suite, the cross-package level): examples 1 to 3, with Ipopt and MadNLP (and Uno), as @test on the closed form.

Still open (not for the user page)

  • Box constraints. The dual of a box (0 ≤ u(t) ≤ 1 declared as a box) has the opposite sign to the same constraint written as a path constraint, and it is not divided by the step (control-toolbox/CTDirect.jl#639). The page should say so until it is fixed, or wait for it.
  • Boundary and box duals of a flow solution are not rebuilt (dual throws a PreconditionError).
  • Two-sided constraints: the signed value is kept. Is that what the page should present, or a pair (lower, upper)?

🤖 Generated with Claude Code

Ngôn ngữ chính
Julia
Star
135
Fork
11
Merge trung bình
7 giờ 49 phút
Pull request đã merge (30 ngày)
23

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của control-toolbox/OptimalControl.jl

Tất cả issue của control-toolbox/OptimalControl.jl

Issue tương tự

Thêm issue về Julia

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.