A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
|
|
@ -0,0 +1,56 @@
|
|||
class Main
|
||||
{
|
||||
static const Str target := "METHINKS IT IS LIKE A WEASEL"
|
||||
static const Int C := 100 // size of population
|
||||
static const Float p := 0.1f // chance any char is mutated
|
||||
|
||||
// compute distance of str from target
|
||||
static Int fitness (Str str)
|
||||
{
|
||||
Int sum := 0
|
||||
str.each |Int c, Int index|
|
||||
{
|
||||
if (c != target[index]) sum += 1
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
// mutate given parent string
|
||||
static Str mutate (Str str)
|
||||
{
|
||||
Str result := ""
|
||||
str.size.times |Int index|
|
||||
{
|
||||
result += ((Float.random < p) ? randomChar() : str[index]).toChar
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// return a random char
|
||||
static Int randomChar ()
|
||||
{
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ "[Int.random(0..26)]
|
||||
}
|
||||
|
||||
// make population by mutating parent and sorting by fitness
|
||||
static Str[] makePopulation (Str parent)
|
||||
{
|
||||
Str[] result := [,]
|
||||
C.times { result.add (mutate(parent)) }
|
||||
result.sort |Str a, Str b -> Int| { fitness(a) <=> fitness(b) }
|
||||
return result
|
||||
}
|
||||
|
||||
public static Void main ()
|
||||
{
|
||||
Str parent := ""
|
||||
target.size.times { parent += randomChar().toChar }
|
||||
|
||||
while (parent != target)
|
||||
{
|
||||
echo (parent)
|
||||
parent = makePopulation(parent).first
|
||||
}
|
||||
echo (parent)
|
||||
}
|
||||
}
|
||||
51
Task/Evolutionary-algorithm/Icon/evolutionary-algorithm.icon
Normal file
51
Task/Evolutionary-algorithm/Icon/evolutionary-algorithm.icon
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
global target, chars, parent, C, M, current_fitness
|
||||
|
||||
procedure fitness(s)
|
||||
fit := 0
|
||||
#Increment the fitness for every position in the string s that matches the target
|
||||
every i := 1 to *target & s[i] == target[i] do fit +:= 1
|
||||
return fit
|
||||
end
|
||||
|
||||
procedure mutate(s)
|
||||
#If a random number between 0 and 1 is inside the bounds of mutation randomly alter a character in the string
|
||||
if (?0 <= M) then ?s := ?chars
|
||||
return s
|
||||
end
|
||||
|
||||
procedure generation()
|
||||
population := [ ]
|
||||
next_parent := ""
|
||||
next_fitness := -1
|
||||
|
||||
#Create the next population
|
||||
every 1 to C do push(population, mutate(parent))
|
||||
#Find the member of the population with highest fitness, or use the last one inspected
|
||||
every x := !population & (xf := fitness(x)) > next_fitness do {
|
||||
next_parent := x
|
||||
next_fitness := xf
|
||||
}
|
||||
|
||||
parent := next_parent
|
||||
|
||||
return next_fitness
|
||||
end
|
||||
|
||||
procedure main()
|
||||
target := "METHINKS IT IS LIKE A WEASEL" #Our target string
|
||||
chars := &ucase ++ " " #Set of usable characters
|
||||
parent := "" & every 1 to *target do parent ||:= ?chars #The universal common ancestor!
|
||||
current_fitness := fitness(parent) #The best fitness we have so far
|
||||
|
||||
|
||||
C := 50 #Population size in each generation
|
||||
M := 0.5 #Mutation rate per individual in a generation
|
||||
|
||||
gen := 1
|
||||
#Until current fitness reaches a score of perfect match with the target string keep generating new populations
|
||||
until ((current_fitness := generation()) = *target) do {
|
||||
write(gen || " " || current_fitness || " " || parent)
|
||||
gen +:= 1
|
||||
}
|
||||
write("At generation " || gen || " we found a string with perfect fitness at " || current_fitness || " reading: " || parent)
|
||||
end
|
||||
14
Task/Evolutionary-algorithm/J/evolutionary-algorithm-1.j
Normal file
14
Task/Evolutionary-algorithm/J/evolutionary-algorithm-1.j
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
CHARSET=: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '
|
||||
NPROG=: 100 NB. number of progeny (C)
|
||||
MRATE=: 0.05 NB. mutation rate
|
||||
|
||||
create =: (?@$&$ { ])&CHARSET NB. creates random list from charset of same shape as y
|
||||
fitness =: +/@:~:"1
|
||||
copy =: # ,:
|
||||
mutate =: &(>: $ ?@$ 0:)(`(,: create))} NB. adverb
|
||||
select =: ] {~ (i. <./)@:fitness NB. select fittest member of population
|
||||
|
||||
nextgen =: select ] , [: MRATE mutate NPROG copy ]
|
||||
while =: conjunction def '(] , (u {:))^:(v {:)^:_ ,:'
|
||||
|
||||
evolve=: nextgen while (0 < fitness) create
|
||||
6
Task/Evolutionary-algorithm/J/evolutionary-algorithm-2.j
Normal file
6
Task/Evolutionary-algorithm/J/evolutionary-algorithm-2.j
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
filter=: {: ,~ ({~ i.@>.&.(%&20)@#) NB. take every 20th and last item
|
||||
filter evolve 'METHINKS IT IS LIKE A WEASEL'
|
||||
XXURVQXKQXDLCGFVICCUA NUQPND
|
||||
MEFHINVQQXT IW LIKEUA WEAPEL
|
||||
METHINVS IT IW LIKEUA WEAPEL
|
||||
METHINKS IT IS LIKE A WEASEL
|
||||
27
Task/Evolutionary-algorithm/J/evolutionary-algorithm-3.j
Normal file
27
Task/Evolutionary-algorithm/J/evolutionary-algorithm-3.j
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
CHARSET=: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '
|
||||
NPROG=: 100 NB. "C" from specification
|
||||
|
||||
fitness=: +/@:~:"1
|
||||
select=: ] {~ (i. <./)@:fitness NB. select fittest member of population
|
||||
populate=: (?@$&# { ])&CHARSET NB. get random list from charset of same length as y
|
||||
log=: [: smoutput [: ;:inv (('#';'fitness: ';'; ') ,&.> ":&.>)
|
||||
|
||||
mutate=: dyad define
|
||||
idxmut=. I. x >: (*/$y) ?@$ 0
|
||||
(populate idxmut) idxmut"_} y
|
||||
)
|
||||
|
||||
evolve=: monad define
|
||||
target=. y
|
||||
parent=. populate y
|
||||
iter=. 0
|
||||
mrate=. %#y
|
||||
while. 0 < val=. target fitness parent do.
|
||||
if. 0 = 50|iter do. log iter;val;parent end.
|
||||
iter=. iter + 1
|
||||
progeny=. mrate mutate NPROG # ,: parent NB. create progeny by mutating parent copies
|
||||
parent=. target select parent,progeny NB. select fittest parent for next generation
|
||||
end.
|
||||
log iter;val;parent
|
||||
parent
|
||||
)
|
||||
5
Task/Evolutionary-algorithm/J/evolutionary-algorithm-4.j
Normal file
5
Task/Evolutionary-algorithm/J/evolutionary-algorithm-4.j
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
evolve 'METHINKS IT IS LIKE A WEASEL'
|
||||
#0 fitness: 27 ; YGFDJFTBEDB FAIJJGMFKDPYELOA
|
||||
#50 fitness: 2 ; MEVHINKS IT IS LIKE ADWEASEL
|
||||
#76 fitness: 0 ; METHINKS IT IS LIKE A WEASEL
|
||||
METHINKS IT IS LIKE A WEASEL
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
C = 10
|
||||
'mutaterate has to be greater than 1 or it will not mutate
|
||||
mutaterate = 2
|
||||
mutationstaken = 0
|
||||
generations = 0
|
||||
Dim parentcopies$((C - 1))
|
||||
Global targetString$ : targetString$ = "METHINKS IT IS LIKE A WEASEL"
|
||||
Global allowableCharacters$ : allowableCharacters$ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
currentminFitness = Len(targetString$)
|
||||
|
||||
For i = 1 To Len(targetString$)
|
||||
parent$ = parent$ + Mid$(allowableCharacters$, Int(Rnd(1) * Len(allowableCharacters$)), 1)
|
||||
Next i
|
||||
|
||||
Print "Parent = " + parent$
|
||||
|
||||
While parent$ <> targetString$
|
||||
generations = (generations + 1)
|
||||
For i = 0 To (C - 1)
|
||||
parentcopies$(i) = mutate$(parent$, mutaterate)
|
||||
mutationstaken = (mutationstaken + 1)
|
||||
Next i
|
||||
For i = 0 To (C - 1)
|
||||
currentFitness = Fitness(targetString$, parentcopies$(i))
|
||||
If currentFitness = 0 Then
|
||||
parent$ = parentcopies$(i)
|
||||
Exit For
|
||||
Else
|
||||
If currentFitness < currentminFitness Then
|
||||
currentminFitness = currentFitness
|
||||
parent$ = parentcopies$(i)
|
||||
End If
|
||||
End If
|
||||
Next i
|
||||
CLS
|
||||
Print "Generation - " + str$(generations)
|
||||
Print "Parent - " + parent$
|
||||
Scan
|
||||
Wend
|
||||
|
||||
Print
|
||||
Print "Congratulations to me; I finished!"
|
||||
Print "Final Mutation: " + parent$
|
||||
'The ((i + 1) - (C)) reduces the total number of mutations that it took by one generation
|
||||
'minus the perfect child mutation since any after that would not have been required.
|
||||
Print "Total Mutations Taken - " + str$(mutationstaken - ((i + 1) - (C)))
|
||||
Print "Total Generations Taken - " + str$(generations)
|
||||
Print "Child Number " + str$(i) + " has perfect similarities to your target."
|
||||
End
|
||||
|
||||
|
||||
|
||||
Function mutate$(mutate$, mutaterate)
|
||||
If (Rnd(1) * mutaterate) > 1 Then
|
||||
'The mutatingcharater randomizer needs 1 more than the length of the string
|
||||
'otherwise it will likely take forever to get exactly that as a random number
|
||||
mutatingcharacter = Int(Rnd(1) * (Len(targetString$) + 1))
|
||||
mutate$ = Left$(mutate$, (mutatingcharacter - 1)) + Mid$(allowableCharacters$, Int(Rnd(1) * Len(allowableCharacters$)), 1) _
|
||||
+ Mid$(mutate$, (mutatingcharacter + 1))
|
||||
End If
|
||||
End Function
|
||||
|
||||
Function Fitness(parent$, offspring$)
|
||||
For i = 1 To Len(targetString$)
|
||||
If Mid$(parent$, i, 1) <> Mid$(offspring$, i, 1) Then
|
||||
Fitness = (Fitness + 1)
|
||||
End If
|
||||
Next i
|
||||
End Function
|
||||
44
Task/Evolutionary-algorithm/Logo/evolutionary-algorithm.logo
Normal file
44
Task/Evolutionary-algorithm/Logo/evolutionary-algorithm.logo
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
make "target "|METHINKS IT IS LIKE A WEASEL|
|
||||
|
||||
to distance :w
|
||||
output reduce "sum (map.se [ifelse equal? ?1 ?2 [0][1]] :w :target)
|
||||
end
|
||||
|
||||
to random.letter
|
||||
output pick "| ABCDEFGHIJKLMNOPQRSTUVWXYZ|
|
||||
end
|
||||
|
||||
to mutate :parent :rate
|
||||
output map [ifelse random 100 < :rate [random.letter] [?]] :parent
|
||||
end
|
||||
|
||||
make "C 100
|
||||
make "mutate.rate 10 ; percent
|
||||
|
||||
to breed :parent
|
||||
make "parent.distance distance :parent
|
||||
localmake "best.child :parent
|
||||
repeat :C [
|
||||
localmake "child mutate :parent :mutate.rate
|
||||
localmake "child.distance distance :child
|
||||
if greater? :parent.distance :child.distance [
|
||||
make "parent.distance :child.distance
|
||||
make "best.child :child
|
||||
]
|
||||
]
|
||||
output :best.child
|
||||
end
|
||||
|
||||
to progress
|
||||
output (sentence :trials :parent "distance: :parent.distance)
|
||||
end
|
||||
|
||||
to evolve
|
||||
make "parent cascade count :target [lput random.letter ?] "||
|
||||
make "trials 0
|
||||
while [not equal? :parent :target] [
|
||||
make "parent breed :parent
|
||||
print progress
|
||||
make "trials :trials + 1
|
||||
]
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
target = "METHINKS IT IS LIKE A WEASEL";
|
||||
alphabet = CharacterRange["A", "Z"]~Join~{" "};
|
||||
fitness = HammingDistance[target, #] &;
|
||||
Mutate[parent_String, rate_: 0.01, fertility_Integer: 25] := Module[
|
||||
{offspring, kidfits, gen = 0, alphabet = CharacterRange["A", "Z"]~Join~{" "}},
|
||||
offspring = ConstantArray[Characters[parent], fertility];
|
||||
Table[
|
||||
If[RandomReal[] <= rate, offspring[[j, k]] = RandomChoice[alphabet]],
|
||||
{j, fertility}, {k, StringLength@parent}
|
||||
];
|
||||
offspring = StringJoin[#] & /@ offspring;
|
||||
kidfits = fitness[#] & /@ Flatten[{offspring, parent}];
|
||||
Return[offspring[[First@Ordering[kidfits]]]];
|
||||
];
|
||||
|
||||
mutationRate = 0.02;
|
||||
parent = StringJoin[ alphabet[[RandomInteger[{1, Length@alphabet}, StringLength@target]]] ];
|
||||
results = NestWhileList[Mutate[#, mutationRate, 100] &, parent, fitness[#] > 0 &];
|
||||
fits = fitness[#] & /@ results;
|
||||
results = Transpose[{results, fits}];
|
||||
TableForm[results[[;; ;; 2]], TableHeadings->{Range[1, Length@results, 2],{"String","Fitness"}}, TableSpacing -> {1, 2}]
|
||||
Loading…
Add table
Add a link
Reference in a new issue