117 lines
2.8 KiB
Smalltalk
117 lines
2.8 KiB
Smalltalk
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.
|