Skip to content

added: support box constraint in LinMPC and NonLinMPC#379

Open
franckgaga wants to merge 14 commits into
mainfrom
box_constraints
Open

added: support box constraint in LinMPC and NonLinMPC#379
franckgaga wants to merge 14 commits into
mainfrom
box_constraints

Conversation

@franckgaga

@franckgaga franckgaga commented Jun 18, 2026

Copy link
Copy Markdown
Member

Following discussion at #378, it is a good idea in terms of performances to treat constraints on the decision variable as box constraints, instead of linear inequality constraints, at least for NLP and interior point methods.

In this PR, these constraints:

  • limit on slack variable $\epsilon \ge 0$
  • limits on the input increments $\mathbf{\Delta u}$,
  • limits on the terminal state $\mathbf{\hat{x}}(k+H_p)$ for non-SingleShooting

are treated as box constraints. It applies to both LinMPC and NonLinMPC. Note that if there is a nonzero value in the associated softness parameters $\mathbf{c_{(\bullet)}}$ it is no longer a box constraint and the associated bound is treated as a linear inequality constraint, like before.

The default QP solver for LinMPC is OSQP.jl, and it does not support box constraint natively. It is still possible to define box constraints with the bridge mechanism of JuMP.jl. The new default optim argument for LinMPC is optim=JuMP.Model(OSQP.MathOptInterfaceOSQP.Optimizer, add_bridges=true). It should not affect the performances since JuMP will automatically convert them as linear equality constraints, as it was the case before this PR. It's possible that the performances with DAQP.jl will be improved however, since it supports box constraints natively.

Warning

Constructing LinMPC with optim=JuMP.Model(OSQP.MathOptInterfaceOSQP.Optimizer, add_bridges=false) will now throw an error. Please use add_bridges=true (it should not affect performances).

Let's see the benchmarks.

@codecov-commenter

codecov-commenter commented Jun 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.60%. Comparing base (ed09542) to head (82f0ab8).
⚠️ Report is 8 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #379      +/-   ##
==========================================
+ Coverage   98.58%   98.60%   +0.02%     
==========================================
  Files          27       27              
  Lines        5512     5595      +83     
==========================================
+ Hits         5434     5517      +83     
  Misses         78       78              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown

Benchmark Results (Julia v1)

