June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -10,8 +10,8 @@ Starting with:
;See also:
*   [[wp:Weasel_program#Weasel_algorithm|Weasel algorithm]].
*   [[wp:Evolutionary algorithm|Evolutionary algorithm]].
*   Wikipedia entry:   [[wp:Weasel_program#Weasel_algorithm|Weasel algorithm]].
*   Wikipedia entry:   [[wp:Evolutionary algorithm|Evolutionary algorithm]].
<br>
<small>Note: to aid comparison, try and ensure the variables and functions mentioned in the task description appear in solutions</small>

View file

@ -1,33 +1,24 @@
integer
fitness(data t, data b)
{
integer f, i;
integer c, f, i;
f = 0;
i = b_length(t);
while (i) {
i -= 1;
f += sign(t[i] ^ b[i]);
for (i, c in b) {
f += sign(t[i] ^ c);
}
return f;
f;
}
void
mutate(data c, data b, data u)
mutate(data e, data b, data u)
{
integer i, l;
integer c;
l = b_length(b);
i = 0;
while (i < l) {
if (drand(15)) {
b_append(c, b[i]);
} else {
b_append(c, u[drand(26)]);
}
i += 1;
for (, c in b) {
e.append(drand(15) ? c : u[drand(26)]);
}
}
@ -35,17 +26,15 @@ integer
main(void)
{
data b, t, u;
integer f, i, l;
integer f, i;
b_cast(t, "METHINK IT IS LIKE A WEASEL");
b_cast(u, "ABCDEFGHIJKLMNOPQRSTUVWXYZ ");
t = "METHINK IT IS LIKE A WEASEL";
u = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
l = b_length(t);
i = l;
i = ~t;
while (i) {
i -= 1;
b_append(b, u[drand(26)]);
b.append(u[drand(26)]);
}
f = fitness(t, b);
@ -53,7 +42,7 @@ main(void)
data n;
integer a;
o_form("/lw4/~\n", f, b_string(b));
o_form("/lw4/~\n", f, b);
n = b;
@ -73,7 +62,7 @@ main(void)
b = n;
}
o_form("/lw4/~\n", f, b_string(b));
o_form("/lw4/~\n", f, b);
return 0;
}

View file

@ -0,0 +1,37 @@
USING: arrays formatting io kernel literals math prettyprint
random sequences strings ;
FROM: math.extras => ... ;
IN: rosetta-code.evolutionary-algorithm
CONSTANT: target "METHINKS IT IS LIKE A WEASEL"
CONSTANT: mutation-rate 0.1
CONSTANT: num-children 25
CONSTANT: valid-chars
$[ CHAR: A ... CHAR: Z >array { 32 } append ]
: rand-char ( -- n )
valid-chars random ;
: new-parent ( -- str )
target length [ rand-char ] replicate >string ;
: fitness ( str -- n )
target [ = ] { } 2map-as sift length ;
: mutate ( str rate -- str/str' )
[ random-unit > [ drop rand-char ] when ] curry map ;
: next-parent ( str -- str/str' )
dup [ mutation-rate mutate ] curry num-children 1 - swap
replicate [ 1array ] dip append [ fitness ] supremum-by ;
: print-parent ( str -- )
[ fitness pprint bl ] [ print ] bi ;
: main ( -- )
0 new-parent
[ dup target = ]
[ next-parent dup print-parent [ 1 + ] dip ] until drop
"Finished in %d generations." printf ;
MAIN: main

View file

@ -0,0 +1,24 @@
fitness(a::AbstractString, b::AbstractString) = count(l == t for (l, t) in zip(a, b))
function mutate(str::AbstractString, rate::Float64)
L = collect(Char, " ABCDEFGHIJKLMNOPQRSTUVWXYZ")
return map(str) do c
if rand() < rate rand(L) else c end
end
end
function evolve(parent::String, target::String, mutrate::Float64, nchild::Int)
println("Initial parent is $parent, its fitness is $(fitness(parent, target))")
gens = 0
while parent != target
children = collect(mutate(parent, mutrate) for i in 1:nchild)
bestfit, best = findmax(fitness.(children, target))
parent = children[best]
gens += 1
if gens % 10 == 0
println("After $gens generations, the new parent is $parent and its fitness is $(fitness(parent, target))")
end
end
println("After $gens generations, the parent evolved into the target $target")
end
evolve("IU RFSGJABGOLYWF XSMFXNIABKT", "METHINKS IT IS LIKE A WEASEL", 0.08998, 100)

View file

@ -14,7 +14,7 @@ class CreationFactory
var f = USize(0)
for i in Range(0, s.size()) do
try
if s(i) == _desired(i) then
if s(i)? == _desired(i)? then
f = f +1
end
end
@ -57,7 +57,7 @@ class Mutator
fun ref _random_letter(): U8 =>
let ln = _rand.int(_possibilities.size().u64()).usize()
try _possibilities(ln) else ' ' end
try _possibilities(ln)? else ' ' end
class Generation
let _size: USize

View file

@ -0,0 +1,34 @@
# Setup
set.seed(42)
target= unlist(strsplit("METHINKS IT IS LIKE A WEASEL", ""))
chars= c(LETTERS, " ")
C= 100
# Fitness function; high value means higher fitness
fitness= function(x){
sum(x == target)
}
# Mutate function
mutate= function(x, rate= 0.01){
idx= which(runif(length(target)) <= rate)
x[idx]= replicate(n= length(idx), expr= sample(x= chars, size= 1, replace= T))
x
}
# Evolve function
evolve= function(x){
parents= rep(list(x), C+1) # Repliction
parents[1:C]= lapply(parents[1:C], function(x) mutate(x)) # Mutation
idx= which.max(lapply(parents, function(x) fitness(x))) # Selection
parents[[idx]]
}
# Initialize first parent
parent= sample(x= chars, size= length(target), replace= T)
# Main program
while (fitness(parent) < fitness(target)) {
parent= evolve(parent)
cat(paste0(parent, collapse=""), "\n")
}

View file

@ -0,0 +1,60 @@
# Project : Evolutionary algorithm
# Date : 2018/03/28
# Author : Gal Zsolt [~ CalmoSoft ~]
# Email : <calmosoft@gmail.com>
target = "METHINKS IT IS LIKE A WEASEL"
parent = "IU RFSGJABGOLYWF XSMFXNIABKT"
num = 0
mutationrate = 0.5
children = len(target)
child = list(children)
while parent != target
bestfitness = 0
bestindex = 0
for index = 1 to children
child[index] = mutate(parent, mutationrate)
fitness = fitness(target, child[index])
if fitness > bestfitness
bestfitness = fitness
bestindex = index
ok
next
if bestindex > 0
parent = child[bestindex]
num = num + 1
see "" + num + ": " + parent + nl
ok
end
func fitness(text, ref)
f = 0
for i = 1 to len(text)
if substr(text, i, 1) = substr(ref, i, 1)
f = f + 1
ok
next
return (f / len(text))
func mutate(text, rate)
rnd = randomf()
if rate > rnd
c = 63+random(27)
if c = 64
c = 32
ok
rnd2 = random(len(text))
if rnd2 > 0
text[rnd2] = char(c)
ok
ok
return text
func randomf()
decimals(10)
str = "0."
for i = 1 to 10
nr = random(9)
str = str + string(nr)
next
return number(str)

View file

@ -0,0 +1,101 @@
//! Author : Thibault Barbie
//!
//! A simple evolutionary algorithm written in Rust.
extern crate rand;
use rand::Rng;
fn main() {
let target = "METHINKS IT IS LIKE A WEASEL";
let copies = 100;
let mutation_rate = 20; // 1/20 = 0.05 = 5%
let mut rng = rand::weak_rng();
// Generate first sentence, mutating each character
let start = mutate(&mut rng, target, 1); // 1/1 = 1 = 100%
println!("{}", target);
println!("{}", start);
evolve(&mut rng, target, start, copies, mutation_rate);
}
/// Evolution algorithm
///
/// Evolves `parent` to match `target`. Returns the number of evolutions performed.
fn evolve<R: Rng>(
rng: &mut R,
target: &str,
mut parent: String,
copies: usize,
mutation_rate: u32,
) -> usize {
let mut counter = 0;
let mut parent_fitness = target.len() + 1;
loop {
counter += 1;
let (best_fitness, best_sentence) = (0..copies)
.map(|_| {
// Copy and mutate a new sentence.
let sentence = mutate(rng, &parent, mutation_rate);
// Find the fitness of the new mutation
(fitness(target, &sentence), sentence)
})
.min_by_key(|&(f, _)| f) // find the closest mutation to the target
.unwrap(); // fails if `copies == 0`
// If the best mutation of this generation is better than `parent` then "the fittest
// survives" and the next parent becomes the best of this generation.
if best_fitness < parent_fitness {
parent = best_sentence;
parent_fitness = best_fitness;
println!(
"{} : generation {} with fitness {}",
parent, counter, best_fitness
);
if best_fitness == 0 {
return counter;
}
}
}
}
/// Computes the fitness of a sentence against a target string, returning the number of
/// incorrect characters.
fn fitness(target: &str, sentence: &str) -> usize {
sentence
.chars()
.zip(target.chars())
.filter(|&(c1, c2)| c1 != c2)
.count()
}
/// Mutation algorithm.
///
/// It mutates each character of a string, according to a `mutation_rate`.
fn mutate<R: Rng>(rng: &mut R, sentence: &str, mutation_rate: u32) -> String {
let maybe_mutate = |c| {
if rng.gen_weighted_bool(mutation_rate) {
random_char(rng)
} else {
c
}
};
sentence.chars().map(maybe_mutate).collect()
}
/// Generates a random letter or space.
fn random_char<R: Rng>(rng: &mut R) -> char {
// Returns a value in the range [A, Z] + an extra slot for the space character. (The `u8`
// values could be cast to larger integers for a better chance of the RNG hitting the proper
// range).
match rng.gen_range(b'A', b'Z' + 2) {
c if c == b'Z' + 1 => ' ', // the `char` after 'Z'
c => c as char,
}
}

View file

@ -0,0 +1,47 @@
String subclass: Mutant [
<shape: #character>
Target := Mutant from: 'METHINKS IT IS LIKE A WEASEL'.
Letters := ' ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
Mutant class >> run: c rate: p
["Run Evolutionary algorighm, using c copies and mutate rate p."
| pool parent |
parent := self newRandom.
pool := Array new: c+1.
[parent displayNl.
parent = Target] whileFalse:
[1 to: c do: [:i | pool at: i put: (parent copy mutate: p)].
pool at: c+1 put: parent.
parent := pool fold: [:winner :each | winner fittest: each]]]
Mutant class >> newRandom
[^(self new: Target size)
initializeToRandom;
yourself]
initializeToRandom
[self keys do: [:i | self at: i put: self randomLetter]]
mutate: p
[self keys do:
[:i |
Random next <= p ifTrue: [self at: i put: self randomLetter]]]
fitness
[| score |
score := 0.
self with: Target do:
[:me :you |
me = you ifTrue: [score := score + 1]].
^score]
fittest: aMutant
[^self fitness > aMutant fitness
ifTrue: [self]
ifFalse: [aMutant]]
randomLetter
[^Letters at: (Random between: 1 and: Letters size)]
]

View file

@ -0,0 +1,21 @@
st> Mutant run: 2500 rate: 0.1
QJUUIQHYXEZORSXGJCAHEWACH KG
QJUUIQHYXEZORSXGJCAHEWWCMSKG
QEUUIUHYXEZORSOGICAHYWWCSSKG
QETUIUHGXEZORS GICE YWWCSSEG
METUIUHSXOZORS OICE YWWCSSEG
METUIUHSXOZORS OICE Y WCSSEG
METUIUHSXOZMIS OIOE Y WCNSEG
METKIUKSTOFMIS LIOE Y WCNSEG
METKINKSTOFMIS LIKE E WCNSEG
METKINKSTOFMIS LIKE F WCNSEL
METHINKSTOF IS LIKE F WCNSEL
METHINKS OW IS LIKE F WCNSEL
METHINKS IW IS LIKE F WCNSEL
METHINKS IW IS LIKE C WCASEL
METHINKS IW IS LIKE C WCASEL
METHINKS IW IS LIKE A WCASEL
METHINKS IW IS LIKE A WCASEL
METHINKS IW IS LIKE A WEASEL
METHINKS IT IS LIKE A WEASEL
Mutant

View file

@ -1,116 +0,0 @@
Object subclass: Evolution [
|target parent mutateRate c alphabet fitness|
Evolution class >> newWithRate: rate andTarget: aTarget [
|r| r := super new.
^r initWithRate: rate andTarget: aTarget.
]
initWithRate: rate andTarget: aTarget [
target := aTarget.
self mutationRate: rate.
self maxCount: 100.
self defaultAlphabet.
self changeParent.
self fitness: (self defaultFitness).
^self
]
defaultFitness [
^ [:p :t |
|t1 t2 s|
t1 := p asOrderedCollection.
t2 := t asOrderedCollection.
s := 0.
t2 do: [:e| (e == (t1 removeFirst)) ifTrue: [ s:=s+1 ] ].
s / (target size)
]
]
defaultAlphabet [ alphabet := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' asOrderedCollection. ]
maxCount: anInteger [ c := anInteger ]
mutationRate: aFloat [ mutateRate := aFloat ]
changeParent [
parent := self generateStringOfLength: (target size) withAlphabet: alphabet.
^ parent.
]
generateStringOfLength: len withAlphabet: ab [
|r|
r := String new.
1 to: len do: [ :i |
r := r , ((ab at: (Random between: 1 and: (ab size))) asString)
].
^r
]
fitness: aBlock [ fitness := aBlock ]
randomCollection: d [
|r| r := OrderedCollection new.
1 to: d do: [:i|
r add: (Random next)
].
^r
]
mutate [
|r p nmutants s|
r := parent copy.
p := self randomCollection: (r size).
nmutants := (p select: [ :e | (e < mutateRate)]) size.
(nmutants > 0)
ifTrue: [ |t|
s := (self generateStringOfLength: nmutants withAlphabet: alphabet) asOrderedCollection.
t := 1.
(p collect: [ :e | e < mutateRate ]) do: [ :v |
v ifTrue: [ r at: t put: (s removeFirst) ].
t := t + 1.
]
].
^r
]
evolve [
|children es mi mv|
es := self getEvolutionStatus.
children := OrderedCollection new.
1 to: c do: [ :i |
children add: (self mutate)
].
children add: es.
mi := children size.
mv := fitness value: es value: target.
children doWithIndex: [:e :i|
(fitness value: e value: target) > mv
ifTrue: [ mi := i. mv := fitness value: e value: target ]
].
parent := children at: mi.
^es "returns the parent, not the evolution"
]
printgen: i [
('%1 %2 "%3"' % {i . (fitness value: parent value: target) . parent }) displayNl
]
evoluted [ ^ target = parent ]
getEvolutionStatus [ ^ parent ]
].
|organism j|
organism := Evolution newWithRate: 0.01 andTarget: 'METHINKS IT IS LIKE A WEASEL'.
j := 0.
[ organism evoluted ]
whileFalse: [
j := j + 1.
organism evolve.
((j rem: 20) = 0) ifTrue: [ organism printgen: j ]
].
organism getEvolutionStatus displayNl.