Skip to content

Commit 16b6d62

Browse files
Merge pull request #108 from jonasmac16/multiobjective
Adding basic implementation for BBO BorgMOEA multiobjective opt
2 parents 1729909 + e328953 commit 16b6d62

File tree

3 files changed

+78
-3
lines changed

3 files changed

+78
-3
lines changed

src/GalacticOptim.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import DiffEqBase: OptimizationProblem, OptimizationFunction, AbstractADType
1414
include("solve.jl")
1515
include("function.jl")
1616

17-
export solve
17+
export solve, EnsembleOptimizationProblem
1818

1919
export BBO, CMAEvolutionStrategyOpt
2020

src/solve.jl

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ function Base.show(io::IO, r::AbstractOptimizationSolution)
2020

2121
@printf io " * Status: %s\n\n" r.iteration_converged ? "success" : failure_string
2222
@printf io " * Candidate solution\n"
23-
@printf io " Final objective value: %e\n" r.minimum
23+
fmt = " Final objective value: %e "*repeat(", %e ",length(r.minimum)-1)*"\n"
24+
@eval @printf($io, $fmt, $r.minimum...)
25+
#@printf io " Final objective value: %e\n" r.minimum
2426
@printf io "\n"
2527
@printf io " * Found with\n"
2628
@printf io " Algorithm: %s\n" r.method
@@ -36,7 +38,11 @@ get_maxiters(data) = Iterators.IteratorSize(typeof(DEFAULT_DATA)) isa Iterators.
3638
Iterators.IteratorSize(typeof(DEFAULT_DATA)) isa Iterators.SizeUnknown ?
3739
typemax(Int) : length(data)
3840

39-
function DiffEqBase.solve(prob::OptimizationProblem, opt, args...;kwargs...)
41+
struct EnsembleOptimizationProblem
42+
prob::Array{T, 1} where T<:OptimizationProblem
43+
end
44+
45+
function DiffEqBase.solve(prob::Union{OptimizationProblem,EnsembleOptimizationProblem}, opt, args...;kwargs...)
4046
__solve(prob, opt, args...; kwargs...)
4147
end
4248

@@ -405,6 +411,71 @@ function __init__()
405411
NamedTuple())
406412

407413
end
414+
415+
function __solve(prob::EnsembleOptimizationProblem, opt::BBO, data = DEFAULT_DATA;
416+
cb = (args...) -> (false), maxiters = nothing,
417+
progress = false, FitnessScheme=nothing, kwargs...)
418+
419+
local x, cur, state
420+
421+
if data != DEFAULT_DATA
422+
maxiters = length(data)
423+
end
424+
425+
cur, state = iterate(data)
426+
427+
function _cb(trace)
428+
cb_call = cb(decompose_trace(trace),x...)
429+
if !(typeof(cb_call) <: Bool)
430+
error("The callback should return a boolean `halt` for whether to stop the optimization process.")
431+
end
432+
if cb_call == true
433+
BlackBoxOptim.shutdown_optimizer!(trace) #doesn't work
434+
end
435+
cur, state = iterate(data, state)
436+
cb_call
437+
end
438+
439+
if !(isnothing(maxiters)) && maxiters <= 0.0
440+
error("The number of maxiters has to be a non-negative and non-zero number.")
441+
elseif !(isnothing(maxiters))
442+
maxiters = convert(Int, maxiters)
443+
end
444+
445+
if !(opt.method == :borg_moea)
446+
error("Multi-Objective optimisation is only possible with BorgMOEA algorithm(:borg_moea).")
447+
end
448+
449+
_loss = function(θ)
450+
x = ntuple(i->first(prob.prob[i].f(θ, prob.prob[i].p, cur...)),length(prob.prob))
451+
return x
452+
end
453+
454+
if any([prob.prob[1].lb != i.lb || prob.prob[1].ub != i.ub for i in prob.prob[2:end]])
455+
error("Lower or upper bounds are not consistent between OptimizationProblem.")
456+
else
457+
multi_bounds = (lb=prob.prob[1].lb,ub=prob.prob[1].ub)
458+
end
459+
460+
if isnothing(FitnessScheme)
461+
println("Warning: No FitnessScheme was defined, using default scheme: FitnessScheme=ParetoFitnessScheme{length(prob.prob)}(is_minimizing=true).")
462+
FitnessScheme=BlackBoxOptim.ParetoFitnessScheme{length(prob.prob)}(is_minimizing=true)
463+
end
464+
465+
bboptre = !(isnothing(maxiters)) ? BlackBoxOptim.bboptimize(_loss;Method = opt.method, SearchRange = [(multi_bounds.lb[i], multi_bounds.ub[i]) for i in 1:length(multi_bounds.lb)], MaxSteps = maxiters, CallbackFunction = _cb, CallbackInterval = 0.0, FitnessScheme=FitnessScheme, kwargs...) : BlackBoxOptim.bboptimize(_loss;Method = opt.method, SearchRange = [(multi_bounds.lb[i], multi_bounds.ub[i]) for i in 1:length(multi_bounds.lb)], CallbackFunction = _cb, CallbackInterval = 0.0, FitnessScheme=FitnessScheme, kwargs...)
466+
467+
468+
OptimizationSolution(opt.method,
469+
[NaN],# initial_x,
470+
BlackBoxOptim.best_candidate(bboptre), #pick_best_x(f_incr_pick, state),
471+
BlackBoxOptim.best_fitness(bboptre), # pick_best_f(f_incr_pick, state, d),
472+
bboptre.iterations, #iteration,
473+
!(isnothing(maxiters)) ? bboptre.iterations >= maxiters : true, #iteration == options.iterations,
474+
true,
475+
bboptre.elapsed_time,
476+
NamedTuple())
477+
478+
end
408479
end
409480

410481
@require NLopt="76087f3c-5699-56af-9a33-bf431cd00edd" begin

test/rosenbrock.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,7 @@ using BlackBoxOptim
114114
prob = GalacticOptim.OptimizationProblem(optprob, x0, lb=[-1.0, -1.0], ub=[0.8, 0.8])
115115
sol = solve(prob, BBO())
116116
@test 10*sol.minimum < l1
117+
118+
prob_multi = EnsembleOptimizationProblem([prob, prob])
119+
sol_multi = solve(prob_multi, BBO(:borg_moea), FitnessScheme=ParetoFitnessScheme{2}(is_minimizing=true), ϵ=0.05, MaxSteps=500000)
120+
@test 10*sum(sol_multi.minimum) < l1

0 commit comments

Comments
 (0)