Time benchmarks
main 82f0ab8... main / 82f0ab8...
CASE STUDIES/PredictiveController/CSTR/LinMPC/With feedforward/DAQP/SingleShooting 5.49 ± 0.5 ms 5.74 ± 0.58 ms 0.956 ± 0.13
CASE STUDIES/PredictiveController/CSTR/LinMPC/With feedforward/OSQP/MultipleShooting 11.6 ± 0.78 ms 11.6 ± 0.71 ms 0.999 ± 0.09
CASE STUDIES/PredictiveController/CSTR/LinMPC/With feedforward/OSQP/SingleShooting 1.93 ± 0.12 ms 1.86 ± 0.11 ms 1.04 ± 0.087
CASE STUDIES/PredictiveController/CSTR/LinMPC/Without feedforward/DAQP/SingleShooting 5.44 ± 0.51 ms 5.64 ± 0.55 ms 0.965 ± 0.13
CASE STUDIES/PredictiveController/CSTR/LinMPC/Without feedforward/OSQP/MultipleShooting 8.12 ± 0.54 ms 8.07 ± 0.49 ms 1.01 ± 0.09
CASE STUDIES/PredictiveController/CSTR/LinMPC/Without feedforward/OSQP/SingleShooting 2.13 ± 0.12 ms 2.04 ± 0.11 ms 1.04 ± 0.083
CASE STUDIES/PredictiveController/Pendulum/LinMPC/Successive linearization/DAQP/SingleShooting 9.9 ± 1.4 ms 9.99 ± 1.3 ms 0.991 ± 0.19
CASE STUDIES/PredictiveController/Pendulum/LinMPC/Successive linearization/OSQP/MultipleShooting 0.107 ± 0.02 s 0.104 ± 0.021 s 1.02 ± 0.28
CASE STUDIES/PredictiveController/Pendulum/LinMPC/Successive linearization/OSQP/SingleShooting 14.8 ± 1.8 ms 14.9 ± 1.8 ms 0.99 ± 0.17
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/MultipleShooting 0.598 ± 0.0024 s 0.534 ± 0.0017 s 1.12 ± 0.0058
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/MultipleShooting (Hessian) 0.759 ± 0.0015 s 1.28 ± 0.0026 s 0.594 ± 0.0017
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/SingleShooting 1.43 ± 0.0031 s 1.6 ± 0.0048 s 0.893 ± 0.0033
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/TrapezoidalCollocation 0.585 ± 0.0012 s 0.973 ± 0.0021 s 0.602 ± 0.0018
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/TrapezoidalCollocation (Hessian) 0.586 ± 0.0027 s 0.972 ± 0.0018 s 0.603 ± 0.003
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/MultipleShooting 0.368 ± 0.0011 s 0.364 ± 0.00055 s 1.01 ± 0.0033
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/MultipleShooting (Hessian) 0.422 ± 0.002 s 0.42 ± 0.0035 s 1 ± 0.0095
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/OrthogonalCollocation 0.541 ± 0.0036 s 0.529 ± 0.00098 s 1.02 ± 0.0071
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/OrthogonalCollocation (Hessian) 0.544 ± 0.0013 s 0.54 ± 0.00094 s 1.01 ± 0.003
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/SingleShooting 0.541 ± 0.0022 s 0.587 ± 0.0013 s 0.922 ± 0.0044
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/SingleShooting (Hessian) 0.191 ± 0.0013 s 0.188 ± 0.0015 s 1.01 ± 0.011
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/TrapezoidalCollocation 0.347 ± 0.0011 s 0.334 ± 0.0013 s 1.04 ± 0.0052
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/TrapezoidalCollocation (Hessian) 0.323 ± 0.0018 s 0.322 ± 0.00065 s 1 ± 0.0058
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/MadNLP/SingleShooting (Hessian) 0.0829 ± 0.00029 s 0.0896 ± 0.00067 s 0.925 ± 0.0077
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Uno/MultipleShooting (Hessian) 0.193 ± 0.011 s 0.192 ± 0.012 s 1.01 ± 0.083
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/MultipleShooting 0.351 ± 0.00081 s 0.342 ± 0.0034 s 1.03 ± 0.011
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/MultipleShooting (Hessian) 0.356 ± 0.0011 s 0.364 ± 0.00091 s 0.977 ± 0.0038
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/MultipleShooting (threaded) 0.374 ± 0.0016 s 0.363 ± 0.0027 s 1.03 ± 0.009
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/OrthogonalCollocation 0.599 ± 0.0012 s 0.632 ± 0.0031 s 0.949 ± 0.005
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/OrthogonalCollocation (Hessian) 1.67 ± 0.0093 s 1.7 ± 0.0084 s 0.979 ± 0.0073
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/SingleShooting 0.546 ± 0.0024 s 0.527 ± 0.0024 s 1.04 ± 0.0065
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/SingleShooting (Hessian) 0.18 ± 0.00058 s 0.183 ± 0.00065 s 0.981 ± 0.0047
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/TrapezoidalCollocation 0.336 ± 0.00079 s 0.339 ± 0.00076 s 0.991 ± 0.0032
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/TrapezoidalCollocation (Hessian) 0.278 ± 0.0012 s 0.286 ± 0.00097 s 0.972 ± 0.0054
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/TrapezoidalCollocation (threaded) 0.357 ± 0.0014 s 0.361 ± 0.0015 s 0.989 ± 0.0057
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/MadNLP/MultipleShooting (Hessian) 0.242 ± 0.0012 s 0.242 ± 0.001 s 0.999 ± 0.0065
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/MadNLP/SingleShooting (Hessian) 0.0802 ± 0.00035 s 0.0808 ± 0.00052 s 0.993 ± 0.0077
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Uno/MultipleShooting (Hessian) 0.176 ± 0.0016 s 0.173 ± 0.0012 s 1.02 ± 0.012
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Uno/OrthogonalCollocation (Hessian) 0.794 ± 0.0057 s 0.808 ± 0.0042 s 0.982 ± 0.0087
CASE STUDIES/StateEstimator/CSTR/MovingHorizonEstimator/DAQP/Current form 0.0639 ± 0.0023 s 0.0669 ± 0.0026 s 0.956 ± 0.051
CASE STUDIES/StateEstimator/CSTR/MovingHorizonEstimator/DAQP/Prediction form 0.048 ± 0.0017 s 0.0487 ± 0.0017 s 0.986 ± 0.05
CASE STUDIES/StateEstimator/CSTR/MovingHorizonEstimator/OSQP/Current form 0.06 ± 0.0037 s 0.0635 ± 0.0039 s 0.945 ± 0.081
CASE STUDIES/StateEstimator/CSTR/MovingHorizonEstimator/OSQP/Prediction form 0.0427 ± 0.0044 s 0.0424 ± 0.0045 s 1.01 ± 0.15
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/Ipopt/Current form 0.0929 ± 0.00028 s 0.0926 ± 0.00015 s 1 ± 0.0034
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/Ipopt/Current form (Hessian) 0.0918 ± 0.00022 s 0.0921 ± 0.00079 s 0.996 ± 0.0089
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/Ipopt/Prediction form 0.0697 ± 0.00031 s 0.07 ± 0.00041 s 0.995 ± 0.0074
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/Ipopt/Prediction form (Hessian) 0.0899 ± 0.00024 s 0.09 ± 0.00042 s 0.999 ± 0.0053
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/MadNLP/Current form (Hessian) 0.0499 ± 0.00031 s 0.0505 ± 0.00031 s 0.987 ± 0.0086
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/MadNLP/Prediction form (Hessian) 0.045 ± 0.00029 s 0.0454 ± 0.00032 s 0.991 ± 0.0094
UNIT TESTS/PredictiveController/ExplicitMPC/moveinput! 4.19 ± 0.03 μs 3.79 ± 0.039 μs 1.11 ± 0.014
UNIT TESTS/PredictiveController/LinMPC/getinfo! 0.108 ± 0.0025 ms 0.112 ± 0.0027 ms 0.962 ± 0.033
UNIT TESTS/PredictiveController/LinMPC/moveinput!/MultipleShooting 0.11 ± 0.0012 ms 0.135 ± 0.0092 ms 0.818 ± 0.056
UNIT TESTS/PredictiveController/LinMPC/moveinput!/SingleShooting 15.9 ± 0.31 μs 16.5 ± 0.31 μs 0.968 ± 0.026
UNIT TESTS/PredictiveController/NonLinMPC/getinfo!/LinModel 0.191 ± 0.016 ms 0.168 ± 0.011 ms 1.14 ± 0.12
UNIT TESTS/PredictiveController/NonLinMPC/getinfo!/NonLinModel 0.228 ± 0.018 ms 0.233 ± 0.021 ms 0.979 ± 0.12
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/LinModel/MultipleShooting 1.52 ± 0.23 ms 1.07 ± 0.2 ms 1.41 ± 0.34
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/LinModel/SingleShooting 1 ± 0.057 ms 0.466 ± 0.026 ms 2.15 ± 0.17
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/MultipleShooting 2.45 ± 0.73 ms 10.5 ± 0.2 ms 0.235 ± 0.07
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/MultipleShootingHessian 2.31 ± 0.13 ms 10.5 ± 0.18 ms 0.221 ± 0.013
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/OrthogonalCollocation 2.25 ± 0.31 ms 10.4 ± 1.2 ms 0.215 ± 0.039
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/OrthogonalCollocationHessian 3.02 ± 0.14 ms 10.5 ± 0.55 ms 0.287 ± 0.02
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/SingleShooting 1.32 ± 0.041 ms 7.17 ± 0.28 ms 0.184 ± 0.0092
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/SingleShootingHessian 1.32 ± 0.033 ms 7.26 ± 0.26 ms 0.182 ± 0.0079
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/TrapezoidalCollocation 1.7 ± 0.21 ms 7.45 ± 0.25 ms 0.228 ± 0.029
UNIT TESTS/SimModel/LinModel/evaloutput 0.14 ± 0 μs 0.13 ± 0.01 μs 1.08 ± 0.083
UNIT TESTS/SimModel/LinModel/updatestate! 0.2 ± 0.01 μs 0.18 ± 0.001 μs 1.11 ± 0.056
UNIT TESTS/SimModel/NonLinModel/evaloutput 0.391 ± 0.01 μs 0.401 ± 0.01 μs 0.975 ± 0.035
UNIT TESTS/SimModel/NonLinModel/linearize! 1.93 ± 0.021 μs 2.02 ± 0.03 μs 0.956 ± 0.018
UNIT TESTS/SimModel/NonLinModel/updatestate! 0.461 ± 0.01 μs 0.441 ± 0.01 μs 1.05 ± 0.033
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/evaloutput/LinModel 0.511 ± 0.01 μs 0.511 ± 0.01 μs 1 ± 0.028
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/evaloutput/NonLinModel 1.74 ± 0.011 μs 1.75 ± 0.02 μs 0.994 ± 0.013
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/preparestate!/LinModel 0.261 ± 0.01 μs 0.24 ± 0.01 μs 1.09 ± 0.062
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/preparestate!/NonLinModel 1.41 ± 0.01 μs 1.39 ± 0.001 μs 1.01 ± 0.0072
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/updatestate!/LinModel 3.94 ± 0.049 μs 3.96 ± 0.04 μs 0.995 ± 0.016
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/updatestate!/NonLinModel 8.62 ± 0.08 μs 8.74 ± 0.089 μs 0.986 ± 0.014
UNIT TESTS/StateEstimator/InternalModel/evaloutput/LinModel 0.23 ± 0.01 μs 0.231 ± 0.011 μs 0.996 ± 0.064
UNIT TESTS/StateEstimator/InternalModel/evaloutput/NonLinModel 0.571 ± 0.01 μs 0.571 ± 0.02 μs 1 ± 0.039
UNIT TESTS/StateEstimator/InternalModel/preparestate!/LinModel 0.311 ± 0.001 μs 0.311 ± 0.001 μs 1 ± 0.0045
UNIT TESTS/StateEstimator/InternalModel/preparestate!/NonLinModel 0.721 ± 0.001 μs 0.711 ± 0.01 μs 1.01 ± 0.014
UNIT TESTS/StateEstimator/InternalModel/updatestate!/LinModel 0.431 ± 0.001 μs 0.44 ± 0.01 μs 0.98 ± 0.022
UNIT TESTS/StateEstimator/InternalModel/updatestate!/NonLinModel 1.23 ± 0.019 μs 1.21 ± 0.01 μs 1.02 ± 0.018
UNIT TESTS/StateEstimator/KalmanFilter/evaloutput 0.25 ± 0.019 μs 0.23 ± 0.001 μs 1.09 ± 0.083
UNIT TESTS/StateEstimator/KalmanFilter/preparestate! 0.13 ± 0.009 μs 0.131 ± 0.01 μs 0.992 ± 0.1
UNIT TESTS/StateEstimator/KalmanFilter/updatestate! 2.45 ± 0.03 μs 2.58 ± 0.03 μs 0.95 ± 0.016
UNIT TESTS/StateEstimator/Luenberger/evaloutput 0.24 ± 0.001 μs 0.24 ± 0.01 μs 1 ± 0.042
UNIT TESTS/StateEstimator/Luenberger/preparestate! 0.24 ± 0.001 μs 0.25 ± 0.01 μs 0.96 ± 0.039
UNIT TESTS/StateEstimator/Luenberger/updatestate! 0.35 ± 0.01 μs 0.33 ± 0.01 μs 1.06 ± 0.044
UNIT TESTS/StateEstimator/MovingHorizonEstimator/getinfo!/LinModel 0.235 ± 0.018 ms 0.234 ± 0.019 ms 1 ± 0.11
UNIT TESTS/StateEstimator/MovingHorizonEstimator/getinfo!/NonLinModel 0.345 ± 0.021 ms 0.346 ± 0.021 ms 0.996 ± 0.087
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/LinModel/Constant arr. cov. 25.9 ± 1.6 ms 25.7 ± 1.7 ms 1 ± 0.089
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/LinModel/Current form 25.7 ± 1.6 ms 25.8 ± 1.6 ms 0.995 ± 0.087
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/LinModel/Prediction form 0.511 ± 0.01 μs 0.511 ± 0.01 μs 1 ± 0.028
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/NonLinModel/Current form 0.306 ± 0.022 ms 0.305 ± 0.021 ms 1 ± 0.1
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/NonLinModel/Prediction form 1.43 ± 0.019 μs 1.4 ± 0.01 μs 1.02 ± 0.015
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/LinModel/Constant arr. cov. 9.33 ± 1.5 μs 8.46 ± 1.5 μs 1.1 ± 0.27
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/LinModel/Current form 22.1 ± 5 μs 22 ± 3.8 μs 1 ± 0.29
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/LinModel/Prediction form 24 ± 1.2 ms 23.8 ± 1 ms 1.01 ± 0.067
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/NonLinModel/Current form 17 ± 0.31 μs 16.9 ± 0.32 μs 1.01 ± 0.027
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/NonLinModel/Prediction form 0.319 ± 0.022 ms 0.321 ± 0.022 ms 0.992 ± 0.098
UNIT TESTS/StateEstimator/SteadyKalmanFilter/evaloutput 0.26 ± 0.01 μs 0.26 ± 0.01 μs 1 ± 0.054
UNIT TESTS/StateEstimator/SteadyKalmanFilter/preparestate! 0.271 ± 0.01 μs 0.271 ± 0.001 μs 1 ± 0.037
UNIT TESTS/StateEstimator/SteadyKalmanFilter/updatestate! 0.341 ± 0.011 μs 0.351 ± 0.011 μs 0.972 ± 0.044
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/evaloutput/LinModel 0.311 ± 0.01 μs 0.311 ± 0.01 μs 1 ± 0.045
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/evaloutput/NonLinModel 0.912 ± 0.011 μs 0.912 ± 0.01 μs 1 ± 0.016
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/preparestate!/LinModel 3.6 ± 0.029 μs 3.62 ± 0.08 μs 0.995 ± 0.023
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/preparestate!/NonLinModel 4.9 ± 0.031 μs 4.94 ± 0.03 μs 0.992 ± 0.0087
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/updatestate!/LinModel 3.56 ± 0.07 μs 3.5 ± 0.031 μs 1.02 ± 0.022
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/updatestate!/NonLinModel 6.26 ± 0.069 μs 6.35 ± 0.05 μs 0.986 ± 0.013
time_to_load 6.03 ± 0.021 s 5.97 ± 0.028 s 1.01 ± 0.0059
Memory benchmarks
main 82f0ab8... main / 82f0ab8...
CASE STUDIES/PredictiveController/CSTR/LinMPC/With feedforward/DAQP/SingleShooting 0.0469 M allocs: 1.85 MB 0.0489 M allocs: 1.86 MB 0.993
CASE STUDIES/PredictiveController/CSTR/LinMPC/With feedforward/OSQP/MultipleShooting 0.126 M allocs: 3.16 MB 0.126 M allocs: 3.16 MB 1
CASE STUDIES/PredictiveController/CSTR/LinMPC/With feedforward/OSQP/SingleShooting 12.9 k allocs: 0.361 MB 12.6 k allocs: 0.356 MB 1.01
CASE STUDIES/PredictiveController/CSTR/LinMPC/Without feedforward/DAQP/SingleShooting 0.0468 M allocs: 1.84 MB 0.0487 M allocs: 1.85 MB 0.993
CASE STUDIES/PredictiveController/CSTR/LinMPC/Without feedforward/OSQP/MultipleShooting 0.0882 M allocs: 2.23 MB 0.0879 M allocs: 2.23 MB 1
CASE STUDIES/PredictiveController/CSTR/LinMPC/Without feedforward/OSQP/SingleShooting 12.8 k allocs: 0.355 MB 12.5 k allocs: 0.35 MB 1.01
CASE STUDIES/PredictiveController/Pendulum/LinMPC/Successive linearization/DAQP/SingleShooting 0.119 M allocs: 6.37 MB 0.119 M allocs: 6.38 MB 0.999
CASE STUDIES/PredictiveController/Pendulum/LinMPC/Successive linearization/OSQP/MultipleShooting 4.76 M allocs: 0.257 GB 4.76 M allocs: 0.257 GB 1
CASE STUDIES/PredictiveController/Pendulum/LinMPC/Successive linearization/OSQP/SingleShooting 0.149 M allocs: 8.5 MB 0.148 M allocs: 8.23 MB 1.03
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/MultipleShooting 0.381 M allocs: 26.4 MB 0.369 M allocs: 25.5 MB 1.03
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/MultipleShooting (Hessian) 1.28 M allocs: 0.141 GB 2.2 M allocs: 0.244 GB 0.579
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/SingleShooting 0.233 M allocs: 0.0323 GB 0.306 M allocs: 0.0435 GB 0.743
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/TrapezoidalCollocation 1.28 M allocs: 0.124 GB 2.17 M allocs: 0.212 GB 0.585
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Custom constraints/Ipopt/TrapezoidalCollocation (Hessian) 1.28 M allocs: 0.124 GB 2.17 M allocs: 0.212 GB 0.585
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/MultipleShooting 0.316 M allocs: 22 MB 0.316 M allocs: 22 MB 1
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/MultipleShooting (Hessian) 0.741 M allocs: 0.0843 GB 0.741 M allocs: 0.0843 GB 0.999
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/OrthogonalCollocation 1.33 M allocs: 0.119 GB 1.33 M allocs: 0.119 GB 0.999
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/OrthogonalCollocation (Hessian) 1.33 M allocs: 0.119 GB 1.33 M allocs: 0.119 GB 0.999
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/SingleShooting 0.0965 M allocs: 17.6 MB 0.0965 M allocs: 17.6 MB 1
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/SingleShooting (Hessian) 0.0812 M allocs: 16.8 MB 0.0812 M allocs: 16.9 MB 0.993
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/TrapezoidalCollocation 0.314 M allocs: 21.8 MB 0.314 M allocs: 21.9 MB 0.996
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Ipopt/TrapezoidalCollocation (Hessian) 0.757 M allocs: 0.0765 GB 0.757 M allocs: 0.0765 GB 1
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/MadNLP/SingleShooting (Hessian) 0.0926 M allocs: 19.8 MB 0.0926 M allocs: 20 MB 0.994
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Economic/Uno/MultipleShooting (Hessian) 0.311 M allocs: 0.0327 GB 0.311 M allocs: 0.0327 GB 0.999
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/MultipleShooting 0.277 M allocs: 19 MB 0.277 M allocs: 19 MB 1
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/MultipleShooting (Hessian) 0.709 M allocs: 0.0738 GB 0.709 M allocs: 0.0739 GB 0.999
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/MultipleShooting (threaded) 0.296 M allocs: 28 MB 0.296 M allocs: 28 MB 1
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/OrthogonalCollocation 1.43 M allocs: 0.128 GB 1.43 M allocs: 0.128 GB 0.999
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/OrthogonalCollocation (Hessian) 5.12 M allocs: 0.601 GB 5.12 M allocs: 0.601 GB 0.999
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/SingleShooting 0.0754 M allocs: 13.3 MB 0.0754 M allocs: 13.3 MB 1
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/SingleShooting (Hessian) 0.0808 M allocs: 16.8 MB 0.0808 M allocs: 16.9 MB 0.993
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/TrapezoidalCollocation 0.276 M allocs: 19 MB 0.276 M allocs: 19 MB 0.996
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/TrapezoidalCollocation (Hessian) 0.72 M allocs: 0.0656 GB 0.72 M allocs: 0.0656 GB 1
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Ipopt/TrapezoidalCollocation (threaded) 0.295 M allocs: 28 MB 0.295 M allocs: 28.1 MB 0.997
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/MadNLP/MultipleShooting (Hessian) 0.587 M allocs: 0.0728 GB 0.587 M allocs: 0.0728 GB 0.999
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/MadNLP/SingleShooting (Hessian) 0.0927 M allocs: 19.9 MB 0.0927 M allocs: 20 MB 0.994
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Uno/MultipleShooting (Hessian) 0.307 M allocs: 30.3 MB 0.307 M allocs: 30.3 MB 0.999
CASE STUDIES/PredictiveController/Pendulum/NonLinMPC/Noneconomic/Uno/OrthogonalCollocation (Hessian) 2.13 M allocs: 0.243 GB 2.13 M allocs: 0.243 GB 0.999
CASE STUDIES/StateEstimator/CSTR/MovingHorizonEstimator/DAQP/Current form 1.25 M allocs: 0.213 GB 1.25 M allocs: 0.214 GB 0.995
CASE STUDIES/StateEstimator/CSTR/MovingHorizonEstimator/DAQP/Prediction form 1.16 M allocs: 0.136 GB 1.16 M allocs: 0.136 GB 1
CASE STUDIES/StateEstimator/CSTR/MovingHorizonEstimator/OSQP/Current form 1.13 M allocs: 0.21 GB 1.13 M allocs: 0.21 GB 1
CASE STUDIES/StateEstimator/CSTR/MovingHorizonEstimator/OSQP/Prediction form 1.07 M allocs: 0.134 GB 1.07 M allocs: 0.134 GB 1
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/Ipopt/Current form 0.0691 M allocs: 12.1 MB 0.0691 M allocs: 12.1 MB 1
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/Ipopt/Current form (Hessian) 0.0682 M allocs: 12 MB 0.0682 M allocs: 12 MB 1
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/Ipopt/Prediction form 0.0521 M allocs: 8.54 MB 0.0521 M allocs: 8.54 MB 1
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/Ipopt/Prediction form (Hessian) 0.0684 M allocs: 12.1 MB 0.0684 M allocs: 12.1 MB 1
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/MadNLP/Current form (Hessian) 0.0902 M allocs: 16 MB 0.0902 M allocs: 16 MB 1
CASE STUDIES/StateEstimator/Pendulum/MovingHorizonEstimator/MadNLP/Prediction form (Hessian) 0.0851 M allocs: 14.7 MB 0.0851 M allocs: 14.7 MB 1
UNIT TESTS/PredictiveController/ExplicitMPC/moveinput! 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/PredictiveController/LinMPC/getinfo! 0.327 k allocs: 15.8 kB 0.326 k allocs: 15.6 kB 1.01
UNIT TESTS/PredictiveController/LinMPC/moveinput!/MultipleShooting 0.994 k allocs: 25.5 kB 1.62 k allocs: 0.0403 MB 0.618
UNIT TESTS/PredictiveController/LinMPC/moveinput!/SingleShooting 0.088 k allocs: 2.23 kB 0.114 k allocs: 2.98 kB 0.749
UNIT TESTS/PredictiveController/NonLinMPC/getinfo!/LinModel 0.482 k allocs: 0.0604 MB 0.408 k allocs: 0.0579 MB 1.04
UNIT TESTS/PredictiveController/NonLinMPC/getinfo!/NonLinModel 0.614 k allocs: 0.0785 MB 0.571 k allocs: 0.077 MB 1.02
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/LinModel/MultipleShooting 1.89 k allocs: 0.11 MB 1.79 k allocs: 0.105 MB 1.05
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/LinModel/SingleShooting 0.431 k allocs: 18.1 kB 0.254 k allocs: 10.1 kB 1.79
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/MultipleShooting 2.29 k allocs: 0.143 MB 4.76 k allocs: 0.368 MB 0.388
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/MultipleShootingHessian 2.88 k allocs: 0.198 MB 5.34 k allocs: 0.423 MB 0.468
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/OrthogonalCollocation 3.78 k allocs: 0.22 MB 9.58 k allocs: 0.609 MB 0.361
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/OrthogonalCollocationHessian 7.62 k allocs: 0.681 MB 0.0459 M allocs: 4.44 MB 0.154
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/SingleShooting 0.333 k allocs: 0.0473 MB 0.957 k allocs: 0.233 MB 0.203
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/SingleShootingHessian 0.333 k allocs: 0.0473 MB 0.957 k allocs: 0.233 MB 0.203
UNIT TESTS/PredictiveController/NonLinMPC/moveinput!/NonLinModel/TrapezoidalCollocation 1.45 k allocs: 0.0898 MB 3.42 k allocs: 0.241 MB 0.373
UNIT TESTS/SimModel/LinModel/evaloutput 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/SimModel/LinModel/updatestate! 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/SimModel/NonLinModel/evaloutput 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/SimModel/NonLinModel/linearize! 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/SimModel/NonLinModel/updatestate! 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/evaloutput/LinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/evaloutput/NonLinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/preparestate!/LinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/preparestate!/NonLinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/updatestate!/LinModel 4 allocs: 0.0938 kB 4 allocs: 0.0938 kB 1
UNIT TESTS/StateEstimator/ExtendedKalmanFilter/updatestate!/NonLinModel 4 allocs: 0.0938 kB 4 allocs: 0.0938 kB 1
UNIT TESTS/StateEstimator/InternalModel/evaloutput/LinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/InternalModel/evaloutput/NonLinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/InternalModel/preparestate!/LinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/InternalModel/preparestate!/NonLinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/InternalModel/updatestate!/LinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/InternalModel/updatestate!/NonLinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/KalmanFilter/evaloutput 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/KalmanFilter/preparestate! 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/KalmanFilter/updatestate! 4 allocs: 0.0938 kB 4 allocs: 0.0938 kB 1
UNIT TESTS/StateEstimator/Luenberger/evaloutput 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/Luenberger/preparestate! 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/Luenberger/updatestate! 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/MovingHorizonEstimator/getinfo!/LinModel 1.01 k allocs: 0.0405 MB 1.01 k allocs: 0.0405 MB 1
UNIT TESTS/StateEstimator/MovingHorizonEstimator/getinfo!/NonLinModel 1.27 k allocs: 0.167 MB 1.27 k allocs: 0.167 MB 1
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/LinModel/Constant arr. cov. 0.158 M allocs: 0.119 GB 0.158 M allocs: 0.117 GB 1.02
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/LinModel/Current form 0.158 M allocs: 0.117 GB 0.158 M allocs: 0.115 GB 1.02
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/LinModel/Prediction form 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/NonLinModel/Current form 0.977 k allocs: 25.3 kB 0.977 k allocs: 25.3 kB 1
UNIT TESTS/StateEstimator/MovingHorizonEstimator/preparestate!/NonLinModel/Prediction form 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/LinModel/Constant arr. cov. 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/LinModel/Current form 2 allocs: 0.0469 kB 2 allocs: 0.0469 kB 1
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/LinModel/Prediction form 7.08 k allocs: 0.451 MB 7.08 k allocs: 0.451 MB 1
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/NonLinModel/Current form 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/MovingHorizonEstimator/updatestate!/NonLinModel/Prediction form 0.977 k allocs: 25.3 kB 0.977 k allocs: 25.3 kB 1
UNIT TESTS/StateEstimator/SteadyKalmanFilter/evaloutput 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/SteadyKalmanFilter/preparestate! 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/SteadyKalmanFilter/updatestate! 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/evaloutput/LinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/evaloutput/NonLinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/preparestate!/LinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/preparestate!/NonLinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/updatestate!/LinModel 0 allocs: 0 B 0 allocs: 0 B
UNIT TESTS/StateEstimator/UnscentedKalmanFilter/updatestate!/NonLinModel 0 allocs: 0 B 0 allocs: 0 B
time_to_load 0.149 k allocs: 11.2 kB 0.149 k allocs: 11.2 kB 1

