Skip to content

Commit 8382cec

Browse files
committed
[TambyVanderpooten] improve performance based on profiling
1 parent 6b7ae28 commit 8382cec

File tree

1 file changed

+89
-38
lines changed

1 file changed

+89
-38
lines changed

src/algorithms/TambyVanderpooten.jl

Lines changed: 89 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function _update_search_region(
4141
bounds_to_remove = Vector{Float64}[]
4242
bounds_to_add = Dict{Vector{Float64},Vector{Vector{Vector{Float64}}}}()
4343
for u in keys(U_N)
44-
if all(y .< u)
44+
if _is_less(y, u, 0) # k=0 here because we want to check every element
4545
push!(bounds_to_remove, u)
4646
for l in 1:p
4747
u_l = _get_child(u, y, l)
@@ -55,7 +55,7 @@ function _update_search_region(
5555
end
5656
else
5757
for k in 1:p
58-
if (y[k] == u[k]) && all(_project(y, k) .< _project(u, k))
58+
if _is_less(y, u, k)
5959
push!(U_N[u][k], y)
6060
end
6161
end
@@ -68,6 +68,21 @@ function _update_search_region(
6868
return
6969
end
7070

71+
function _is_less(y, u, k)
72+
for i in 1:length(y)
73+
if i == k
74+
if !(y[i] == u[i])
75+
return false
76+
end
77+
else
78+
if !(y[i] < u[i])
79+
return false
80+
end
81+
end
82+
end
83+
return true
84+
end
85+
7186
function _get_child(u::Vector{Float64}, y::Vector{Float64}, k::Int)
7287
@assert length(u) == length(y)
7388
return vcat(u[1:(k-1)], y[k], u[(k+1):length(y)])
@@ -80,52 +95,78 @@ function _select_search_zone(
8095
)
8196
upper_bounds = collect(keys(U_N))
8297
p = length(yI)
83-
hvs = [
84-
u[k] == yN[k] ? 0.0 : prod(_project(u, k) .- _project(yI, k)) for
85-
k in 1:p, u in upper_bounds
86-
]
87-
k_star, j_star = argmax(hvs).I
88-
return k_star, upper_bounds[j_star]
98+
k_star, u_star, v_star = 1, first(upper_bounds), 0.0
99+
for k in 1:p
100+
for u in upper_bounds
101+
if u[k] != yN[k]
102+
v = 1.0
103+
for i in 1:p
104+
if i != k
105+
v *= u[i] - yI[i]
106+
end
107+
end
108+
if v > v_star
109+
k_star, u_star, v_star = k, u, v
110+
end
111+
end
112+
end
113+
end
114+
return k_star, u_star
89115
end
90116

91117
function minimize_multiobjective!(
92118
algorithm::TambyVanderpooten,
93119
model::Optimizer,
94120
)
95-
@assert MOI.get(model.inner, MOI.ObjectiveSense()) == MOI.MIN_SENSE
96-
warm_start_supported = false
97-
if MOI.supports(model, MOI.VariablePrimalStart(), MOI.VariableIndex)
98-
warm_start_supported = true
99-
end
100121
solutions = Dict{Vector{Float64},Dict{MOI.VariableIndex,Float64}}()
101-
variables = MOI.get(model.inner, MOI.ListOfVariableIndices())
102-
n = MOI.output_dimension(model.f)
122+
status = _minimize_multiobjective!(
123+
algorithm,
124+
model,
125+
model.inner,
126+
model.f,
127+
solutions,
128+
)::MOI.TerminationStatusCode
129+
return status, SolutionPoint[SolutionPoint(X, Y) for (Y, X) in solutions]
130+
end
131+
132+
function _minimize_multiobjective!(
133+
algorithm::TambyVanderpooten,
134+
model::Optimizer,
135+
inner::MOI.ModelLike,
136+
f::MOI.AbstractVectorFunction,
137+
solutions::Dict{Vector{Float64},Dict{MOI.VariableIndex,Float64}},
138+
)
139+
@assert MOI.get(inner, MOI.ObjectiveSense()) == MOI.MIN_SENSE
140+
warm_start_supported =
141+
MOI.supports(inner, MOI.VariablePrimalStart(), MOI.VariableIndex)
142+
variables = MOI.get(inner, MOI.ListOfVariableIndices())
143+
n = MOI.output_dimension(f)
103144
yI, yN = zeros(n), zeros(n)
104-
scalars = MOI.Utilities.scalarize(model.f)
145+
scalars = MOI.Utilities.scalarize(f)
105146
for (i, f_i) in enumerate(scalars)
106-
MOI.set(model.inner, MOI.ObjectiveFunction{typeof(f_i)}(), f_i)
107-
MOI.set(model.inner, MOI.ObjectiveSense(), MOI.MIN_SENSE)
147+
MOI.set(inner, MOI.ObjectiveFunction{typeof(f_i)}(), f_i)
148+
MOI.set(inner, MOI.ObjectiveSense(), MOI.MIN_SENSE)
108149
optimize_inner!(model)
109-
status = MOI.get(model.inner, MOI.TerminationStatus())
150+
status = MOI.get(inner, MOI.TerminationStatus())
110151
if !_is_scalar_status_optimal(status)
111-
return status, nothing
152+
return status
112153
end
113154
_, Y = _compute_point(model, variables, f_i)
114155
_log_subproblem_solve(model, variables)
115156
yI[i] = Y
116157
model.ideal_point[i] = Y
117-
MOI.set(model.inner, MOI.ObjectiveSense(), MOI.MAX_SENSE)
158+
MOI.set(inner, MOI.ObjectiveSense(), MOI.MAX_SENSE)
118159
optimize_inner!(model)
119-
status = MOI.get(model.inner, MOI.TerminationStatus())
160+
status = MOI.get(inner, MOI.TerminationStatus())
120161
if !_is_scalar_status_optimal(status)
121162
_warn_on_nonfinite_anti_ideal(algorithm, MOI.MIN_SENSE, i)
122-
return status, nothing
163+
return status
123164
end
124165
_, Y = _compute_point(model, variables, f_i)
125166
_log_subproblem_solve(model, variables)
126167
yN[i] = Y + 1
127168
end
128-
MOI.set(model.inner, MOI.ObjectiveSense(), MOI.MIN_SENSE)
169+
MOI.set(inner, MOI.ObjectiveSense(), MOI.MIN_SENSE)
129170
U_N = Dict{Vector{Float64},Vector{Vector{Vector{Float64}}}}()
130171
V = [Tuple{Vector{Float64},Vector{Float64}}[] for k in 1:n]
131172
U_N[yN] = [[_get_child(yN, yI, k)] for k in 1:n]
@@ -137,15 +178,15 @@ function minimize_multiobjective!(
137178
end
138179
k, u = _select_search_zone(U_N, yI, yN)
139180
MOI.set(
140-
model.inner,
181+
inner,
141182
MOI.ObjectiveFunction{typeof(scalars[k])}(),
142183
scalars[k],
143184
)
144185
ε_constraints = Any[]
145186
for (i, f_i) in enumerate(scalars)
146187
if i != k
147188
ci = MOI.Utilities.normalize_and_add_constraint(
148-
model.inner,
189+
inner,
149190
f_i,
150191
MOI.LessThan{Float64}(u[i] - 1),
151192
)
@@ -157,7 +198,7 @@ function minimize_multiobjective!(
157198
variables_start = solutions[first(U_N[u][k])]
158199
for x_i in variables
159200
MOI.set(
160-
model.inner,
201+
inner,
161202
MOI.VariablePrimalStart(),
162203
x_i,
163204
variables_start[x_i],
@@ -167,27 +208,27 @@ function minimize_multiobjective!(
167208
end
168209
optimize_inner!(model)
169210
_log_subproblem_solve(model, "auxillary subproblem")
170-
status = MOI.get(model.inner, MOI.TerminationStatus())
211+
status = MOI.get(inner, MOI.TerminationStatus())
171212
if !_is_scalar_status_optimal(status)
172213
MOI.delete.(model, ε_constraints)
173-
return status, nothing
214+
return status
174215
end
175-
y_k = MOI.get(model.inner, MOI.ObjectiveValue())
216+
y_k = MOI.get(inner, MOI.ObjectiveValue())::Float64
176217
sum_f = sum(1.0 * s for s in scalars)
177-
MOI.set(model.inner, MOI.ObjectiveFunction{typeof(sum_f)}(), sum_f)
218+
MOI.set(inner, MOI.ObjectiveFunction{typeof(sum_f)}(), sum_f)
178219
y_k_constraint = MOI.Utilities.normalize_and_add_constraint(
179-
model.inner,
220+
inner,
180221
scalars[k],
181222
MOI.EqualTo(y_k),
182223
)
183224
optimize_inner!(model)
184-
status = MOI.get(model.inner, MOI.TerminationStatus())
225+
status = MOI.get(inner, MOI.TerminationStatus())
185226
if !_is_scalar_status_optimal(status)
186227
MOI.delete.(model, ε_constraints)
187228
MOI.delete(model, y_k_constraint)
188-
return status, nothing
229+
return status
189230
end
190-
X, Y = _compute_point(model, variables, model.f)
231+
X, Y = _compute_point(model, variables, f)
191232
_log_subproblem_solve(model, Y)
192233
MOI.delete.(model, ε_constraints)
193234
MOI.delete(model, y_k_constraint)
@@ -205,8 +246,9 @@ function minimize_multiobjective!(
205246
push!(bounds_to_remove, u_i)
206247
else
207248
for (u_j, y_j) in V[k]
208-
if all(_project(u_i, k) .<= _project(u_j, k)) &&
209-
isapprox(y_j[k], u_i[k]; atol = 1e-6)
249+
if isapprox(y_j[k], u_i[k]; atol = 1e-6) &&
250+
_is_less_eq(u_i, u_j, k)
251+
210252
push!(bounds_to_remove, u_i)
211253
end
212254
end
@@ -219,5 +261,14 @@ function minimize_multiobjective!(
219261
end
220262
end
221263
end
222-
return status, [SolutionPoint(X, Y) for (Y, X) in solutions]
264+
return status
265+
end
266+
267+
function _is_less_eq(y, u, k)
268+
for i in 1:length(y)
269+
if i != k && !(y[i] <= u[i])
270+
return false
271+
end
272+
end
273+
return true
223274
end

0 commit comments

Comments
 (0)