Skip to content

Commit 3b1c659

Browse files
committed
WIP: begin support for vector-valued objective functions
This is a re-hash of #968 The last PR lost steam because of the discussion in jump-dev/JuMP.jl#2099 My sense is that this is still the right API approach at the MOI-level, but that it's the wrong approach at the JuMP level. I'm working on a PR to JuMP, so let's hold off comments until things are working fully and we can discuss the full API, rather than the pros and cons of treating multi-criteria as vector optimization. I have a proof-of-concept solver at https://github.com/odow/MOO.jl and I'll also update Gurobi.jl to support the new API.
1 parent 40b81c5 commit 3b1c659

File tree

3 files changed

+295
-32
lines changed

3 files changed

+295
-32
lines changed

src/Test/test_multiobjective.jl

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# Copyright (c) 2017: Miles Lubin and contributors
2+
#
3+
# Use of this source code is governed by an MIT-style license that can be found
4+
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
5+
6+
function test_multiobjective_vector_of_variables(
7+
model::MOI.ModelLike,
8+
::Config{T},
9+
) where {T}
10+
F = MOI.VectorOfVariables
11+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
12+
x = MOI.add_variables(model, 2)
13+
f = MOI.VectorOfVariables(x)
14+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
15+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
16+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
17+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) == f
18+
return
19+
end
20+
21+
function test_multiobjective_vector_of_variables_delete(
22+
model::MOI.ModelLike,
23+
::Config{T},
24+
) where {T}
25+
F = MOI.VectorOfVariables
26+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
27+
x = MOI.add_variables(model, 2)
28+
f = MOI.VectorOfVariables(x)
29+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
30+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
31+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
32+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) == f
33+
MOI.delete(model, x[1])
34+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) ==
35+
MOI.VectorOfVariables([x[2]])
36+
return
37+
end
38+
39+
function test_multiobjective_vector_of_variables_delete_all(
40+
model::MOI.ModelLike,
41+
::Config{T},
42+
) where {T}
43+
F = MOI.VectorOfVariables
44+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
45+
x = MOI.add_variables(model, 2)
46+
f = MOI.VectorOfVariables(x)
47+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
48+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
49+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
50+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) == f
51+
MOI.delete(model, x[1])
52+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) ==
53+
MOI.VectorOfVariables([x[2]])
54+
MOI.delete(model, x[2])
55+
# ObjectiveFunction no longer set because we deleted all the variables!
56+
attributes = MOI.get(model, MOI.ListOfModelAttributesSet())
57+
@test !(MOI.ObjectiveFunction{F}() in attributes)
58+
return
59+
end
60+
61+
function test_multiobjective_vector_of_variables_delete_vector(
62+
model::MOI.ModelLike,
63+
::Config{T},
64+
) where {T}
65+
F = MOI.VectorOfVariables
66+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
67+
x = MOI.add_variables(model, 2)
68+
f = MOI.VectorOfVariables(x)
69+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
70+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
71+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
72+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) == f
73+
attributes = MOI.get(model, MOI.ListOfModelAttributesSet())
74+
@test MOI.ObjectiveFunction{F}() in attributes
75+
MOI.delete(model, x)
76+
# ObjectiveFunction no longer set because we deleted all the variables!
77+
attributes = MOI.get(model, MOI.ListOfModelAttributesSet())
78+
@test !(MOI.ObjectiveFunction{F}() in attributes)
79+
return
80+
end
81+
82+
function test_multiobjective_vector_affine_function(
83+
model::MOI.ModelLike,
84+
::Config{T},
85+
) where {T}
86+
F = MOI.VectorAffineFunction{T}
87+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
88+
x = MOI.add_variables(model, 2)
89+
f = MOI.Utilities.operate(vcat, T, T(1) * x[1], T(2) * x[2] + T(3))
90+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
91+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
92+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
93+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) f
94+
return
95+
end
96+
97+
function test_multiobjective_vector_affine_function_delete(
98+
model::MOI.ModelLike,
99+
::Config{T},
100+
) where {T}
101+
F = MOI.VectorAffineFunction{T}
102+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
103+
x = MOI.add_variables(model, 2)
104+
f = MOI.Utilities.operate(vcat, T, T(1) * x[1], T(2) * x[2] + T(3))
105+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
106+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
107+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
108+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) f
109+
MOI.delete(model, x[1])
110+
@test MOI.get(model, MOI.ObjectiveFunction{F}())
111+
MOI.Utilities.operate(vcat, T, T(0), T(2) * x[2] + T(3))
112+
return
113+
end
114+
115+
function test_multiobjective_vector_affine_function_delete_vector(
116+
model::MOI.ModelLike,
117+
::Config{T},
118+
) where {T}
119+
F = MOI.VectorAffineFunction{T}
120+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
121+
x = MOI.add_variables(model, 2)
122+
f = MOI.Utilities.operate(vcat, T, T(1) * x[1], T(2) * x[2] + T(3))
123+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
124+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
125+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
126+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) f
127+
MOI.delete(model, x)
128+
@test MOI.get(model, MOI.ObjectiveFunction{F}())
129+
MOI.VectorAffineFunction{T}(MOI.VectorAffieTerm{T}[], T[0, 3])
130+
return
131+
end
132+
133+
function test_multiobjective_vector_quadratic_function(
134+
model::MOI.ModelLike,
135+
::Config{T},
136+
) where {T}
137+
F = MOI.VectorQuadraticFunction{T}
138+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
139+
x = MOI.add_variables(model, 2)
140+
f = MOI.Utilities.operate(vcat, T, (T(1) .* x .* x)...)
141+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
142+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
143+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
144+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) f
145+
return
146+
end
147+
148+
function test_multiobjective_vector_quadratic_function_delete(
149+
model::MOI.ModelLike,
150+
::Config{T},
151+
) where {T}
152+
F = MOI.VectorQuadraticFunction{T}
153+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
154+
x = MOI.add_variables(model, 2)
155+
f = MOI.Utilities.operate(vcat, T, (T(1) .* x .* x)...)
156+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
157+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
158+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
159+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) f
160+
MOI.delete(model, x[1])
161+
@test MOI.get(model, MOI.ObjectiveFunction{F}())
162+
MOI.Utilities.operate(vcat, T, T(0), T(1) * x[2] * x[2])
163+
return
164+
end
165+
166+
function test_multiobjective_vector_quadratic_function_delete_vector(
167+
model::MOI.ModelLike,
168+
::Config{T},
169+
) where {T}
170+
F = MOI.VectorQuadraticFunction{T}
171+
@requires MOI.supports(model, MOI.ObjectiveFunction{F}())
172+
x = MOI.add_variables(model, 2)
173+
f = MOI.Utilities.operate(vcat, T, (T(1) .* x .* x)...)
174+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
175+
MOI.set(model, MOI.ObjectiveFunction{F}(), f)
176+
@test MOI.get(model, MOI.ObjectiveFunctionType()) == F
177+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) f
178+
MOI.delete(model, x)
179+
new_f = MOI.VectorQuadraticFunction{T}(
180+
MOI.VectorQuadraticTerm{T}[],
181+
MOI.VectorAffineTerm{T}[],
182+
zeros(T, 2)
183+
)
184+
@test MOI.get(model, MOI.ObjectiveFunction{F}()) new_f
185+
return
186+
end

0 commit comments

Comments
 (0)