@franckgaga

franckgaga commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

Wow these terrible results haha ⁉️⁉️⁉️

I did something wrong for sure 😆

@franckgaga

franckgaga commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

Okay I ran some of the benchmark locally and many case studies did not converge anymore, that's why. There's presumably a nasty bug hidden somewhere.

I just modify them on `setconstraint!` calls
@franckgaga

franckgaga commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

Okay I have this MRE that converge to the best solution (at least a very good solution) on main, but a very bad solution in this branch:

using ModelPredictiveControl, ControlSystemsBase, JuMP, Ipopt, BenchmarkTools

function f!(ẋ, x, u, _ , p)
    g, L, K, m = p
    θ, ω = x[1], x[2]
    τ = u[1]
    ẋ[1] = ω
    ẋ[2] = -g/L*sin(θ) - K/m*ω + τ/m/L^2
end
h!(y, x, _ , _ ) = (y[1] = 180/π*x[1])
p = [9.8, 0.4, 1.2, 0.3]
nu = 1; nx = 2; ny = 1; Ts = 0.1
pendulum_model = NonLinModel(f!, h!, Ts, nu, nx, ny; p)
pendulum_p = p

h2!(y, x, _ , _ ) = (y[1] = 180/π*x[1]; y[2]=x[2])
nu, nx, ny = 1, 2, 2
pendulum_model2 = NonLinModel(f!, h2!, Ts, nu, nx, ny; p)
pendulum_p2 = p

