Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get_curr_violations and violations computed based on eval_g and bounds do not agree #603

Closed
DanielDoehring opened this issue Aug 29, 2022 · 2 comments

Comments

@DanielDoehring
Copy link
Contributor

I observed that in my application the violations as computed e.g. by get_curr_violations do not match those obtained "manually" when calling eval_g and subtracting / adding the upper / lower bound, respectively.

To check this, I resort to the hs071_cpp example and added these lines in the intermediate_callback function:

   std::cout.precision(std::numeric_limits<Number>::max_digits10);

   std::cout << std::endl << "Violations from get_curr_violations: \t" 
             << constraint_violation[0] << " " << constraint_violation[1] << std::endl;

   eval_g(4, x, true, 2, constraint_violation); // Compute violations based on current iterate x
   std::cout << "Violations from eval_g: \t \t" 
             << 25. - constraint_violation[0] << " " << constraint_violation[1] -40. << std::endl << std::endl;

To keep the output clean, I out-commented the lines 414-455.

Furthermore, I added in finalize_solution the lines

   std::cout << std::endl << "Final violations of the constraints:" << std::endl;
   std::cout << "g(" << 0 << ") = " << 25. - g[0] << std::endl;
   std::cout << "g(" << 1 << ") = " << g[1] - 40. << std::endl;

This gives the output:


******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
 Ipopt is released as open source code under the Eclipse Public License (EPL).
         For more information visit https://github.com/coin-or/Ipopt
******************************************************************************

This is Ipopt version 3.14.10, running with linear solver MUMPS 5.5.0.

Number of nonzeros in equality constraint Jacobian...:        4
Number of nonzeros in inequality constraint Jacobian.:        4
Number of nonzeros in Lagrangian Hessian.............:       10

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


Violations from get_curr_violations:    0 11.243400939696002
Violations from eval_g:                 -0.096092162945630832 11.243400939696002

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  1.6109693e+01 1.12e+01 5.28e-01   0.0 0.00e+00    -  0.00e+00 0.00e+00   0

Violations from get_curr_violations:    0 0.74894595468575176
Violations from eval_g:                 -0.20860234632937491 0.74894595468575176

   1  1.7410406e+01 7.49e-01 2.25e+01  -0.3 7.97e-01    -  3.19e-01 1.00e+00f  1

Violations from get_curr_violations:    0 0.0075231790452647829
Violations from eval_g:                 -1.0331199484597278 0.0075231790452647829

   2  1.8001613e+01 7.52e-03 4.96e+00  -0.3 5.60e-02   2.0 9.97e-01 1.00e+00h  1

Violations from get_curr_violations:    0.03816758077581639 0.039953432860642124
Violations from eval_g:                 0.038167830775815759 0.039953432860642124

   3  1.7199482e+01 4.00e-02 4.24e-01  -1.0 9.91e-01    -  9.98e-01 1.00e+00f  1

Violations from get_curr_violations:    0.13720718679095611 0.15938033810270724
Violations from eval_g:                 0.13720743679095548 0.15938033810270724

   4  1.6940955e+01 1.59e-01 4.58e-02  -1.4 2.88e-01    -  9.66e-01 1.00e+00h  1

Violations from get_curr_violations:    0.021573856298374494 0.0061694408560200031
Violations from eval_g:                 0.021574106298373863 0.0061694408560200031

   5  1.7003411e+01 2.16e-02 8.42e-03  -2.9 7.03e-02    -  9.68e-01 1.00e+00h  1

Violations from get_curr_violations:    0.00020258544763862574 8.0748108949535435e-05
Violations from eval_g:                 0.00020283544763799455 8.0748108949535435e-05

   6  1.7013974e+01 2.03e-04 8.65e-05  -4.5 6.22e-03    -  1.00e+00 1.00e+00h  1

Violations from get_curr_violations:    2.7626678544834249e-07 7.1997845907390001e-08
Violations from eval_g:                 5.2626678481715317e-07 7.1997845907390001e-08

   7  1.7014017e+01 2.76e-07 2.18e-07 -10.3 1.43e-04    -  9.99e-01 1.00e+00h  1

Number of Iterations....: 7

                                   (scaled)                 (unscaled)
Objective...............:   1.7014017031783709e+01    1.7014017031783709e+01
Dual infeasibility......:   2.1824331116938792e-07    2.1824331116938792e-07
Constraint violation....:   2.7626678544834249e-07    2.7626678544834249e-07
Variable bound violation:   0.0000000000000000e+00    0.0000000000000000e+00
Complementarity.........:   1.0473361552932239e-07    1.0473361552932239e-07
Overall NLP error.......:   2.7626678544834249e-07    2.7626678544834249e-07


Number of objective function evaluations             = 8
Number of objective gradient evaluations             = 8
Number of equality constraint evaluations            = 8
Number of inequality constraint evaluations          = 8
Number of equality constraint Jacobian evaluations   = 8
Number of inequality constraint Jacobian evaluations = 8
Number of Lagrangian Hessian evaluations             = 7
Total seconds in IPOPT                               = 0.005

EXIT: Optimal Solution Found.


Solution of the primal variables, x
x[0] = 1.0000000412793351
x[1] = 4.7429996061160633
x[2] = 3.8211500589803418
x[3] = 1.3794081892523982


Solution of the bound multipliers, z_L and z_U
z_L[0] = 1.0878716767473644
z_L[1] = 4.6358194761218199e-09
z_L[2] = 9.0874474076569869e-09
z_L[3] = 8.5559549728650972e-09
z_U[0] = 4.470027046608337e-09
z_U[1] = 4.0752309197030412e-07
z_U[2] = 1.1897911561120774e-08
z_U[3] = 6.398749117664807e-09


Objective value
f(x*) = 17.014017031783709

Final value of the constraints:
g(0) = 24.999999473733215
g(1) = 40.000000071997846

Final violations of the constraints:
g(0) = 5.2626678481715317e-07
g(1) = 7.1997845907390001e-08


*** The problem solved!

As you can see, the violations differ sometimes by more than machine epsilon and most importantly, the final solution does not bear the same violations as the iterate at which the optimizer stops!

As printed, I am using Ipopt 3.14.10 and MUMPS 5.5.0 and compiled with
g++ -std=c++11 -O0 -g -Wall -Wextra -Wpedantic `PKG_CONFIG_PATH=/usr/local/lib/pkgconfig: pkg-config --cflags ipopt` -c -o hs071_main.o hs071_main.cpp
g++ -std=c++11 -O0 -g -Wall -Wextra -Wpedantic -o hs071_nlp.exe hs071_nlp.o hs071_main.o `PKG_CONFIG_PATH=/usr/local/lib/pkgconfig: pkg-config --libs ipopt`

Is this reproducable?

@svigerske
Copy link
Member

The differences are caused by the relaxation of constraint sides that Ipopt applies (https://coin-or.github.io/Ipopt/OPTIONS.html#OPT_bound_relax_factor). If you set bound_relax_factor to 0, then you'll get the same values.

For the violation of variable bounds, it uses the original (nonrelaxed) bounds, though. So it would probably be nicer to get this also for the constraint violation. Currently the original constraint sides aren't stored, so this would need to be added first.

The violation you print in finalize_solution seems to correspond to the one you print for "Violations from eval_g" in intermediate_callback.

@DanielDoehring
Copy link
Contributor Author

DanielDoehring commented Aug 30, 2022

Ah okay, I thought that the relaxation is only active (internally) at the optimization stage and not at constraint evaluation.
Thanks!

Yes, I phrased that poorly - what I meant is that the optimizer stops based on the relaxed violations, but the true values of the solution are different from that.

svigerske added a commit that referenced this issue Aug 30, 2022
- for bounds violations, original bounds were already used
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants