Since GA package does’nt provides integer type, its impossible to work with short positif natural numbers. This paper explains how to use binary type of GA package to solve somes mathematical problems like this mathematical equality: a + 2b + 3c + 4d = n
According to the manual, GA package can work with 3 types of genetic algorithms.
| Type | Description |
|---|---|
| “binary” | for binary representations of decision variables. |
| “real-valued” | for optimization problems where the decision variables are floating-point representations of real numbers. |
| “permutation” | for problems that involves reordering of a list. |
As you can see, we have not the “integer” type needed in somes computations. Despict the fact that we can work with real numbers, these are not suitable for certain calculations, whether in computation time or the fact that we need to work with positive integers.
In any case, the only possibility would be to use the “binary” type. When “binary” type is defined, the chromosome passed as argument to your fitness function is a vector of binary digits, for example:
| c(1,0,0,1,1,1,0,1,1,0,1,0,0) |
An integer value can be represented in binary, for instance the binary 101010 is 42 in base 10.
So, let’s work with this type
First, we have to choose how many integer variables we need. Say nbvars = 3 for instance.
We choose how many bits we needs to code these variables. The max value in decimal stored in a binary variable is defined as \(Vmax_{10} = 2^n - 1\)
Here we can see the maximum according to the number of bits for some values of n
| n | \(2^n - 1\) |
|---|---|
| 2 | 3 |
| 3 | 7 |
| 4 | 15 |
| 5 | 31 |
| 6 | 63 |
| 8 | 255 |
| 10 | 1 023 |
| 12 | 4 095 |
| 16 | 65 535 |
| 24 | 16 777 215 |
| 32 | 4 294 967 295 |
So, if you choose 8 bits for your variables, you need to set the nBits argument of function ga() to 8 * nbvars so \(nBits = 3 * nbvars = 8 * 3 = 24\).
As seen above, the binary chromosome is passed as argument to your fitness function as a vector, so we have to retrieve our variables from this one.
The “bin2int” function is able to transform a binary vector to an integer vector. It needs two arguments, the binary vector and the number of bits of your variables.
bin2int <- function(x, len) {
Bin <- paste(x, collapse="")
V <- stri_sub(Bin, seq(1, stri_length(Bin),by=len), length=len)
ret <- strtoi(V, base=2)
ret
}
bin2int(rep(0:1, length=16), 4)
## [1] 5 5 5 5
bin2int(rep(0:1, length=24), 8)
## [1] 85 85 85
bin2int(rep(0:1, length=32), 32)
## [1] 1431655765
We want to solve the equality : \(a + 2b + 3c + 4d = 30\)
Where \(a, b, c, d \neq 0\)
One of the solutions is:
7 + (2 x 5) + (3 x 3) + (4 x 1) = 30
Other solutions have been found by the algorithm:
Our fitness function needs to retrieve 4 variables of 4 bits (range values is [0, 15] for each variables, that is \(15^4 = 50625\) possible combinations), nBits argument of the ga() function will be 4 * 4 = 16.
NB: our fitness function has to resolve the equation \(f = a +2b + 3c + 4d - 30 = 0\) where \(a,b,c,d \neq 0\)
solver <- function(x) {
V <- bin2int(x, 4)
a <- V[1]
b <- V[2]
c <- V[3]
d <- V[4]
R <- abs(((a+2*b+3*c+4*d)-30))
if (a == 0 | b == 0 | c == 0 | d == 0) {
return(100)
} else {
return(R)
}
}
fitness <- function(x) -solver(x)
system.time({
GA <- ga(type = "binary", nBits=16,
fitness = fitness, elitism = 4,
pcrossover = 0.20, pmutation = 0.1,
popSize = 32, maxiter = 600, run = 100)
})
## user system elapsed
## 0.179 0.000 0.179
summary(GA)
## +-----------------------------------+
## | Genetic Algorithm |
## +-----------------------------------+
##
## GA settings:
## Type = binary
## Population size = 32
## Number of generations = 600
## Elitism = 4
## Crossover probability = 0.2
## Mutation probability = 0.1
##
## GA results:
## Iterations = 102
## Fitness function value = 0
## Solutions =
## x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16
## [1,] 0 0 1 1 0 1 1 0 0 0 0 1 0 0 1 1
## [2,] 0 1 1 1 0 1 1 0 0 0 0 1 0 0 1 0
## [3,] 1 1 1 1 0 0 1 0 0 0 0 1 0 0 1 0
## [4,] 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0
solution <- GA@solution
for (i in 1:nrow(solution)) {
S <- bin2int(solution[i,], 4)
To <- S[1]+2*S[2]+3*S[3]+4*S[4]
res <-sprintf("Total = %d, a = %d, b = %d, c = %d, d = %d", To, S[1], S[2], S[3], S[4])
print(res)
}
## [1] "Total = 30, a = 3, b = 6, c = 1, d = 3"
## [1] "Total = 30, a = 7, b = 6, c = 1, d = 2"
## [1] "Total = 30, a = 15, b = 2, c = 1, d = 2"
## [1] "Total = 30, a = 7, b = 3, c = 3, d = 2"
plot(GA)