Hp, Hc, Mwt, Nwt, Cwt = 20, 2, [0.5], [2.5], Inf
umin, umax = [-1.5], [+1.5]

model2, p = pendulum_model2, pendulum_p2
plant2 = deepcopy(model2)
plant2.p[3] = 1.25*p[3]  # plant-model mismatch
σQ = [0.1, 1.0]; σR=[5.0]; nint_u=[1]; σQint_u=[0.1]
estim2 = UnscentedKalmanFilter(model2; σQ, σR, nint_u, σQint_u, i_ym=[1])
function JE(UE, ŶE, _ , p, _)
    Ts = p
    τ, ω = @views UE[1:end-1], ŶE[2:2:end-1]
    return Ts*dot(τ, ω)
end
p = Ts; Mwt2 = [Mwt; 0.0]; Ewt = 3.5e3
x_0 = [0, 0]; x̂_0 = [0, 0, 0]; ry = [180; 0]

function gc!(LHS, Ue, Ŷe, _, p, ϵ)
    Pmax = p
    i_τ, i_ω = 1, 2
    for i in eachindex(LHS)
        τ, ω = Ue[i_τ], Ŷe[i_ω]
        P = τ*ω
        LHS[i] = P - Pmax - ϵ
        i_τ += 1
        i_ω += 2
    end
    return nothing
