[Design] Should a constraint bound be allowed to depend on the model? Levels of relaxation
I maintainer di solito rispondono entro 1 giorno
@jbcaillau ci sta già lavorando.
Dal 1/11/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Written by Claude (Claude Code), at the request of ocots, from an exploration of the question. The analysis and the prototype are mine; the position of ocots is given at the end. The question to decide is for the maintainers.
@jbcaillau: your opinion is asked, see the question at the end.
Context
A constraint is written lb ≤ expression ≤ ub, and the bounds must not depend on the state, the control, the variable or the time. Since #343 a bound that does is rejected with a ParsingError; before, it leaked an internal name. PR #396 (for #352) makes the error say how to rewrite the constraint. This issue asks whether the parser should keep refusing, or do the rewriting itself.
Why the rule exists
It is not only a simplification of the parser. The generated code always calls constraint!(…; f=…, lb=…, ub=…), and the model stores each constraint as lb ≤ f(x, u, v, t) ≤ ub with constant lb and ub. This is the form of an optimal control problem and of the NLP it is discretised into, and a box constraint (x₂(t) ≥ 1) becomes a bound on a variable.
Nothing is undecidable: whether a bound depends on the model is known when the block is parsed (has on the declared symbols), and a ≤ b is always equivalent to a - b ≤ 0. A constraint with a bound that depends on the model is a different constraint written in a different place.
What I tried
A throwaway prototype (not pushed) that rewrites instead of refusing, in p_constraint!, before the type of the constraint is chosen:
1 ≤ x₂(t)→ swap the sides:x₂(t) ≥ 1. Same constraint, still a box constraint.x₁(t) ≤ u(t)→x₁(t) - u(t) ≤ 0(lb = -Inf,ub = 0), a path constraint.x₂(2) == v→x₂(2) - v == 0, a boundary constraint.
With the :fun backend the model is the one of the hand-written form (numbers checked: f = 2 for x₁ ≤ u at x = [3, 0], u = 1; f = 5 for x₂(2) == v at xf = [5, 7], v = 2). With the :exa backend the NLP is identical to the hand-written form (number of variables and constraints, lvar, uvar, lcon, ucon, and cons at a random point) for the scalar cases.
What has to be settled
- Sign of the multipliers.
a ≤ brewritten asa - b ≤ 0or asb - a ≥ 0changes the orientation of the dual. A rule must be fixed and documented (left minus right, relation kept), which matters for the duals by label (#382). - Vector expressions. A scalar bound on a vector expression is not broadcast today, see #400 (
DimensionMismatchwith:fun, silently0with:exa). A rewriting of a vector constraint would hit it, so it has to be fixed first, or the rewriting has to build bounds of the right dimension. - Two-sided constraints with a bound that depends on the model (
0 ≤ x₂(0) ≤ v). They would have to be split in two, and the label duplicated. I would keep them refused. - Tests on both backends, and the type of the constraint (box, path, boundary) recomputed after the rewriting.
Levels
Relaxing is not breaking (what is refused today would be accepted), whereas tightening later would be. So it can be done in steps:
| Level | Behaviour | Risk |
|---|---|---|
| 0 (PR #396, current) | refuse, with a rewriting suggested from the constraint itself | none |
| 1 | swap the sides when only the bound depends on the model and the middle does not (1 ≤ x₂(t) → x₂(t) ≥ 1) |
none: same constraint, same type, same dual |
| 2 | also move the term to the left when both sides depend on the model (x₁(t) ≤ u(t) → x₁(t) - u(t) ≤ 0), and equalities (x₂(2) == v) |
duals (point 1), vector expressions (point 2) |
| 3 | also two-sided constraints, by splitting | labels, duals |
Position of ocots
Level 0 is a good first step and PR #396 is it. ocots would go as far as level 1 and stop there: the freedom it gives is free of ambiguity (1 ≤ x₂(t) can only mean x₂(t) ≥ 1), while from level 2 the parser would choose a form, and with it the sign of the duals, in place of the user. The point of the exploration was to see what is possible without a reason for the rigid syntax; there is none that forbids it, only the choices of points 1 to 4.
Question
For @jbcaillau: do you see a reason for the current rigidity that I do not (for instance in how the constraints are used downstream, in CTDirect or in the plots), and where would you stop: level 0, 1 or 2?
Related: #343, #352, #400.
- Lingua principale
- Julia
- Stelle
- 3
- Fork
- 0
- Merge medio
- 1g 32m
- PR unite (30g)
- 18
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di control-toolbox/CTParser.jl
-
Generate every representation of each component; remove the discretization from the :exa backendForse già presa @jbcaillau l’ha presa 3 giorni fa. Aperta
control-toolbox/CTParser.jl#415 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Keep the :exa constraint handles by label and return the path/boundary multipliers by labelForse già presa @jbcaillau l’ha presa 6 giorni fa. Aperta
control-toolbox/CTParser.jl#414 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
[Dev] Automatic names of the components (x₁, x1, …): limit of 9 for a symbolic dimensionForse già presa @jbcaillau l’ha presa 7 giorni fa. Apertafeature
control-toolbox/CTParser.jl#403 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
[Dev] Digit exponents R²¹, R¹⁰⁰: keep the limit of 20 or read the exponent?Forse già presa @jbcaillau l’ha presa 7 giorni fa. Apertafeature
control-toolbox/CTParser.jl#402 · 1 commento · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
A scalar bound on a vector-valued boundary constraint is not broadcast: DimensionMismatch with :fun, silently 0 with :exaForse già presa @jbcaillau l’ha presa 7 giorni fa. Apertabug
control-toolbox/CTParser.jl#400 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di control-toolbox/CTParser.jl
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 1-3 ore Idoneità per principianti 86/100
-
Pin the porting environmentAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
FluxML/Metalhead.jl#407 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
SciML/ModelingToolkit.jl#5371 ·
I maintainer di solito rispondono entro 2 giorni