Using `bboptimize` with a function containing `JuMP` calls

Hi everyone,

I am trying blackbox optimization with a function that contains JuMP functions. So, this is like a nested optimization where the “inner problem” is evaluated using JuMP functions and the “outer problem” is optimized using bboptimize. However, I am getting an error (see below).

To illustrate what I am doing, here is a minimal example.

  • I define a function estimate_objective that is parameterized by c. This function tries to solve a well-behaved optimization problem.
  • Then, I want to find the value of c that gives the smallest objective through bboptimize.

An obvious solution is to make c a variable in the JuMP call. But I do not want to do this in my problem because when it is fixed, the problem I have is convex (the problem I want to solve is more complicated, the function below is just an illustration). Solving the “inner problem” with a fixed c is also very fast.

using BlackBoxOptim, JuMP, NLopt


function estimate_objective(c)
  model = Model(NLopt.Optimizer)
  set_optimizer_attribute(model, "algorithm", :LD_MMA)

  # Min x^2 + c s.t. x >= c
  @variable(model, x .>= c)
  @objective(model, Min, x^2 .+ c)

  JuMP.optimize!(model)

  return objective_value(model)
end

bboptimize(estimate_objective; SearchRange = [(-5.0, 5.0)])

The error I get is:

ERROR: At REPL[387]:7: `@variable(model, x[1:1] .>= c)`: Passing arrays as variable bounds without indexing them is not supported.

Instead of:
@variable(model, x[1:2] >= lb)

use

@variable(model, x[i=1:2] >= lb[i])

or
@variable(model, x[1:2])
set_lower_bound.(x, lb)

Any thoughts are very much appreciated!! I am also open to using other packages. Thank you!!

1 Like

The input c to the function estimate_objective is a vector. JuMP does not support broadcasting lower bounds.

You need

julia> using BlackBoxOptim, JuMP, NLopt

julia> function estimate_objective(c)
           c_scalar = only(c)
           model = Model(NLopt.Optimizer)
           set_optimizer_attribute(model, "algorithm", :LD_MMA)
           @variable(model, x >= c_scalar)
           @objective(model, Min, x^2 + c_scalar)
           JuMP.optimize!(model)
           return objective_value(model)
       end
estimate_objective (generic function with 1 method)

julia> bboptimize(estimate_objective; SearchRange = [(-5.0, 5.0)])
1 Like

Thanks, this works great!!

1 Like