end
Cwt, Pmax, nc = 1e5, 3, Hp+1
x_0 = [0, 0]; x̂_0 = [0, 0, 0]; ry = [180; 0]

N = 35

optim = JuMP.Model(optimizer_with_attributes(Ipopt.Optimizer,"sb"=>"yes"), add_bridges=false)
transcription = MultipleShooting()
nmpc2_ipopt_ms = NonLinMPC(estim2; 
    Hp, Hc, Nwt=Nwt, Mwt=[0.5, 0], Cwt, gc!, nc, p=Pmax, optim, transcription
)
nmpc2_ipopt_ms = setconstraint!(nmpc2_ipopt_ms; umin, umax)
JuMP.unset_time_limit_sec(nmpc2_ipopt_ms.optim)

samples, evals, seconds = 100, 1, 15*60
# @btime(
#     sim!($nmpc2_ipopt_ms, $N, $ry; plant=$plant2, x_0=$x_0, x̂_0=$x̂_0, progress=false),
#     samples=samples, evals=evals, seconds=seconds, setup=GC.gc()
# )

unset_silent(nmpc2_ipopt_ms.optim)
initstate!(nmpc2_ipopt_ms, [0], [0])
setstate!(nmpc2_ipopt_ms, x̂_0)

preparestate!(nmpc2_ipopt_ms, [0])
u = moveinput!(nmpc2_ipopt_ms, ry)

