de.Rd
Maximization of a fitness function using Differential Evolution (DE). DE is a population-based evolutionary algorithm for optimisation of fitness functions defined over a continuous parameter space.
de(fitness,
lower, upper,
popSize = 10*d,
stepsize = 0.8,
pcrossover = 0.5,
...)
the fitness function, any allowable R function which takes as input a vector of values representing a potential solution, and returns a numerical value describing its ``fitness''.
a vector of length equal to the decision variables providing the lower bounds of the search space.
a vector of length equal to the decision variables providing the upper bounds of the search space.
the population size. By default is set at 10 times the number of decision variables.
the probability of crossover, by default set to 0.5.
the stepsize or weighting factor. A value in the interval [0,2], by default set to 0.8. If set at NA
a random value is selected in the interval [0.5, 1.0] (so called dithering).
additional arguments to be passed to the ga
function.
Differential Evolution (DE) is a stochastic evolutionary algorithm that optimises multidimensional real-valued fitness functions without requiring the optimisation problem to be differentiable.
This implimentation follows the description in Simon (2013; Sec. 12.4, and Fig. 12.12) and uses the functionalities available in the ga
function for Genetic Algorithms.
The DE selection operator is defined by gareal_de
with parameters p = pcrossover
and F = stepsize
.
Returns an object of class de-class
. See de-class
for a description of available slots information.
Scrucca L. (2013). GA: A Package for Genetic Algorithms in R. Journal of Statistical Software, 53(4), 1-37, doi:10.18637/jss.v053.i04 .
Scrucca, L. (2017) On some extensions to GA package: hybrid optimisation, parallelisation and islands evolution. The R Journal, 9/1, 187-206, doi:10.32614/RJ-2017-008 .
Simon D. (2013) Evolutionary Optimization Algorithms. John Wiley & Sons.
Price K., Storn R.M., Lampinen J.A. (2005) Differential Evolution: A Practical Approach to Global Optimization. Springer.
# 1) one-dimensional function
f <- function(x) abs(x)+cos(x)
curve(f, -20, 20)
DE <- de(fitness = function(x) -f(x), lower = -20, upper = 20)
plot(DE)
summary(DE)
#> ── Differential Evolution ──────────────
#>
#> DE settings:
#> Type = real-valued
#> Population size = 10
#> Number of generations = 100
#> Elitism = 0
#> Stepsize = 0.8
#> Crossover probability = 0.5
#> Mutation probability = 0
#> Search domain =
#> x1
#> lower -20
#> upper 20
#>
#> DE results:
#> Iterations = 100
#> Fitness function value = -1
#> Solution =
#> x1
#> [1,] 0
curve(f, -20, 20, n = 1000)
abline(v = DE@solution, lty = 3)
# 2) "Wild" function, global minimum at about -15.81515
wild <- function(x) 10*sin(0.3*x)*sin(1.3*x^2) + 0.00001*x^4 + 0.2*x + 80
plot(wild, -50, 50, n = 1000)
# from help("optim")
SANN <- optim(50, fn = wild, method = "SANN",
control = list(maxit = 20000, temp = 20, parscale = 20))
unlist(SANN[1:2])
#> par value
#> -15.81505 67.46782
DE <- de(fitness = function(...) -wild(...), lower = -50, upper = 50)
plot(DE)
summary(DE)
#> ── Differential Evolution ──────────────
#>
#> DE settings:
#> Type = real-valued
#> Population size = 10
#> Number of generations = 100
#> Elitism = 0
#> Stepsize = 0.8
#> Crossover probability = 0.5
#> Mutation probability = 0
#> Search domain =
#> x1
#> lower -50
#> upper 50
#>
#> DE results:
#> Iterations = 100
#> Fitness function value = -67.49512
#> Solution =
#> x1
#> [1,] -15.50653
# 3) two-dimensional Rastrigin function
Rastrigin <- function(x1, x2)
{
20 + x1^2 + x2^2 - 10*(cos(2*pi*x1) + cos(2*pi*x2))
}
x1 <- x2 <- seq(-5.12, 5.12, by = 0.1)
f <- outer(x1, x2, Rastrigin)
persp3D(x1, x2, f, theta = 50, phi = 20, col.palette = bl2gr.colors)
DE <- de(fitness = function(x) -Rastrigin(x[1], x[2]),
lower = c(-5.12, -5.12), upper = c(5.12, 5.12),
popSize = 50)
plot(DE)
summary(DE)
#> ── Differential Evolution ──────────────
#>
#> DE settings:
#> Type = real-valued
#> Population size = 50
#> Number of generations = 100
#> Elitism = 0
#> Stepsize = 0.8
#> Crossover probability = 0.5
#> Mutation probability = 0
#> Search domain =
#> x1 x2
#> lower -5.12 -5.12
#> upper 5.12 5.12
#>
#> DE results:
#> Iterations = 100
#> Fitness function value = -4.369838e-13
#> Solution =
#> x1 x2
#> [1,] 4.58929e-08 -9.880176e-09
filled.contour(x1, x2, f, color.palette = bl2gr.colors,
plot.axes = { axis(1); axis(2);
points(DE@solution,
col = "yellow", pch = 3, lwd = 2) })
# 4) two-dimensional Ackley function
Ackley <- function(x1, x2)
{
-20*exp(-0.2*sqrt(0.5*(x1^2 + x2^2))) -
exp(0.5*(cos(2*pi*x1) + cos(2*pi*x2))) + exp(1) + 20
}
x1 <- x2 <- seq(-3, 3, by = 0.1)
f <- outer(x1, x2, Ackley)
persp3D(x1, x2, f, theta = 50, phi = 20, col.palette = bl2gr.colors)
DE <- de(fitness = function(x) -Ackley(x[1], x[2]),
lower = c(-3, -3), upper = c(3, 3),
stepsize = NA)
plot(DE)
summary(DE)
#> ── Differential Evolution ──────────────
#>
#> DE settings:
#> Type = real-valued
#> Population size = 20
#> Number of generations = 100
#> Elitism = 0
#> Stepsize = runif(0.5,1.0)
#> Crossover probability = 0.5
#> Mutation probability = 0
#> Search domain =
#> x1 x2
#> lower -3 -3
#> upper 3 3
#>
#> DE results:
#> Iterations = 100
#> Fitness function value = -5.340475e-10
#> Solution =
#> x1 x2
#> [1,] -1.086033e-10 1.544546e-10
filled.contour(x1, x2, f, color.palette = bl2gr.colors,
plot.axes = { axis(1); axis(2);
points(DE@solution,
col = "yellow", pch = 3, lwd = 2) })
# 5) Curve fitting example (see Scrucca JSS 2013)
if (FALSE) {
# subset of data from data(trees, package = "spuRs")
tree <- data.frame(Age = c(2.44, 12.44, 22.44, 32.44, 42.44, 52.44, 62.44,
72.44, 82.44, 92.44, 102.44, 112.44),
Vol = c(2.2, 20, 93, 262, 476, 705, 967, 1203, 1409,
1659, 1898, 2106))
richards <- function(x, theta)
{ theta[1]*(1 - exp(-theta[2]*x))^theta[3] }
fitnessL2 <- function(theta, x, y)
{ -sum((y - richards(x, theta))^2) }
DE <- de(fitness = fitnessL2, x = tree$Age, y = tree$Vol,
lower = c(3000, 0, 2), upper = c(4000, 1, 4),
popSize = 500, maxiter = 1000, run = 100,
names = c("a", "b", "c"))
summary(DE)
}