Question on allowing user to specify the optimization sense

I have a small package in which I solve an optimization model. The sense of the objective function is to be specified by the user. Now, I export MAX_SENSE and MIN_SENSE for the user to use them. A small example:

module MyPkg

using JuMP
using Gurobi

export solve, MAX_SENSE, MIN_SENSE

function solve(sense::MOI.OptimizationSense)
    model = Model(Gurobi.Optimizer)
    @variable(model, x[1:2] >= 0)
    @constraint(model, sum(x) <= 2)
    @objective(model, sense, 2*x[1]+x[2])
    
    optimize!(model)
    if termination_status == MOI.OPTIMAL 
        return objective_valule(model)
    else
        error("Not solved to optimality")
    end
end

end

I have a couple of questions here:

  1. Is there another (more safe, neat, and probably more standard) way to allow users to allow specifying the objective without exporting MIN_SENSE and MAX_SENSE. I want to keep the exported items to a minimum.
  2. I haven’t explicitly added the following lines to my package:
using MathOptInterface
const MOI = MathOptInterface

However, I could still use MOI.OptimizationSense and MOI.OPTIMAL inside my package functions without any issue. So my question is, why is it working exactly? Also, I have seen some packages that actually add the lines mentioned above, so when do I actually need to add the using MathOptInterface; const MOI = MathOptInterface lines to my package?

  1. How is MOI.ObjectiveSense related to the MOI.OptimizationSense? I can find the documentation for the former here, but nothing on the latter. Any reference or explanation about the difference between the two would be appreciated.

Thanks!

Use an argument like

function solve(; maximize::Bool)
    sense = maximize ? MOI.MAX_SENSE : MOI.MIN_SENSE
    # ...
end

solve(; maximize = true)
  1. I haven’t explicitly added the following lines to my package:

JuMP exports the MOI constant, so using JuMP pulls MOI into scope.

  1. How is MOI.ObjectiveSense related to the MOI.OptimizationSense ?

ObjectiveSense is the attribute, as in MOI.ObjectiveSense(). OptimizationSense is the enum, as in MOI.MIN_SENSE.

help?> MOI.ObjectiveSense
  ObjectiveSense()

  A model attribute for the objective sense of the objective function, which must be an
  OptimizationSense: MIN_SENSE, MAX_SENSE, or FEASIBILITY_SENSE. The default is FEASIBILITY_SENSE.

  Interaction with ObjectiveFunction
  ====================================

  Setting the sense to FEASIBILITY_SENSE unsets the ObjectiveFunction attribute. That is, if you
  first set ObjectiveFunction and then set ObjectiveSense to be FEASIBILITY_SENSE, no objective
  function will be passed to the solver.

  In addition, some reformulations of ObjectiveFunction via bridges rely on the value of
  ObjectiveSense. Therefore, you should set ObjectiveSense before setting ObjectiveFunction.

julia> MOI.OptimizationSense
Enum MathOptInterface.OptimizationSense:
MIN_SENSE = 0
MAX_SENSE = 1
FEASIBILITY_SENSE = 2
1 Like

Amazing. That makes it much more clear. Thanks!

1 Like