GAPerm: Genetic Algorithm setup

Description Usage Arguments Details Value References Examples

View source: R/GAOptim_perm.R

Description

Setup a GAPerm object that can be used to perform a permutation-based optimization.

Usage

1
2
3
4
  GAPerm(FUN, n, popSize = 100, mutRate = 0.1,
    cxRate = 0.9, eliteRate = 0.4,
    selection = c("fitness", "uniform"),
    crossover = c("pmx"), mutation = c("swap"))

Arguments

FUN

The fitness function, which should take a vector as argument and return a numeric value (See details).

n

The number of elements to permutate.

popSize

The population size.

mutRate

The mutation rate, a numeric value between 0 and 1. When implementing a custom mutation function, this value should be one of the parameters (see details and examples).

cxRate

The crossover rate, a numeric value between 0 and 1. This parameter specifies the probability of two individuals effectively exchange DNA during crossover. In case the individuals didn't crossover, the offspring is a exact copy of the parents. When implementing a custom crossover function, this value should be one of the arguments (see details and examples).

eliteRate

A numeric value between 0 and 1. The eliteRate * popSize best-fitted individuals will automatically be selected for the next generation.

selection

The selection operator to be used. You can also implement a custom selection function (see details and examples).

crossover

The crossover operator to be used. You can also implement a custom crossover function (see details and examples).

mutation

The mutation operator to be used. You can also implement a custom mutation function (see details and examples).

Details

This is the function used to configure and fine-tune a permutation-based optimization. The basic usage requires only the FUN parameter (function to be maximized), together with n (the number of elements to permutate), all the other parameters have sensible defaults.

The parameters selection, crossover and mutation can also take a custom function as argument, which needs to be in the appropriate format (see the examples). The text below explains the default behaviour for these parameters, which will be usefull if you want to override one or more genetic operators.

Value

An object of class GAPerm, which you can pass as an argument to plot or summary. This object is a list with the following accessor functions:

bestFit: Returns a vector with the best fitness achieved in each generation.
meanFit: Returns a vector with the mean fitness achieved in each generation.
bestIndividual: Returns a vector with the best solution found.
evolve(h): This is the function you call to evolve your population.
You also need to specify the number of generations to evolve.
population: Returns the current population matrix.

References

Even, S. Algorithmic Combinatorics. The Macmillan Company, NY 1973.

Michalewicz, Zbigniew. Genetic Algorithms + Data Structures = Evolution Programs - 3rd ed.

