53 lines
1.4 KiB
R
53 lines
1.4 KiB
R
set.seed(1234, kind="Mersenne-Twister")
|
|
|
|
## Easier if the string is a character vector
|
|
target <- unlist(strsplit("METHINKS IT IS LIKE A WEASEL", ""))
|
|
|
|
charset <- c(LETTERS, " ")
|
|
parent <- sample(charset, length(target), replace=TRUE)
|
|
|
|
mutaterate <- 0.01
|
|
|
|
## Number of offspring in each generation
|
|
C <- 100
|
|
|
|
## Hamming distance between strings normalized by string length is used
|
|
## as the fitness function.
|
|
fitness <- function(parent, target) {
|
|
sum(parent == target) / length(target)
|
|
}
|
|
|
|
mutate <- function(parent, rate, charset) {
|
|
p <- runif(length(parent))
|
|
nMutants <- sum(p < rate)
|
|
if (nMutants) {
|
|
parent[ p < rate ] <- sample(charset, nMutants, replace=TRUE)
|
|
}
|
|
parent
|
|
}
|
|
|
|
evolve <- function(parent, mutate, fitness, C, mutaterate, charset) {
|
|
children <- replicate(C, mutate(parent, mutaterate, charset),
|
|
simplify=FALSE)
|
|
children <- c(list(parent), children)
|
|
children[[which.max(sapply(children, fitness, target=target))]]
|
|
}
|
|
|
|
.printGen <- function(parent, target, gen) {
|
|
cat(format(i, width=3),
|
|
formatC(fitness(parent, target), digits=2, format="f"),
|
|
paste(parent, collapse=""), "\n")
|
|
}
|
|
|
|
i <- 0
|
|
.printGen(parent, target, i)
|
|
while ( ! all(parent == target)) {
|
|
i <- i + 1
|
|
parent <- evolve(parent, mutate, fitness, C, mutaterate, charset)
|
|
|
|
if (i %% 20 == 0) {
|
|
.printGen(parent, target, i)
|
|
}
|
|
}
|
|
.printGen(parent, target, i)
|