We can see that the objective increases throughtout the iterrations:

This is Ipopt version 3.14.19, running with linear solver MUMPS 5.8.2.

Number of nonzeros in equality constraint Jacobian...:      271
Number of nonzeros in inequality constraint Jacobian.:      180
Number of nonzeros in Lagrangian Hessian.............:        0

Total number of variables............................:       63
                     variables with only lower bounds:        1
                variables with lower and upper bounds:        0
                     variables with only upper bounds:        0
Total number of equality constraints.................:       60
Total number of inequality constraints...............:       61
        inequality constraints with only lower bounds:        0
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:       61

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  3.2401000e+05 0.00e+00 1.00e+00   0.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  3.2403228e+05 3.69e-14 1.41e-02  -2.0 9.94e-03    -  9.96e-01 1.00e+00h  1
   2  3.2055122e+05 3.77e-06 1.36e-04  -5.3 5.28e-02    -  9.90e-01 1.00e+00f  1
   3  1.2932991e+05 2.49e+00 4.12e-02  -5.1 6.13e+00    -  9.89e-01 5.94e-01f  1
   4  1.4870286e+05 1.45e+00 1.23e+00  -4.9 1.93e+00    -  1.00e+00 2.29e-01f  1
   5  1.1307417e+05 1.28e+00 2.83e-01  -4.8 1.87e+00    -  1.00e+00 6.82e-01h  1
   6  2.1771590e+06 5.46e+00 3.32e+01  -2.9 7.85e+01    -  9.67e-01 1.32e-01f  1
   7  1.9320195e+06 6.39e+00 1.96e+02  -2.6 7.36e+00    -  1.18e-02 5.79e-01h  1
   8  1.9324280e+06 6.42e+00 9.16e+02  -2.6 5.58e+00    -  1.00e+00 5.48e-03h  1
   9  2.0054702e+06 6.31e+00 1.22e+03  -2.6 6.39e+00    -  5.13e-02 4.58e-02h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  2.0056961e+06 6.31e+00 3.95e+03  -2.6 5.78e+00    -  1.62e-03 1.66e-04h  1
  11  2.3155204e+06 5.84e+00 2.94e+03  -2.6 9.30e+00    -  9.22e-04 9.04e-02f  1
  12  2.5187679e+06 5.70e+00 1.92e+03  -2.6 8.02e+00    -  1.95e-01 5.16e-02h  1
  13  2.5349819e+06 5.69e+00 3.02e+03  -2.6 1.21e+01    -  1.19e-02 2.35e-03h  1
  14  2.8620146e+06 5.40e+00 9.88e+03  -2.6 1.09e+01    -  1.20e-01 4.97e-02f  1
  15  8.2033055e+06 2.88e+00 3.36e+04  -2.6 1.04e+01    -  5.42e-02 4.53e-01h  1
  16  1.7043861e+07 1.41e-01 1.48e+03  -2.6 4.80e+00    -  9.69e-01 9.02e-01h  1
  17  1.6890133e+07 1.13e-01 3.63e+04  -2.6 4.71e-01    -  8.99e-01 2.00e-01h  1
  18  1.6336180e+07 9.55e-02 1.20e+04  -2.6 4.77e-01    -  3.81e-01 6.31e-01f  1
  19  1.7189242e+07 4.06e-03 4.47e+04  -2.6 3.54e-01    -  6.19e-02 1.00e+00f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  20  1.6972350e+07 7.39e-05 2.62e-03  -2.6 8.66e-02    -  9.94e-01 1.00e+00f  1
  21  1.6665026e+07 3.63e-03 4.91e+01  -3.9 3.51e-01    -  7.66e-01 4.49e-01f  1
  22  1.6653241e+07 7.44e-03 2.90e-02  -3.9 2.30e-01    -  1.00e+00 1.00e+00f  1
  23  1.6437398e+07 4.24e-02 2.06e+00  -3.9 5.56e-01    -  8.92e-01 1.00e+00f  1
  24  1.6255387e+07 8.97e-05 2.37e-02  -3.9 7.54e-02    -  3.40e-01 1.00e+00h  1
  25  1.6224119e+07 9.48e-05 1.29e-02  -3.9 3.15e+00    -  6.82e-01 4.03e-03f  2
  26  1.5845220e+07 1.26e-02 5.60e+01  -3.9 1.29e+00    -  2.73e-01 5.07e-01f  1
  27  1.4374217e+07 1.83e-01 9.21e+01  -3.9 1.13e+01    -  1.00e+00 3.53e-01f  1
  28  1.3948387e+07 1.71e-01 2.13e+02  -3.9 2.89e+00    -  1.00e+00 6.37e-02f  1
  29  1.2520204e+07 2.41e-03 4.76e+03  -3.9 6.61e-01    -  2.46e-02 1.00e+00f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  30  1.2501433e+07 2.71e-07 8.91e-03  -3.9 8.92e-03    -  1.00e+00 1.00e+00h  1
  31  1.2463733e+07 1.39e-05 2.43e-04  -3.9 1.52e-01    -  1.00e+00 1.94e-01f  2
  32  1.2406349e+07 1.85e-05 7.59e-05  -5.8 2.93e-02    -  1.00e+00 9.67e-01f  1
  33  1.2404926e+07 2.71e-08 2.81e-06  -5.8 1.16e-03    -  1.00e+00 1.00e+00h  1
  34  1.2404496e+07 2.24e-09 2.15e-04  -8.7 2.15e-04    -  1.00e+00 9.81e-01h  1
  35  1.2404470e+07 2.19e-10 2.41e-05  -8.7 2.41e-05    -  1.00e+00 9.38e-01h  1
  36  1.2404471e+07 8.88e-15 2.59e-07  -8.7 2.58e-07    -  1.00e+00 1.00e+00f  1
  37  1.2404470e+07 3.55e-15 2.88e-07 -12.3 2.88e-07    -  1.00e+00 1.00e+00f  1
  38  1.2404470e+07 1.78e-15 8.97e-11 -12.3 8.95e-11    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 38

                                   (scaled)                 (unscaled)
