-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathRandomWeighting.jl
More file actions
84 lines (72 loc) · 3.02 KB
/
RandomWeighting.jl
File metadata and controls
84 lines (72 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# Copyright 2019, Oscar Dowson and contributors
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v.2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at http://mozilla.org/MPL/2.0/.
"""
RandomWeighting()
A heuristic solver that works by repeatedly solving a weighted sum problem with
random weights.
## Supported problem classes
This algorithm supports all problem classes.
## Supported optimizer attributes
* `MOI.TimeLimitSec()`: terminate if the time limit is exceeded and return the
list of current solutions.
* `MOA.SolutionLimit()`: terminate once this many solutions have been found.
At least one of these two limits must be set.
"""
mutable struct RandomWeighting <: AbstractAlgorithm
solution_limit::Union{Nothing,Int}
RandomWeighting() = new(nothing)
end
MOI.supports(::RandomWeighting, ::SolutionLimit) = true
function MOI.set(alg::RandomWeighting, ::SolutionLimit, value)
alg.solution_limit = value
return
end
function MOI.get(alg::RandomWeighting, attr::SolutionLimit)
return something(alg.solution_limit, default(alg, attr))
end
function optimize_multiobjective!(algorithm::RandomWeighting, model::Optimizer)
if MOI.get(model, MOI.TimeLimitSec()) === nothing &&
algorithm.solution_limit === nothing
error("At least `MOI.TimeLimitSec` or `MOA.SolutionLimit` must be set")
end
start_time = time()
solutions = SolutionPoint[]
sense = MOI.get(model, MOI.ObjectiveSense())
P = MOI.output_dimension(model.f)
variables = MOI.get(model.inner, MOI.ListOfVariableIndices())
f = _scalarise(model.f, ones(P))
MOI.set(model.inner, MOI.ObjectiveFunction{typeof(f)}(), f)
optimize_inner!(model)
status = MOI.get(model.inner, MOI.TerminationStatus())
if _is_scalar_status_optimal(status)
X, Y = _compute_point(model, variables, model.f)
push!(solutions, SolutionPoint(X, Y))
else
return status, nothing
end
# This double loop is a bit weird:
# * the inner loop fills up SolutionLimit number of solutions. Then we cut
# it back to nondominated.
# * then the outer loop goes again
while length(solutions) < MOI.get(algorithm, SolutionLimit())
while length(solutions) < MOI.get(algorithm, SolutionLimit())
ret = _check_premature_termination(model, start_time)
if ret !== nothing
return ret, filter_nondominated(sense, solutions)
end
weights = rand(P)
f = _scalarise(model.f, weights)
MOI.set(model.inner, MOI.ObjectiveFunction{typeof(f)}(), f)
optimize_inner!(model)
status = MOI.get(model.inner, MOI.TerminationStatus())
if _is_scalar_status_optimal(status)
X, Y = _compute_point(model, variables, model.f)
push!(solutions, SolutionPoint(X, Y))
end
end
solutions = filter_nondominated(sense, solutions)
end
return MOI.OPTIMAL, filter_nondominated(sense, solutions)
end