Examples

  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
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# TSP with 10 cities around a circular pattern
 n = 10
 R = 10
 angs = seq(0, 2*pi, length = n)
 xp = R * cos(angs) + rnorm(n)
 yp = R * sin(angs) + rnorm(n)
 xp = c(xp, xp[1])
 yp = c(yp, yp[1])

 base.M = matrix(c(xp, yp), ncol = 2)
 dist.FUN = function(p)
 {
   p = c(p, p[1])
   M.diff = diff(base.M[p, ])
   dists = apply(M.diff, 1, function(x)x[1]^2 + x[2]^2)
   1/sum(dists)
 }

 ga1 = GAPerm(dist.FUN, n, popSize = 100, mutRate = 0.3)
 ga1$evolve(100)
 plot(xp, yp, type = 'n', xlab = '', ylab = '')
 res = ga1$bestIndividual()
 res = c(res, res[1])

 i = 1:n
 xi = base.M[res[i], 1]
 yi = base.M[res[i], 2]
 xf = base.M[res[i + 1], 1]
 yf = base.M[res[i + 1], 2]

 arrows(xi, yi, xf, yf, col = 'red', angle = 10)
 text(base.M[res, 1], base.M[res, 2], 1:n, cex = 0.9, col = 'gray20')


 # Euro tour problem (See ?optim)
 eurodistmat = as.matrix(eurodist)

 # This function will be used for the remaining examples
 distance = function(sq)
 {
   sq = c(sq, sq[1])
   sq2 <- embed(sq, 2)
   1/sum(eurodistmat[cbind(sq2[,2], sq2[,1])])
 }

 loc = -cmdscale(eurodist, add = TRUE)$points
 x = loc[, 1]
 y = loc[, 2]
 n = nrow(eurodistmat)

 set.seed(1)
 ga2 = GAPerm(distance, n, popSize = 100, mutRate = 0.3)
 ga2$evolve(200)
 best = ga2$bestIndividual()
 best = c(best, best[1])
 best.dist = 1/max(ga2$bestFit())
 res = loc[best, ]
 i = 1:n

 plot(x, y, type = 'n', axes = FALSE, ylab = '', xlab = '')
 title ('Euro tour: TSP with 21 cities')
 mtext(paste('Best distance found:', best.dist))
 arrows(res[i, 1], res[i, 2], res[i + 1, 1], res[i + 1, 2], col = 'red', angle = 10)
 text(x, y, labels(eurodist), cex = 0.8, col = 'gray20')


 # Euro tour with custom selection
 selec.FUN = function(population, fitnessVec, nLeft)
 {
   # Chance of being select proportional to fitness sqrt
   idxs = sample(nrow(population), nLeft, prob = sqrt(fitnessVec))

   # Just return the nLeft selected row indexes
   idxs
 }

 ga3 = GAPerm(distance, n, mutRate = 0.3, selection = selec.FUN)
 ga3$evolve(200)
 best.dist = 1/max(ga3$bestFit())
 plot(ga3, main = 'Euro tour: TSP with 21 cities')
 mtext(paste('Best distance found:', best.dist))


 # Euro tour with custom crossover
 # This is the default pmx implementation
 crossover.FUN = function(vec1, vec2, prob)
 {
   # prob is the crossover rate
   if (runif(1) > prob)
     return(matrix(c(vec1, vec2), nrow = 2, byrow = TRUE))

   idxs = sample(1:length(vec1), 2)
   vec1.cp = vec1

   for (i in idxs)
   {
     other.val = vec2[i]
     vec.idx = which(vec1 == other.val)
     vec1[vec.idx] = vec1[i]
     vec1[i] = other.val
   }

   for (i in idxs)
   {
     other.val = vec1.cp[i]
     vec.idx = which(vec2 == other.val)
     vec2[vec.idx] = vec2[i]
     vec2[i] = other.val
   }

   matrix(c(vec1, vec2), nrow = 2, byrow = TRUE)
 }

 ga4 = GAPerm(distance, n, mutRate = 0.3, crossover = crossover.FUN)
 ga4$evolve(200)
 best.dist = 1/max(ga4$bestFit())
 plot(ga4, main = 'Euro tour: TSP with 21 cities')
 mtext(paste('Best distance found:', best.dist))


 # Euro tour with custom mutation
 # This is the default implementation
 mutation.FUN = function(M, mutations)
 {
   # M - The population matrix to apply mutation
   # mutations - The number of mutations you supposed to apply, according to mutRate

   rows = sample(1:nrow(M), mutations, replace = FALSE)
   cols = t(replicate(mutations, sample(1:n, 2)))
   col1 = cols[, 1]
   col2 = cols[, 2]
   extM1 = matrix(c(rows, col1), ncol = 2)
   extM2 = matrix(c(rows, col2), ncol = 2)
   tempCol = M[extM1]
   M[extM1] = M[extM2]
   M[extM2] = tempCol
   M
 }

 ga5 = GAPerm(distance, n, mutRate = 0.3, mutation = mutation.FUN)
 ga5$evolve(200)
 best.dist = 1/max(ga5$bestFit())
 plot(ga5, main = 'Euro tour: TSP with 21 cities')
 mtext(paste('Best distance found:', best.dist))

Example output



gaoptim documentation built on May 30, 2017, 12:37 a.m.

Related to GAPerm in gaoptim...