Objective...............:   1.2404469932044904e-01    1.2404469932044903e+07
Dual infeasibility......:   8.9661412978295787e-11    8.9661412978295791e-03
Constraint violation....:   9.1623033856588404e-20    1.7763568394002505e-15
Variable bound violation:   0.0000000000000000e+00    0.0000000000000000e+00
Complementarity.........:   5.0101162578586281e-13    5.0101162578586282e-05
Overall NLP error.......:   6.4974345416931383e-11    8.9661412978295791e-03


Number of objective function evaluations             = 44
Number of objective gradient evaluations             = 39
Number of equality constraint evaluations            = 44
Number of inequality constraint evaluations          = 44
Number of equality constraint Jacobian evaluations   = 39
Number of inequality constraint Jacobian evaluations = 39
Number of Lagrangian Hessian evaluations             = 0
Total seconds in IPOPT                               = 28.387

EXIT: Optimal Solution Found.
1-element Vector{Float64}:
 -1.5000000149650201

The results on main is way better:


This is Ipopt version 3.14.19, running with linear solver MUMPS 5.8.2.

Number of nonzeros in equality constraint Jacobian...:      271
Number of nonzeros in inequality constraint Jacobian.:      181
Number of nonzeros in Lagrangian Hessian.............:        0

Total number of variables............................:       63
                     variables with only lower bounds:        0
                variables with lower and upper bounds:        0
                     variables with only upper bounds:        0
