-
Notifications
You must be signed in to change notification settings - Fork 80
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
Multi-objective optimization #294
Comments
Try the master version of Gurobi.jl with (v1.3) pkg> add Gurobi#master to have this fix: #291 |
Thanks, this got me a little closer, but I'm still not able to make the JuMP optimize!() call work. Below is my latest code iteration, and the error I'm now receiving. Any help is appreciated. Using JuMP, Gurobi
const MOI = JuMP.MathOptInterface
struct PrintLevel <: MOI.AbstractOptimizerAttribute end
function MOI.set(model::Gurobi.Optimizer, ::PrintLevel, level::Int)
# ... set the print level ...
Gurobi.set_intattr!(model, "PrintLevel", level)
end
struct NumberOfObjective <: MOI.AbstractModelAttribute
end
function MOI.set(model::Gurobi.Optimizer, ::NumberOfObjective, n::Integer)
Gurobi.set_intattr!(model, "NumObj", n)
end
function MOI.get(model::Gurobi.Optimizer, ::NumberOfObjective)
Gurobi.get_intattr(model, "NumObj")
end
struct MultiObjectiveFunction <: MOI.AbstractModelAttribute
id::Int
end
function MOI.set(model::Gurobi.Optimizer, attr::MultiObjectiveFunction, f::MOI.ScalarAffineFunction)
num_vars = length(model.variable_info)
obj = zeros(Float64, num_vars)
for term in f.terms
column = Gurobi._info(model, term.variable_index).column
obj[column] += term.coefficient
end
# This update is needed because we might have added some variables.
Gurobi._update_if_necessary(model)
i0 = Gurobi.get_int_param(model.inner, "ObjNumber")
Gurobi.set_int_param!(model.inner, "ObjNumber", attr.id)
Gurobi.set_dblattrarray!(model.inner, "ObjN", 1, num_vars, obj)
Gurobi.set_dblattr!(model.inner, "ObjNCon", f.constant)
Gurobi.set_int_param!(model.inner, "ObjNumber", i0)
Gurobi._require_update(model)
end
struct MultiObjectivePriority <: MOI.AbstractModelAttribute
id::Int
end
function MOI.set(model::Gurobi.Optimizer, attr::MultiObjectivePriority, priority::Int)
i0 = Gurobi.get_int_param(model.inner, "ObjNumber")
temp = Gurobi.get_int_param(model.inner, "ObjNPriority")
Gurobi.set_int_param!(model.inner, "ObjNumber", attr.id)
Gurobi.set_intattr!(model.inner, "ObjNPriority", priority)
temp1 = Gurobi.get_int_param(model.inner, "ObjNumber")
Gurobi.set_int_param!(model.inner, "ObjNumber", i0)
end
struct MultiObjectiveWeight <: MOI.AbstractModelAttribute
id::Int
end
function MOI.set(model::Gurobi.Optimizer, attr::MultiObjectiveWeight, weight::Float64)
i0 = Gurobi.get_int_param(model.inner, "ObjNumber")
Gurobi.set_int_param!(model.inner, "ObjNumber", attr.id)
Gurobi.set_dblattr!(model.inner, "ObjNWeight", weight)
Gurobi.set_int_param!(model.inner, "ObjNumber", i0)
end Example using above code w/ JuMP: using JuMP
model = Model(with_optimizer(Gurobi.Optimizer))
@variable(model, x)
@variable(model, y)
MOI.set(model, NumberOfObjective(), 2)
MOI.set(model, MultiObjectivePriority(1), 1)
MOI.set(model, MultiObjectivePriority(2), 2)
#MOI.set(model, MultiObjectiveWeight(0), 1.0)
#MOI.set(model, MultiObjectiveWeight(1), 1.0)
MOI.set(model, MultiObjectiveFunction(1), moi_function(x + y))
MOI.set(model, MultiObjectiveFunction(2), moi_function(2x - y))
JuMP.optimize!(model) Error output:
|
function MOI.set(model::Gurobi.Optimizer, ::NumberOfObjective, n::Integer)
Gurobi.set_intattr!(model, "NumObj", n)
end
# needs to be
function MOI.set(model::Gurobi.Optimizer, ::NumberOfObjective, n::Integer)
Gurobi.set_intattr!(model.inner, "NumObj", n)
end There are a few other occurrences as well. |
Fixed the "model.inner" issue, and the optimizer now does not recognize that this is a multi-objective problem (error below). I checked the Gurobi NumObj attribute, and it is set properly (i.e., to 2), and according to the Gurobi documentation, this is supposed to enough to make the model multi-objective.
|
Okay so the issue is that by default, JuMP stores a cache of the model before passing it to Gurobi (this is the
The issue is that the CachingOptimizer doesn't remember the order of operations. You have two options:
model = Model(Gurobi.Optimizer)
@variable(model, x)
optimize!(model)
# set multi-objectives
optimize!(model) cc @blegat. Thoughts on CachingOptimizer remembering an order of operations? |
@odow Thoughts on CachingOptimizer remembering an order of operations? We could make the UniversalFallback use OrderedDicts but we probably don't want to inforce the order on |
Neither option appears to fix the issue. julia> m = JuMP.direct_model(Gurobi.Optimizer())
Academic license - for non-commercial use only
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: DIRECT
Solver name: Gurobi
julia> MOI.set(m, NumberOfObjective(), 2)
julia> print("Number of objectives = $(MOI.get(m, NumberOfObjective()))")
Number of objectives = 1
julia> MOI.set(m, MultiObjectivePriority(1), 1)
ERROR: Gurobi.GurobiError(10008, "It isn't a multi-objective model")
Stacktrace:
[1] get_intattr(::Gurobi.Model, ::String) at /Users/heileman/.julia/packages/Gurobi/EhH9J/src/grb_attrs.jl:16
[2] set(::Gurobi.Optimizer, ::MultiObjectivePriority, ::Int64) at ./REPL[15]:3
[3] set(::Model, ::MultiObjectivePriority, ::Int64) at /Users/heileman/.julia/packages/JuMP/MsUSY/src/JuMP.jl:679
[4] top-level scope at REPL[30]:1 The second option, i.e., calling optimize! before setting the multiple objectives, produces the following error using the previously provided code: julia> JuMP.optimize!(model)
Academic license - for non-commercial use only
Gurobi Optimizer version 9.0.1 build v9.0.1rc0 (mac64)
Optimize a model with 0 rows, 2 columns and 0 nonzeros
Model fingerprint: 0x8dfcd1e3
Coefficient statistics:
Matrix range [0e+00, 0e+00]
Objective range [0e+00, 0e+00]
Bounds range [0e+00, 0e+00]
RHS range [0e+00, 0e+00]
Presolve removed 0 rows and 2 columns
Presolve time: 0.00s
Presolve: All rows and columns removed
Iteration Objective Primal Inf. Dual Inf. Time
0 0.0000000e+00 0.000000e+00 3.000000e-06 0s
Solved in 0 iterations and 0.00 seconds
Optimal objective 0.000000000e+00
julia> MOI.set(model, NumberOfObjective(), 2)
julia> MOI.set(model, MultiObjectivePriority(1), 1)
ERROR: Gurobi.GurobiError(10008, "It isn't a multi-objective model")
Stacktrace:
[1] get_intattr(::Gurobi.Model, ::String) at /Users/heileman/.julia/packages/Gurobi/EhH9J/src/grb_attrs.jl:16
[2] set(::Gurobi.Optimizer, ::MultiObjectivePriority, ::Int64) at ./REPL[15]:3
[3] set(::MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, ::MultiObjectivePriority, ::Int64) at /Users/heileman/.julia/packages/MathOptInterface/C1XBe/src/Bridges/bridge_optimizer.jl:593
[4] set(::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, ::MultiObjectivePriority, ::Int64) at /Users/heileman/.julia/packages/MathOptInterface/C1XBe/src/Utilities/cachingoptimizer.jl:425
[5] set(::Model, ::MultiObjectivePriority, ::Int64) at /Users/heileman/.julia/packages/JuMP/MsUSY/src/JuMP.jl:679
[6] top-level scope at REPL[26]:1 in both cases, Gurobi does not recognize that the model is multi-objective |
Greg's Challenge I will award a prize of $2^8 (in the form of an Amazon gift certificate) to the first person who can demonstrate a working example of the use of mulit-objective optimization using Gurobi.jl through JuMP.jl. To claim this prize, one must provide working code (using the latest versions of Gurobi.jl and JuMP.jl), and associated output for:
Additional constraints:
Good luck! |
I have it working. Pull request incoming. |
@heileman, no need for the $2^8, but feel free to donate to JuMP! You can do so here: https://numfocus.org/project/jump We're part of NumFOCUS, a US non-profit that supports scientific computing. |
Winner, winner, chicken dinner! I will make a $256 donation this evening. |
I believe I'm close to having a working example of multi-objective optimization using JuMP/Gurobi, but I'm getting error when using JuMP.optimize!(), and am wondering if this is a JuMP bug? It seems related to issue #291.
Here's the code, based on suggestions in issue #264:
Example using above code w/ JuMP:
Error output:
The text was updated successfully, but these errors were encountered: