2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -8,11 +8,15 @@ Starting with:
:* Assess the <code>fitness</code> of the parent and all the copies to the <code>target</code> and make the most fit string the new <code>parent</code>, discarding the others.
:* repeat until the parent converges, (hopefully), to the target.
Cf: [[wp:Weasel_program#Weasel_algorithm|Weasel algorithm]] and [[wp:Evolutionary algorithm|Evolutionary algorithm]]
;Related tasks:
* &nbsp; [[wp:Weasel_program#Weasel_algorithm|Weasel algorithm]].
* &nbsp; [[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>
===========
<br>
A cursory examination of a few of the solutions reveals that the instructions have not been followed rigorously in some solutions. Specifically,
* While the <code>parent</code> is not yet the <code>target</code>:
:* copy the <code>parent</code> C times, each time allowing some random probability that another character might be substituted using <code>mutate</code>.
@ -33,3 +37,4 @@ As illustration of this error, the code for 8th has the following remark.
Clearly, this algo will be applying the mutation function only to the parent characters that don't match to the target characters!
To ensure that the new parent is never less fit than the prior parent, both the parent and all of the latest mutations are subjected to the fitness test to select the next parent.
<br><br>

View file

@ -0,0 +1,88 @@
identification division.
program-id. evolutionary-program.
data division.
working-storage section.
01 evolving-strings.
05 target pic a(28)
value 'METHINKS IT IS LIKE A WEASEL'.
05 parent pic a(28).
05 offspring-table.
10 offspring pic a(28)
occurs 50 times.
01 fitness-calculations.
05 fitness pic 99.
05 highest-fitness pic 99.
05 fittest pic 99.
01 parameters.
05 character-set pic a(27)
value 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '.
05 size-of-generation pic 99
value 50.
05 mutation-rate pic 99
value 5.
01 counters-and-working-variables.
05 character-position pic 99.
05 randomization.
10 random-seed pic 9(8).
10 random-number pic 99.
10 random-letter pic 99.
05 generation pic 999.
05 child pic 99.
05 temporary-string pic a(28).
procedure division.
control-paragraph.
accept random-seed from time.
move function random(random-seed) to random-number.
perform random-letter-paragraph,
varying character-position from 1 by 1
until character-position is greater than 28.
move temporary-string to parent.
move zero to generation.
perform output-paragraph.
perform evolution-paragraph,
varying generation from 1 by 1
until parent is equal to target.
stop run.
evolution-paragraph.
perform mutation-paragraph varying child from 1 by 1
until child is greater than size-of-generation.
move zero to highest-fitness.
move 1 to fittest.
perform check-fitness-paragraph varying child from 1 by 1
until child is greater than size-of-generation.
move offspring(fittest) to parent.
perform output-paragraph.
output-paragraph.
display generation ': ' parent.
random-letter-paragraph.
move function random to random-number.
divide random-number by 3.80769 giving random-letter.
add 1 to random-letter.
move character-set(random-letter:1)
to temporary-string(character-position:1).
mutation-paragraph.
move parent to temporary-string.
perform character-mutation-paragraph,
varying character-position from 1 by 1
until character-position is greater than 28.
move temporary-string to offspring(child).
character-mutation-paragraph.
move function random to random-number.
if random-number is less than mutation-rate
then perform random-letter-paragraph.
check-fitness-paragraph.
move offspring(child) to temporary-string.
perform fitness-paragraph.
fitness-paragraph.
move zero to fitness.
perform character-fitness-paragraph,
varying character-position from 1 by 1
until character-position is greater than 28.
if fitness is greater than highest-fitness
then perform fittest-paragraph.
character-fitness-paragraph.
if temporary-string(character-position:1) is equal to
target(character-position:1) then add 1 to fitness.
fittest-paragraph.
move fitness to highest-fitness.
move child to fittest.

View file

@ -0,0 +1,65 @@
#import system.
#import system'routines.
#import extensions.
#symbol Target = "METHINKS IT IS LIKE A WEASEL".
#symbol AllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ".
#symbol C = 100.
#symbol P = 0.05r.
#symbol rnd = randomGenerator.
#symbol randomChar
= AllowedCharacters @ (rnd nextInt:(AllowedCharacters length)).
#class(extension) evoHelper
{
#method randomString
= 0 repeat &till:self &each:x [ randomChar ] summarize:(String new) literal.
#method fitness &of:s
= self zip:s &into:(:a:b)[ (a == b)iif:1:0 ] summarize:(Integer new) int.
#method mutate : p
= self select &each: ch [ (rnd nextReal <= p) iif:randomChar:ch ] summarize:(String new) literal.
}
#class EvoAlgorithm :: Enumerator
{
#field theTarget.
#field theCurrent.
#field theVariantCount.
#constructor new : s &of:count
[
theTarget := s.
theVariantCount := count int.
]
#method get = theCurrent.
#method next
[
($nil == theCurrent)
? [ theCurrent := theTarget length randomString. ^ true. ].
(theTarget == theCurrent)
? [ ^ false. ].
#var variants := Array new:theVariantCount set &every:(&index:x) [ theCurrent mutate:P ].
theCurrent := variants array sort:(:a:b) [ a fitness &of:Target > b fitness &of:Target ] getAt:0.
^ true.
]
}
#symbol program =
[
#var attempt := Integer new.
EvoAlgorithm new:Target &of:C run &each:current
[
console
writeLiteral:"#":(attempt += 1) &paddingLeft:10
writeLine:" ":current:" fitness: ":(current fitness &of:Target).
].
].

View file

@ -0,0 +1,63 @@
defmodule Log do
def show(offspring,i) do
IO.puts "Generation: #{i}, Offspring: #{offspring}"
end
def found({target,i}) do
IO.puts "#{target} found in #{i} iterations"
end
end
defmodule Evolution do
# char list from A to Z; 32 is the ord value for space.
@chars [32 | Enum.to_list(?A..?Z)]
def select(target) do
(1..String.length(target)) # Creates parent for generation 0.
|> Enum.map(fn _-> Enum.random(@chars) end)
|> mutate(to_char_list(target),0)
|> Log.found
end
# w is used to denote fitness in population genetics.
defp mutate(parent,target,i) when target == parent, do: {parent,i}
defp mutate(parent,target,i) do
w = fitness(parent,target)
prev = reproduce(target,parent,mu_rate(w))
# Check if the most fit member of the new gen has a greater fitness than the parent.
if w < fitness(prev,target) do
parent = prev
Log.show(parent,i)
end
mutate(parent,target,i+1)
end
# Generate 100 offspring and select the one with the greatest fitness.
defp reproduce(target,parent,rate) do
[parent | Enum.map(1..100, fn _-> mutation(parent,rate) end)]
|> Enum.max_by(fn n -> fitness(n,target) end)
end
# Calculate fitness by checking difference between parent and offspring chars.
defp fitness(t,r) do
Enum.zip(t,r)
|> Enum.reduce(0, fn {tn,rn},sum -> abs(tn - rn) + sum end)
|> calc
end
# Generate offspring based on parent.
defp mutation(p,r) do
# Copy the parent chars, then check each val against the random mutation rate
Enum.map(p, fn n -> if :rand.uniform <= r, do: Enum.random(@chars), else: n end)
end
defp calc(sum), do: 100 * :math.exp(sum/-10)
defp mu_rate(n), do: 1 - :math.exp(-(100-n)/400)
end
Evolution.select("METHINKS IT IS LIKE A WEASEL")

View file

@ -0,0 +1,46 @@
target="METHINKS IT IS LIKE A WEASEL";
fitness(s)=-dist(Vec(s),Vec(target));
dist(u,v)=sum(i=1,min(#u,#v),u[i]!=v[i])+abs(#u-#v);
letter()=my(r=random(27)); if(r==26, " ", Strchr(r+65));
insert(v,x=letter())=
{
my(r=random(#v+1));
if(r==0, return(concat([x],v)));
if(r==#v, return(concat(v,[x])));
concat(concat(v[1..r],[x]),v[r+1..#v]);
}
delete(v)=
{
if(#v<2, return([]));
my(r=random(#v)+1);
if(r==1, return(v[2..#v]));
if(r==#v, return(v[1..#v-1]));
concat(v[1..r-1],v[r+1..#v]);
}
mutate(s,rateM,rateI,rateD)=
{
my(v=Vec(s));
if(random(1.)<rateI, v=insert(v));
if(random(1.)<rateD, v=delete(v));
for(i=1,#v,
if(random(1.)<rateM, v[i]=letter())
);
concat(v);
}
evolve(C,rate)=
{
my(parent=concat(vector(#target,i,letter())),ct=0);
while(parent != target,
print(parent" "fitness(parent));
my(v=vector(C,i,mutate(parent,rate,0,0)),best,t);
best=fitness(parent=v[1]);
for(i=2,C,
t=fitness(v[i]);
if(t>best, best=t; parent=v[i])
);
ct++
);
print(parent" "fitness(parent));
ct;
}
evolve(35,.05)

View file

@ -1,69 +1,71 @@
Define.i Pop = 100 ,Mrate = 6
Define.s targetS = "METHINKS IT IS LIKE A WEASEL"
Define.s CsetS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
Define population = 100, mutationRate = 6
Define.s target$ = "METHINKS IT IS LIKE A WEASEL"
Define.s charSet$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
Procedure.i fitness (Array aspirant.c(1),Array target.c(1))
Protected.i i ,len, fit
Procedure.i fitness(Array aspirant.c(1), Array target.c(1))
Protected i, len, fit
len = ArraySize(aspirant())
For i=0 To len
If aspirant(i)=target(i): fit +1: EndIf
For i = 0 To len
If aspirant(i) = target(i): fit +1: EndIf
Next
ProcedureReturn fit
EndProcedure
Procedure mutatae(Array parent.c(1),Array child.c(1),Array CsetA.c(1),rate.i)
Protected i.i ,L.i,maxC
Procedure mutatae(Array parent.c(1), Array child.c(1), Array charSetA.c(1), rate.i)
Protected i, L, maxC
L = ArraySize(child())
maxC = ArraySize(CsetA())
maxC = ArraySize(charSetA())
For i = 0 To L
If Random(100) < rate
child(i)= CsetA(Random(maxC))
child(i) = charSetA(Random(maxC))
Else
child(i)=parent(i)
child(i) = parent(i)
EndIf
Next
EndProcedure
Procedure.s Carray2String(Array A.c(1))
Protected S.s ,len.i
len = ArraySize(A())+1 : S = LSet("",len," ")
CopyMemory(@A(0),@S, len *SizeOf(Character))
Procedure.s cArray2string(Array A.c(1))
Protected S.s, len
len = ArraySize(A())+1 : S = Space(len)
CopyMemory(@A(0), @S, len * SizeOf(Character))
ProcedureReturn S
EndProcedure
Define.i Mrate , maxC ,Tlen ,i ,maxfit ,gen ,fit,bestfit
Dim targetA.c(Len(targetS)-1)
CopyMemory(@targetS, @targetA(0), StringByteLength(targetS))
Define mutationRate, maxChar, target_len, i, maxfit, gen, fit, bestfit
Dim targetA.c(Len(target$) - 1)
CopyMemory(@target$, @targetA(0), StringByteLength(target$))
Dim CsetA.c(Len(CsetS)-1)
CopyMemory(@CsetS, @CsetA(0), StringByteLength(CsetS))
Dim charSetA.c(Len(charSet$) - 1)
CopyMemory(@charSet$, @charSetA(0), StringByteLength(charSet$))
maxC = Len(CsetS)-1
maxfit = Len(targetS)
Tlen = Len(targetS)-1
Dim parent.c(Tlen)
Dim child.c(Tlen)
Dim Bestchild.c(Tlen)
maxChar = Len(charSet$) - 1
maxfit = Len(target$)
target_len = Len(target$) - 1
Dim parent.c(target_len)
Dim child.c(target_len)
Dim Bestchild.c(target_len)
For i = 0 To Tlen
parent(i)= CsetA(Random(maxC))
For i = 0 To target_len
parent(i) = charSetA(Random(maxChar))
Next
fit = fitness (parent(),targetA())
fit = fitness (parent(), targetA())
OpenConsole()
PrintN(Str(gen)+": "+Carray2String(parent())+" Fitness= "+Str(fit)+"/"+Str(maxfit))
PrintN(Str(gen) + ": " + cArray2string(parent()) + ": Fitness= " + Str(fit) + "/" + Str(maxfit))
While bestfit <> maxfit
gen +1 :
For i = 1 To Pop
mutatae(parent(),child(),CsetA(),Mrate)
fit = fitness (child(),targetA())
gen + 1
For i = 1 To population
mutatae(parent(),child(),charSetA(), mutationRate)
fit = fitness (child(), targetA())
If fit > bestfit
bestfit = fit : Swap Bestchild() , child()
bestfit = fit: CopyArray(child(), Bestchild())
EndIf
Next
Swap parent() , Bestchild()
PrintN(Str(gen)+": "+Carray2String(parent())+" Fitness= "+Str(bestfit)+"/"+Str(maxfit))
CopyArray(Bestchild(), parent())
PrintN(Str(gen) + ": " + cArray2string(parent()) + ": Fitness= " + Str(bestfit) + "/" + Str(maxfit))
Wend
PrintN("Press any key to exit"): Repeat: Until Inkey() <> ""

View file

@ -1,34 +1,33 @@
/*REXX program demonstrates an evolutionary algorithm (by using mutation). */
parse arg children MR seed . /*get optional arguments from the C.L. */
if children=='' then children = 10 /*# children produced each generation. */
if MR =='' then MR = '4%' /*the character Mutation Rate each gen.*/
if right(MR,1)=='%' then MR=strip(MR,,'%')/100 /*expressed as %? Then adjust*/
if seed\=='' then call random ,,seed /*SEED allow the runs to be repeatable.*/
/*REXX program demonstrates an evolutionary algorithm (by using mutation). */
parse arg children MR seed . /*get optional arguments from the C.L. */
if children=='' then children = 10 /*# children produced each generation. */
if MR =='' then MR = "4%" /*the character Mutation Rate each gen.*/
if right(MR,1)=='%' then MR=strip(MR,,"%")/100 /*expressed as a percent? Then adjust.*/
if seed\=='' then call random ,,seed /*SEED allow the runs to be repeatable.*/
abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' ; Labc=length(abc)
target= 'METHINKS IT IS LIKE A WEASEL' ; Ltar=length(target)
parent= mutate( left('',Ltar), 1) /*gen rand string,same length as target*/
say center('target string',Ltar,'') "children" 'mutationRate'
say target center(children,8) center((MR*100/1)'%',12); say
say center('new string',Ltar,'') "closeness" 'generation'
parent= mutate( left('',Ltar), 1) /*gen rand string,same length as target*/
say center('target string', Ltar, "") 'children' "mutationRate"
say target center(children,8) center((MR*100/1)'%', 12); say
say center('new string' ,Ltar, "") "closeness" 'generation'
do gen=0 until parent==target; close=fitness(parent)
do gen=0 until parent==target; close=fitness(parent)
almost=parent
do children; child=mutate(parent,MR)
_=fitness(child); if _<=close then iterate
close=_; almost=child
say almost right(close,9) right(gen,10)
end /*children*/
do children; child=mutate(parent,MR)
_=fitness(child); if _<=close then iterate
close=_; almost=child
say almost right(close, 9) right(gen,10)
end /*children*/
parent=almost
end /*gen*/
exit /*stick a fork in it, we're all done. */
/*────────────────────────────────────────────────────────────────────────────*/
fitness: parse arg x; $=0
do k=1 for Ltar; $=$+(substr(x,k,1)==substr(target,k,1)); end /*k*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
fitness: parse arg x; $=0; do k=1 for Ltar; $=$+(substr(x,k,1)==substr(target,k,1)); end
return $
/*────────────────────────────────────────────────────────────────────────────*/
mutate: parse arg x,rate $ /*set X to 1st argument, RATE to 2nd.*/
$=; do j=1 for Ltar; r=random(1,100000) /*REXX's max.*/
if .00001*r<=rate then $=$ || substr(abc,r//Labc+1,1)
else $=$ || substr(x,j,1)
/*──────────────────────────────────────────────────────────────────────────────────────*/
mutate: parse arg x,rate; $= /*set X to 1st argument, RATE to 2nd.*/
do j=1 for Ltar; r=random(1,100000) /*REXX's max for RANSOM*/
if .00001*r<=rate then $=$ || substr(abc,r//Labc+1, 1)
else $=$ || substr(x ,j , 1)
end /*j*/
return $

View file

@ -1,43 +1,42 @@
/*REXX program demonstrates an evolutionary algorithm (by using mutation). */
parse arg children MR seed . /*get optional arguments from the C.L. */
if children=='' then children = 10 /*# children produced each generation. */
if MR =='' then MR = '4%' /*the character Mutation Rate each gen.*/
if right(MR,1)=='%' then MR=strip(MR,,'%')/100 /*expressed as %? Then adjust*/
if seed\=='' then call random ,,seed /*SEED allow the runs to be repeatable.*/
/*REXX program demonstrates an evolutionary algorithm (by using mutation). */
parse arg children MR seed . /*get optional arguments from the C.L. */
if children=='' then children = 10 /*# children produced each generation. */
if MR =='' then MR = "4%" /*the character Mutation Rate each gen.*/
if right(MR,1)=='%' then MR=strip(MR,,"%")/100 /*expressed as a percent? Then adjust.*/
if seed\=='' then call random ,,seed /*SEED allow the runs to be repeatable.*/
abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '; Labc=length(abc)
do i=0 for Labc /*define array (for faster compare), */
@.i=substr(abc,i+1,1) /* it's better than picking out a */
end /*i*/ /* byte from a character string. */
do i=0 for Labc /*define array (for faster compare), */
@.i=substr(abc, i+1, 1) /* it's better than picking out a */
end /*i*/ /* byte from a character string. */
target= 'METHINKS IT IS LIKE A WEASEL' ; Ltar=length(target)
do i=1 for Ltar /*define an array (for faster compare),*/
T.i=substr(target,i,1) /* it's better than a byte-by-byte */
end /*i*/ /* compare using character strings.*/
do i=1 for Ltar /*define an array (for faster compare),*/
T.i=substr(target, i, 1) /* it's better than a byte-by-byte */
end /*i*/ /* compare using character strings.*/
parent= mutate( left('',Ltar), 1) /*gen rand string, same length as tar. */
say center('target string',Ltar,'') "children" 'mutationRate'
say target center(children,8) center((MR*100/1)'%',12); say
say center('new string',Ltar,'') "closeness" 'generation'
parent= mutate( left('', Ltar), 1) /*gen rand string, same length as tar. */
say center('target string', Ltar, "") 'children' "mutationRate"
say target center(children, 8) center((MR*100/1)'%',12); say
say center('new string' , Ltar, "") 'closeness' "generation"
do gen=0 until parent==target; close=fitness(parent)
do gen=0 until parent==target; close=fitness(parent)
almost=parent
do children; child=mutate(parent,MR)
_=fitness(child); if _<=close then iterate
close=_; almost=child
say almost right(close,9) right(gen,10)
do children; child=mutate(parent,MR)
_=fitness(child); if _<=close then iterate
close=_; almost=child
say almost right(close, 9) right(gen, 10)
end /*children*/
parent=almost
end /*gen*/
exit /*stick a fork in it, we're all done. */
/*────────────────────────────────────────────────────────────────────────────*/
fitness: parse arg x; $=0; do k=1 for Ltar; $=$+(substr(x,k,1)==T.k); end
return $
/*────────────────────────────────────────────────────────────────────────────*/
mutate: parse arg x,rate /*set X to 1st argument, RATE to 2nd.*/
$=; do j=1 for Ltar; r=random(1,100000) /*REXX's max.*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
fitness: parse arg x; $=0; do k=1 for Ltar; $=$+(substr(x,k,1)==T.k); end; return $
/*──────────────────────────────────────────────────────────────────────────────────────*/
mutate: parse arg x,rate /*set X to 1st argument, RATE to 2nd.*/
$=; do j=1 for Ltar; r=random(1, 100000) /*REXX's max for RANDOM*/
if .00001*r<=rate then do; _=r//Labc; $=$ || @._; end
else $=$ || substr(x,j,1)
else $=$ || substr(x, j, 1)
end /*j*/
return $