Total number of equality constraints.................:       60
Total number of inequality constraints...............:       62
        inequality constraints with only lower bounds:        0
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:       62

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  3.2400000e+05 0.00e+00 2.20e-03   0.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  3.2399304e+05 3.58e-14 2.13e-03  -8.0 1.00e-02    -  1.00e+00 9.90e-01h  1
   2  3.2525985e+05 8.45e-06 1.09e-04  -9.5 2.39e-01    -  1.00e+00 1.00e+00h  1
   3  3.1650137e+05 3.15e-05 3.85e-03  -6.3 1.21e-01    -  9.90e-01 1.00e+00h  1
   4  2.9849888e+05 1.14e-03 2.22e-01  -7.4 5.31e-01    -  1.00e+00 4.85e-01h  1
   5  2.8580059e+05 2.49e-03 8.67e+00  -7.6 2.35e+00    -  1.00e+00 8.57e-02h  1
   6  1.3045575e+05 2.43e+00 8.87e-01  -7.5 1.04e+01    -  9.85e-01 2.95e-01h  1
   7  1.2954931e+05 1.95e+00 1.96e+00  -5.6 7.44e+00    -  1.00e+00 1.38e-01h  1
   8  1.0191055e+05 2.06e+00 1.05e+00  -5.5 2.58e+00    -  1.00e+00 3.28e-01h  1
   9  1.0072735e+05 2.05e+00 1.41e+00  -5.8 2.41e+00    -  2.21e-01 1.67e-02h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  9.5195578e+04 1.96e+00 1.96e+00  -5.2 2.39e+00    -  1.00e+00 1.04e-01h  1
  11  1.4464578e+05 8.68e-01 3.08e-04  -4.7 1.23e+00    -  1.00e+00 1.00e+00h  1
  12  1.3198381e+05 2.80e-01 1.82e-01  -5.8 7.12e-01    -  1.00e+00 8.09e-01h  1
  13  1.2831229e+05 2.20e-02 7.10e-05  -6.5 4.13e-01    -  1.00e+00 1.00e+00h  1
  14  1.2812679e+05 7.51e-04 1.68e-06  -7.5 3.91e-02    -  1.00e+00 1.00e+00h  1
  15  1.2810475e+05 2.47e-05 2.53e-08  -9.6 1.56e-03    -  1.00e+00 9.69e-01h  1
  16  1.2810408e+05 3.11e-09 4.20e-09 -12.3 5.89e-05    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 16

                                   (scaled)                 (unscaled)
Objective...............:   1.2810408484187311e-03    1.2810408484187310e+05
Dual infeasibility......:   4.1966114646936961e-09    4.1966114646936958e-01
Constraint violation....:   1.6049625022104373e-13    3.1116478005355219e-09
Variable bound violation:   0.0000000000000000e+00    0.0000000000000000e+00
Complementarity.........:   5.0384975200402182e-13    5.0384975200402179e-05
Overall NLP error.......:   4.1966114646936961e-09    4.1966114646936958e-01


Number of objective function evaluations             = 17
Number of objective gradient evaluations             = 17
Number of equality constraint evaluations            = 17
Number of inequality constraint evaluations          = 17
Number of equality constraint Jacobian evaluations   = 17
Number of inequality constraint Jacobian evaluations = 17
Number of Lagrangian Hessian evaluations             = 0
Total seconds in IPOPT                               = 23.984

EXIT: Optimal Solution Found.
1-element Vector{Float64}:
 1.2717046667926974

I'm not sure what's happening. I will continue my investigations. Any clue @cvanaret on why the iterations could suddenly increase like this ?

edit : There is only one box constraint here, the slack $\epsilon \ge 0$, for constraint softening. This decision variable tends to take very small values since there is a $(10^5) \epsilon^2$ term in the objective function.

edit 2: It converges to the good solution if I set hessian=true in the NonLinMPC constructor, that is, provide an exact Hessian instead of the builtin LBFGS solver of Ipopt. Maybe it's not a bug on my side. Maybe the builtin LBFGS has difficulties when it's a bound constraint instead of an inequality constraint because it no longer appears in the Jacobian and Hessian? I will try Uno to see what's happening.

@cvanaret

Copy link
Copy Markdown

@franckgaga I'll try to run Ipopt on your instance to look at what's happening.
A few thoughts:

  • when the bound constraint $\varepsilon \ge 0$ is handled as a linear constraint, Ipopt introduces a slack $s$ such that $\varepsilon - s = 0$ and $s \ge 0$, and initializes $s$ with its own strategy (probably something like $10^{-2}$). In the model with explicit bound constraints, you perhaps set an initial value for $\varepsilon$ (I couldn't tell)?
  • Ipopt implements a fraction-to-boundary rule to maintain positivity of $\varepsilon$ or $s$, which has the other effect that the linearized constraints may not be satisfied by the scaled step. Hence the coupling between $\varepsilon$ and $s$ is temporarily lost during some iterations, which allows more freedom.
  • the linear constraints have no curvature contribution to the Lagrangian Hessian.

@franckgaga

franckgaga commented Jun 22, 2026

Copy link
Copy Markdown
Member Author

Okay thanks for the tips !

Some progress here: changing the weight $C$ of the slack $\epsilon$ from 1e5 to 1e4 solve the issue here. And based on this new weight, the performances are slightly improved on this branch compared to main. My interpretation is the problem is badly scaled (which is kind of inevitable with this approach to constraint softening) and it affects the robustness of the builtin LBFGS solver. Reducing $C$ make it a bit less "ill-conditioned".

I will run the benchmark with this new Cwt value (note that it only affects the "Custom Constraint" entries, that is, the worst results right now).

edit : to answer your question, yes $\epsilon$ is initialized at 0, that is exactly on the bound.

This is necessary if there is a change on the state operating point, for the hard terminal constraints and `MultipleShooting` transcription.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants