Ipopt does NOT memorize a best solution found so far

The title is expounded through optimizing this function

function g(x) return sin(7 * x) + 1.2 * cos(4.7 * x) + 1.3 * x end

which can be visualized via, e.g.

using CairoMakie
f = Figure();
Axis(f[1, 1]);
xs = LinRange(0, 9, 500);
lines!(xs, g.(xs))
f

We verify the title through the following code

import JuMP, Gurobi, Ipopt
# 1️⃣ with Gurobi
NLP = JuMP.Model(() -> Gurobi.Optimizer())
JuMP.@variable(NLP, 0 <= x <= 9)
JuMP.@objective(NLP, Min, g(x))
JuMP.optimize!(NLP)
JuMP.assert_is_solved_and_feasible(NLP; allow_local = false)
x1 = JuMP.value(x) # 0.6553872496146986 (optimal solution)
g(x1) # -1.3379824147669828 (optimal obj value)
x3 = JuMP.value(x; result = 3) # 4.358805270131485 (suboptimal solution)
g(x3) # 4.801279216797521 (suboptimal obj value)
# 2️⃣ with Ipopt
NLP = JuMP.Model(Ipopt.Optimizer)
JuMP.@variable(NLP, 0 <= x <= 9)
JuMP.@objective(NLP, Min, sin(7 * x) + 1.2 * cos(4.7 * x) + 1.3 * x) # 🍅 i.e. Minimize g(x)
JuMP.set_start_value(x, x1)
JuMP.optimize!(NLP)
JuMP.assert_is_solved_and_feasible(NLP)
r1 = JuMP.value(x) # 0.6542659763135713
g(r1) # -1.3380295865474872
# proceed with another start value
JuMP.set_start_value(x, x3)
JuMP.optimize!(NLP)
JuMP.assert_is_solved_and_feasible(NLP)
r3 = JuMP.value(x) # 4.358805269704956
g(r3) # 4.80127921679752
# remark: the second solve gives an inferior solution
# This Ipopt's behavior is supposed to never occur with Gurobi

(Additional question: will it be all right to directly write g(x) in the :tomato: line, as it was look like in the Gurobi’s code?)

Same answer as Ipopt's "local" optimum can be very substandard - #5 by odow

Additional question: will it be all right to directly write g(x) in the :tomato: line, as it was look like in the Gurobi’s code?

Yes. JuMP uses function tracing to compute the underlying expression.

1 Like