Skip to content

Commit 8e3e38d

Browse files
authored
Merge pull request #92 from jmejia8/develop
Add BRKGA optimizer
2 parents 015a0ed + 8685f93 commit 8e3e38d

File tree

10 files changed

+171
-3
lines changed

10 files changed

+171
-3
lines changed

docs/references.bib

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,17 @@ @INPROCEEDINGS{Takahama2006Constrained
257257
number={},
258258
pages={1-8},
259259
doi={10.1109/CEC.2006.1688283}}
260+
261+
@article{Gonalves2010,
262+
doi = {10.1007/s10732-010-9143-1},
263+
url = {https://doi.org/10.1007/s10732-010-9143-1},
264+
year = {2010},
265+
month = aug,
266+
publisher = {Springer Science and Business Media {LLC}},
267+
volume = {17},
268+
number = {5},
269+
pages = {487--525},
270+
author = {Jos{\'{e}} Fernando Gon{\c{c}}alves and Mauricio G. C. Resende},
271+
title = {Biased random-key genetic algorithms for~combinatorial optimization},
272+
journal = {Journal of Heuristics}
273+
}

docs/src/algorithms.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ contributor's understanding of the algorithms detailed in the published paper.
2222
| GA | Single |||| [`GA`](@ref) |
2323
| CCMO | Multi |||| [`CCMO`](@ref) |
2424
| $\varepsilon$DE | Single |||| [`εDE`](@ref) |
25+
| BRKGA | Single |||| [`BRKGA`](@ref) |
2526

2627

2728
✅ = supported,
@@ -174,3 +175,11 @@ CCMO
174175
```@docs
175176
εDE
176177
```
178+
179+
## BRKGA
180+
181+
Biased Random Key Genetic Algorithm by [Gonalves2010](@cite).
182+
183+
```@docs
184+
BRKGA
185+
```

src/Metaheuristics.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export hval, gval, hvals, gvals
1414
export NSGA3, gen_ref_dirs
1515

1616
export SMS_EMOA, SPEA2, MCCGA, CCMO
17+
export BRKGA
1718

1819
export PerformanceIndicators, pareto_front, nadir, ideal
1920
export termination_status_message
@@ -120,7 +121,7 @@ include("algorithms/Restart/Restart.jl")
120121

121122
# genetic algorithm
122123
include("algorithms/MCCGA/MCCGA.jl")
123-
124+
include("algorithms/BRKGA/BRKGA.jl")
124125

125126
include("algorithms/stop_criteria.jl")
126127

src/algorithms/BRKGA/BRKGA.jl

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""
2+
BRKGA(num_elites = 20, num_mutants = 10, num_offsprings = 70, bias = 0.7)
3+
4+
Biased Random Key Genetic Algorithm (BRKGA).
5+
6+
### Example
7+
8+
```julia-repl
9+
julia> target_perm = collect(reverse(1:10))
10+
10-element Vector{Int64}:
11+
10
12+
9
13+
8
14+
7
15+
6
16+
5
17+
4
18+
3
19+
2
20+
1
21+
22+
julia> decode(rk) = sortperm(rk);
23+
24+
julia> f(rk) = sum(abs.(decode(rk) - target_perm));
25+
26+
julia> res = optimize(f, [zeros(10) ones(10)], BRKGA(num_elites=70))
27+
Optimization Result
28+
===================
29+
Iteration: 22
30+
Minimum: 0
31+
Minimizer: [0.938595, 0.851247, 0.823736, …, 0.375321]
32+
Function calls: 2200
33+
Total time: 0.0238 s
34+
Stop reason: Due to Convergence Termination criterion.
35+
36+
julia> decode(minimizer(res))
37+
10-element Vector{Int64}:
38+
10
39+
9
40+
8
41+
7
42+
6
43+
5
44+
4
45+
3
46+
2
47+
1
48+
```
49+
"""
50+
function BRKGA(;
51+
num_elites = 20,
52+
num_mutants = 10,
53+
num_offsprings = 70,
54+
N = num_elites + num_mutants + num_offsprings,
55+
bias = 0.7,
56+
kargs...
57+
)
58+
59+
initializer = RandomInBounds(;N)
60+
selection = BiasedSelection(num_elites, num_offsprings)
61+
crossover = BinomialCrossover(p = bias, n_offsprings = 1)
62+
mutation = InsertRandomMutation(num_mutants)
63+
environmental_selection = ElitistReplacement()
64+
65+
GA(;initializer,
66+
selection,
67+
crossover,
68+
mutation,
69+
environmental_selection,
70+
kargs...
71+
)
72+
end
73+

src/operators/crossover/binomial.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
mutable struct BinomialCrossover
2+
p::Float64
3+
n_offsprings::Int
4+
rng
5+
end
6+
7+
function BinomialCrossover(;p = 0.5, n_offsprings = 2, rng=default_rng_mh())
8+
BinomialCrossover(p, n_offsprings, rng)
9+
end
10+
11+
function crossover(population, c::BinomialCrossover)
12+
Q = positions(population)
13+
14+
Q1 = Q[1:2:end-1, :]
15+
Q2 = Q[2:2:end, :]
16+
17+
mask = rand(c.rng, size(Q,1)÷2, size(Q, 2)) .<= c.p
18+
Q1[mask] = Q2[mask]
19+
20+
if c.n_offsprings > 2
21+
return Q1
22+
end
23+
24+
Q1 = Q[1:2:end-1, :]
25+
Q2[mask] = Q1[mask]
26+
return vcat(Q1, Q2)
27+
end
28+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
mutable struct InsertRandomMutation
2+
num_mutants::Int
3+
end
4+
5+
function mutation!(Q, m::InsertRandomMutation)
6+
# TODO: add rng
7+
R = rand(m.num_mutants, size(Q, 2))
8+
vcat(Q, R)
9+
end

src/operators/mutation/mutation.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
include("insert_random.jl")
2+
3+
14
"""
25
DE_mutation(population, F = 1.0, strategy = :rand1)
36

src/operators/operators.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ include("selection/selection.jl")
1212
include("crossover/order.jl")
1313
include("crossover/sbx.jl")
1414
include("crossover/uniform.jl")
15+
include("crossover/binomial.jl")
1516

1617
include("mutation/bitflip.jl")
1718
include("mutation/polynomial.jl")

src/operators/selection/selection.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,20 @@ function binary_tournament(population, fitness::Vector{T}) where T <: Real
5858

5959
return fitness[a] < fitness[b] ? population[a] : population[b]
6060
end
61+
62+
mutable struct BiasedSelection
63+
num_elites::Int
64+
num_offsprings::Int
65+
end
66+
67+
68+
function selection(population, parameters::BiasedSelection)
69+
elites = 1:parameters.num_elites
70+
no_elites = parameters.num_elites+1:length(population)
71+
n = parameters.num_offsprings ÷ 2
72+
73+
parent = ones(Int, 2n)
74+
parent[1:2:end] = rand(elites, n)
75+
parent[2:2:end] = rand(no_elites, n)
76+
parent
77+
end

test/combinatorial.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,23 @@
5252
@test minimum(result) f(1:n)
5353
test_results(result)
5454
end
55-
55+
56+
function rkga()
57+
n = 5
58+
target_perm = collect(reverse(1:n))
59+
# decoder
60+
decode(rk) = sortperm(rk);
61+
# objective function
62+
f(rk) = sum(abs.(decode(rk) - target_perm));
63+
res = optimize(f, [zeros(n) ones(n)], BRKGA(num_elites=50))
64+
@test decode(minimizer(res)) == target_perm
65+
end
66+
67+
68+
rkga()
5669
#### Permutation
5770
TSP_problem()
58-
71+
5972
#### Binary
6073
options = Options(seed = 1, f_tol = 1e-16, iterations=1000)
6174
information = Information(f_optimum = 0.0)

0 commit comments

Comments
 (0)