Skip to content

Commit 5f5d2e5

Browse files
committed
WIP: begin support for vector-valued objective functions
1 parent 3ee3e37 commit 5f5d2e5

File tree

5 files changed

+58
-1
lines changed

5 files changed

+58
-1
lines changed

Project.toml

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ version = "0.11.5"
77
LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
88
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
99
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
10+
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
1011

1112
[compat]
1213
MathOptInterface = "1.7"

src/MOI_wrapper/MOI_multi_objective.jl

+18
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,21 @@ function MOI.get(model::Gurobi.Optimizer, attr::MultiObjectiveValue)
126126
_check_ret(model, ret)
127127
return val[]
128128
end
129+
130+
function MOI.set(
131+
model::Optimizer,
132+
::MOI.ObjectiveFunction{F},
133+
f::F,
134+
) where {F<:MOI.VectorAffineFunction{Float64}}
135+
for (i, fi) in enumerate(MOI.Utilities.eachscalar(f))
136+
MOI.set(model, MultiObjectiveFunction(i), fi)
137+
end
138+
return
139+
end
140+
141+
function MOI.supports(
142+
model::Optimizer,
143+
::MOI.ObjectiveFunction{MOI.VectorAffineFunction{Float64}},
144+
)
145+
return true
146+
end

src/MOI_wrapper/MOI_wrapper.jl

+4
Original file line numberDiff line numberDiff line change
@@ -3091,6 +3091,10 @@ function MOI.get(model::Optimizer, attr::MOI.ObjectiveValue)
30913091
attr.result_index - 1,
30923092
)
30933093
end
3094+
N = MOI.get(model, NumberOfObjectives())
3095+
if N > 1
3096+
return [MOI.get(model, MultiObjectiveValue(i)) for i in 1:N]
3097+
end
30943098
valueP = Ref{Cdouble}()
30953099
key = attr.result_index == 1 ? "ObjVal" : "PoolObjVal"
30963100
ret = GRBgetdblattr(model, key, valueP)

test/MOI/MOI_multiobjective.jl

+32-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ c4: y >= 0.25
5555
@test MOI.get(model, Gurobi.MultiObjectivePriority(2)) == 0
5656

5757
MOI.optimize!(model)
58-
@test MOI.get(model, MOI.ObjectiveValue()) 1.5
58+
@test MOI.get(model, MOI.ObjectiveValue()) [1.5, 2.0]
5959
@test MOI.get(model, MOI.VariablePrimal(), x) 0.5
6060
@test MOI.get(model, MOI.VariablePrimal(), y) 0.5
6161

@@ -101,6 +101,37 @@ c4: y >= 0.25
101101
@test MOI.get(model, Gurobi.MultiObjectiveValue(2)) BFS[3].f2
102102
end
103103

104+
function test_example_biobjective_knapsack()
105+
p1 = [77.0, 94, 71, 63, 96, 82, 85, 75, 72, 91, 99, 63, 84, 87, 79, 94, 90]
106+
p2 = [65.0, 90, 90, 77, 95, 84, 70, 94, 66, 92, 74, 97, 60, 60, 65, 97, 93]
107+
w = [80.0, 87, 68, 72, 66, 77, 99, 85, 70, 93, 98, 72, 100, 89, 67, 86, 91]
108+
model = Gurobi.Optimizer()
109+
x = MOI.add_variables(model, length(w))
110+
MOI.add_constraint.(model, x, MOI.ZeroOne())
111+
MOI.add_constraint(model, w' * x, MOI.LessThan(900.0))
112+
obj_f = MOI.Utilities.operate(vcat, Float64, p1' * x, p2' * x)
113+
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
114+
MOI.set(model, MOI.ObjectiveFunction{typeof(obj_f)}(), obj_f)
115+
MOI.optimize!(model)
116+
results = Dict(
117+
[955.0, 906.0] => [2, 3, 5, 6, 9, 10, 11, 14, 15, 16, 17],
118+
[948.0, 939.0] => [1, 2, 3, 5, 6, 8, 10, 11, 15, 16, 17],
119+
[934.0, 971.0] => [2, 3, 5, 6, 8, 10, 11, 12, 15, 16, 17],
120+
[918.0, 983.0] => [2, 3, 4, 5, 6, 8, 10, 11, 12, 16, 17],
121+
)
122+
found_non_dominated_point = false
123+
for i in 1:MOI.get(model, MOI.ResultCount())
124+
X = findall(elt -> elt > 0.9, MOI.get.(model, MOI.VariablePrimal(i), x))
125+
Y = MOI.get(model, MOI.ObjectiveValue(i))
126+
if haskey(results, Y)
127+
@test results[Y] == X
128+
found_non_dominated_point = true
129+
end
130+
end
131+
@test found_non_dominated_point
132+
return
133+
end
134+
104135
end
105136

106137
TestMultiobjective.runtests()

test/runtests.jl

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
# Use of this source code is governed by an MIT-style license that can be found
55
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
66

7+
import Pkg
8+
Pkg.pkg"add MathOptInterface#od/vector-optimization"
9+
710
using Gurobi
811
using Test
912

0 commit comments

Comments
 (0)