Hello,
I want to provide analytic expressions for the objective function, the gradient and the Hessian of the problem using a single function instead of three different functions.
I am using Ipopt via the C wrapper in here.
I would like to do so in order to reuse common calculations. In the MWE I show there are no common calculations, but the goal is to have a single function that can perform the three things depending on what is needed in each iteration (some iterations do not calculate the Hessian, for example).
# HS071
# min x * y * z^2
# st x + y + z = 2
# Start at (0.0, 0.0, 0.0)
# End at (1.0, 1.00, 0.00)
using Ipopt
n = 3 # this global is used by some functions
x_L = -Inf*ones(n)
x_U = +Inf*ones(n)
m = 1
g_L = [2.0]
g_U = [2.0]
function eval_f(x)
return x[1] * x[2] * (x[3]^2)
end
function eval_g(x, g)
g[1] = x[1] + x[2] + x[3]
return
end
function eval_grad_f(x, grad_f)
grad_f[1] = x[2] * (x[3]^2)
grad_f[2] = x[1] * (x[3]^2)
grad_f[3] = 2 * x[1] * x[2] * x[3]
return
end
function eval_jac_g(x, mode, rows, cols, values)
if mode == :Structure
# Constraint (row) 1
rows[1] = 1; cols[1] = 1
rows[2] = 1; cols[2] = 2
rows[3] = 1; cols[3] = 3
else
# Constraint (row) 1
values[1] = 1.0 # 1,1
values[2] = 1.0 # 1,2
values[3] = 1.0 # 1,3
end
return
end
function eval_h(x, mode, rows, cols, obj_factor, lambda, values)
if mode == :Structure
# Symmetric matrix, fill the lower left triangle only
idx = 1
for row = 1:n
for col = 1:row
rows[idx] = row
cols[idx] = col
idx += 1
end
end
else
# Again, only lower left triangle
# Objective
values[1] = 0 # 1,1
values[2] = obj_factor * (x[3]^2) # 2,1
values[3] = 0 # 2,2
values[4] = obj_factor * (2 * x[2] * x[3]) # 3,1
values[5] = obj_factor * (2 * x[1] * x[3]) # 3,2
values[6] = obj_factor * (2 * x[1] * x[2]) # 3,3
end
end
prob = createProblem(
n,
x_L,
x_U,
m,
g_L,
g_U,
3,
6,
eval_f,
eval_g,
eval_grad_f,
eval_jac_g,
eval_h,
)
# Set starting solution
prob.x = [0.0, 0.0, 0.0]
# Solve
status = solveProblem(prob)
println(Ipopt.ApplicationReturnStatus[status])
println(prob.x)
println(prob.obj_val)
Can the code above be modified to use only one function that spits out what the solver needs in each iteration? Also, can this function be written to avoid using globals like n
?
Thank you all.