September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -9,7 +9,7 @@ Starting with:
|
|||
:* repeat until the parent converges, (hopefully), to the target.
|
||||
|
||||
|
||||
;Related tasks:
|
||||
;See also:
|
||||
* [[wp:Weasel_program#Weasel_algorithm|Weasel algorithm]].
|
||||
* [[wp:Evolutionary algorithm|Evolutionary algorithm]].
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
set target=M E T H I N K S @ I T @ I S @ L I K E @ A @ W E A S E L
|
||||
set chars=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z @
|
||||
|
||||
set tempcount=0
|
||||
for %%i in (%target%) do (
|
||||
set /a tempcount+=1
|
||||
set target!tempcount!=%%i
|
||||
)
|
||||
call:parent
|
||||
|
||||
echo %target%
|
||||
echo --------------------------------------------------------
|
||||
|
||||
:loop
|
||||
call:fitness parent
|
||||
set currentfit=%errorlevel%
|
||||
if %currentfit%==28 goto end
|
||||
echo %parent% - %currentfit% [%attempts%]
|
||||
set attempts=0
|
||||
|
||||
:innerloop
|
||||
set /a attempts+=1
|
||||
title Attemps - %attempts%
|
||||
call:mutate %parent%
|
||||
call:fitness tempparent
|
||||
set newfit=%errorlevel%
|
||||
if %newfit% gtr %currentfit% (
|
||||
set tempcount=0
|
||||
set "parent="
|
||||
for %%i in (%tempparent%) do (
|
||||
set /a tempcount+=1
|
||||
set parent!tempcount!=%%i
|
||||
set parent=!parent! %%i
|
||||
)
|
||||
goto loop
|
||||
)
|
||||
goto innerloop
|
||||
|
||||
:end
|
||||
echo %parent% - %currentfit% [%attempts%]
|
||||
echo Done.
|
||||
exit /b
|
||||
|
||||
:parent
|
||||
set "parent="
|
||||
for /l %%i in (1,1,28) do (
|
||||
set /a charchosen=!random! %% 27 + 1
|
||||
set tempcount=0
|
||||
for %%j in (%chars%) do (
|
||||
set /a tempcount+=1
|
||||
if !charchosen!==!tempcount! (
|
||||
set parent%%i=%%j
|
||||
set parent=!parent! %%j
|
||||
)
|
||||
)
|
||||
)
|
||||
exit /b
|
||||
|
||||
:fitness
|
||||
set fitness=0
|
||||
set array=%1
|
||||
for /l %%i in (1,1,28) do if !%array%%%i!==!target%%i! set /a fitness+=1
|
||||
exit /b %fitness%
|
||||
|
||||
:mutate
|
||||
set tempcount=0
|
||||
set returnarray=tempparent
|
||||
set "%returnarray%="
|
||||
for %%i in (%*) do (
|
||||
set /a tempcount+=1
|
||||
set %returnarray%!tempcount!=%%i
|
||||
set %returnarray%=!%returnarray%! %%i
|
||||
)
|
||||
set /a tomutate=%random% %% 28 + 1
|
||||
set /a mutateto=%random% %% 27 + 1
|
||||
set tempcount=0
|
||||
for %%i in (%chars%) do (
|
||||
set /a tempcount+=1
|
||||
if %mutateto%==!tempcount! (
|
||||
set %returnarray%!tomutate!=%%i
|
||||
)
|
||||
)
|
||||
set "%returnarray%="
|
||||
for /l %%i in (1,1,28) do set %returnarray%=!%returnarray%! !%returnarray%%%i!
|
||||
exit /b
|
||||
|
|
@ -97,8 +97,7 @@ int main()
|
|||
{
|
||||
std::cout << parent << ": " << fitness << "\n";
|
||||
double const mutation_rate = 0.02 + (0.9*fitness)/initial_fitness;
|
||||
typedef std::vector<std::string> childvec;
|
||||
childvec childs;
|
||||
std::vector<std::string> childs;
|
||||
childs.reserve(C+1);
|
||||
|
||||
childs.push_back(parent);
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
import std.stdio, std.random, std.algorithm, std.range, std.ascii;
|
||||
|
||||
void evolve(string target, double prob=0.05, int C=100) {
|
||||
auto chars = uppercase ~ " ";
|
||||
char rndCh() { return chars[uniform(0, $)]; }
|
||||
void mutate(char[] parent, char[] child) {
|
||||
foreach (i, ref c; child)
|
||||
c = uniform(0.0, 1.0) < prob ? rndCh() : parent[i];
|
||||
}
|
||||
int fitness(char[] subject, string target) {
|
||||
return count!q{ a[0] != a[1] }(zip(subject, target));
|
||||
}
|
||||
auto parent= map!(i => rndCh())(target).array();
|
||||
auto best = parent.dup;
|
||||
auto child = new char[target.length];
|
||||
int currDist = fitness(parent, target);
|
||||
for (int gen; currDist > 0; gen++) {
|
||||
foreach (_; 0 .. C) {
|
||||
mutate(parent, child);
|
||||
int dist = fitness(child, target);
|
||||
if (dist < currDist) {
|
||||
currDist = dist;
|
||||
best[] = child[];
|
||||
}
|
||||
}
|
||||
parent = best;
|
||||
writefln("Generation %2s, dist=%2s: %s", gen, currDist, best);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
evolve("METHINKS IT IS LIKE A WEASEL");
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import std.stdio, std.random, std.algorithm, std.range;
|
||||
|
||||
enum target = "METHINKS IT IS LIKE A WEASEL"d;
|
||||
enum C = 100; // Number of children in each generation.
|
||||
enum P = 0.05; // Mutation probability.
|
||||
auto alphabet = " ABCDEFGHIJLKLMNOPQRSTUVWXYZ"d.dup;
|
||||
const fitness = (dchar[] s) => count!"a[0] != a[1]"(zip(s, target));
|
||||
const rndc = () => alphabet[uniform(0, $)];
|
||||
const mutate = (dchar[] s) =>
|
||||
s.map!(a => uniform(0., 1.) < P ? rndc() : a)().array();
|
||||
|
||||
void main() {
|
||||
auto parent = target.length.iota().map!(_ => rndc())().array();
|
||||
for (int gen = 1; parent != target; gen++) {
|
||||
auto offs = parent.repeat(C).map!mutate().array();
|
||||
parent = offs.minPos!((a, b) => fitness(a) < fitness(b))()[0];
|
||||
writefln("Gen %2d, dist=%2d: %s", gen, fitness(parent), parent);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +1,68 @@
|
|||
#import system.
|
||||
#import system'routines.
|
||||
#import extensions.
|
||||
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.
|
||||
const Target = "METHINKS IT IS LIKE A WEASEL".
|
||||
const AllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ".
|
||||
|
||||
#symbol randomChar
|
||||
= AllowedCharacters @ (rnd nextInt:(AllowedCharacters length)).
|
||||
const C = 100.
|
||||
const P = 0.05r.
|
||||
|
||||
#class(extension) evoHelper
|
||||
rnd = randomGenerator.
|
||||
|
||||
randomChar
|
||||
= AllowedCharacters[rnd nextInt(AllowedCharacters length)].
|
||||
|
||||
extension evoHelper
|
||||
{
|
||||
#method randomString
|
||||
= 0 repeat &till:self &each:x [ randomChar ] summarize:(String new) literal.
|
||||
randomString
|
||||
= 0 till:self repeat(: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.
|
||||
fitnessOf:s
|
||||
= self zip:s by(: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.
|
||||
mutate : p
|
||||
= self selectBy(:ch)( (rnd nextReal <= p) iif(randomChar,ch) ); summarize(String new); literal.
|
||||
}
|
||||
|
||||
#class EvoAlgorithm :: Enumerator
|
||||
class EvoAlgorithm :: Enumerator
|
||||
{
|
||||
#field theTarget.
|
||||
#field theCurrent.
|
||||
#field theVariantCount.
|
||||
object theTarget.
|
||||
object theCurrent.
|
||||
object theVariantCount.
|
||||
|
||||
#constructor new : s &of:count
|
||||
constructor new : s of:count
|
||||
[
|
||||
theTarget := s.
|
||||
theVariantCount := count int.
|
||||
]
|
||||
|
||||
#method get = theCurrent.
|
||||
get = theCurrent.
|
||||
|
||||
#method next
|
||||
next
|
||||
[
|
||||
($nil == theCurrent)
|
||||
? [ theCurrent := theTarget length randomString. ^ true. ].
|
||||
if ($nil == theCurrent)
|
||||
[ theCurrent := theTarget length; randomString. ^ true ].
|
||||
|
||||
(theTarget == theCurrent)
|
||||
? [ ^ false. ].
|
||||
if (theTarget == theCurrent)
|
||||
[ ^ false ].
|
||||
|
||||
#var variants := Array new:theVariantCount set &every:(&index:x) [ theCurrent mutate:P ].
|
||||
var variants := Array new:theVariantCount; populate(:x)( theCurrent mutate:P ).
|
||||
|
||||
theCurrent := variants array sort:(:a:b) [ a fitness &of:Target > b fitness &of:Target ] getAt:0.
|
||||
theCurrent := variants array; sort(:a:b)( a fitnessOf:Target > b fitnessOf:Target ); getAt:0.
|
||||
|
||||
^ true.
|
||||
]
|
||||
}
|
||||
|
||||
#symbol program =
|
||||
program =
|
||||
[
|
||||
#var attempt := Integer new.
|
||||
EvoAlgorithm new:Target &of:C run &each:current
|
||||
var attempt := Integer new.
|
||||
EvoAlgorithm new:Target of:C; forEach(:current)
|
||||
[
|
||||
console
|
||||
writeLiteral:"#":(attempt += 1) &paddingLeft:10
|
||||
writeLine:" ":current:" fitness: ":(current fitness &of:Target).
|
||||
printPaddingLeft(10,"#",attempt append:1);
|
||||
printLine(" ",current," fitness: ",current fitnessOf:Target).
|
||||
].
|
||||
|
||||
console readChar.
|
||||
].
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
defmodule Rand do
|
||||
def init do # Initialize the random values.
|
||||
<< a :: 32, b :: 32, c :: 32 >> = :crypto.strong_rand_bytes(12)
|
||||
:random.seed(a,b,c)
|
||||
end
|
||||
|
||||
def num do # Returns a value between 0.0 and 1.0.
|
||||
init
|
||||
:random.uniform
|
||||
end
|
||||
|
||||
def char(list) do # Returns a random letter or a space.
|
||||
Enum.at(list, :random.uniform(length(list)) - 1)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
defmodule Evolution do
|
||||
def select(target) do
|
||||
# Generate char list from A to Z; 32 is the ord value for space.
|
||||
chars = (?A..?Z) |> Enum.to_list() |> List.insert_at(0, 32)
|
||||
|
||||
(1..String.length(target)) # Creates parent for generation 0.
|
||||
|> Enum.map(fn _-> Rand.char(chars) end)
|
||||
|> mutate(String.to_char_list(target),0,[],chars)
|
||||
|> Log.found()
|
||||
end
|
||||
|
||||
# w is used to denote fitness in population genetics.
|
||||
|
||||
def mutate(parent,target,i,_,_) when target == parent, do: [parent|i]
|
||||
def mutate(parent,target,i,_,chars) when target != parent do
|
||||
w = fitness(parent,target)
|
||||
prev = reproduce(target,parent,w,0,mu_rate(w),chars)
|
||||
|
||||
# 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,prev,chars)
|
||||
end
|
||||
|
||||
# Generate 100 offspring and select the one with the greatest fitness.
|
||||
|
||||
def reproduce(target,parent,_,_,rate,chars) do
|
||||
(1..100)
|
||||
|> Enum.to_list()
|
||||
|> Stream.map(fn _-> mutation(parent,rate,chars) end)
|
||||
|> List.insert_at(0, parent)
|
||||
|> Enum.max_by(fn n -> fitness(n,target) end)
|
||||
end
|
||||
|
||||
# Calculate fitness by checking difference between parent and offspring chars.
|
||||
|
||||
def fitness(t,r) do
|
||||
(0..length(t)-1)
|
||||
|> Stream.map(fn n -> abs(Enum.at(t,n) - Enum.at(r,n)) end)
|
||||
|> Enum.reduce(fn a,b -> a + b end)
|
||||
|> calc()
|
||||
end
|
||||
|
||||
# Generate offspring based on parent.
|
||||
|
||||
def mutation(p,r,chars) do
|
||||
# Copy the parent chars, then check each val against the random mutation rate
|
||||
(0..length(p)-1)
|
||||
|> Stream.map(fn n -> Enum.at(p,n) end)
|
||||
|> Enum.map(fn n -> if Rand.num <= r, do: Rand.char(chars), else: n end)
|
||||
end
|
||||
|
||||
def calc(sum), do: 100 * :math.exp(sum/-10)
|
||||
def mu_rate(n), do: 1 - :math.exp(-(100-n)/400)
|
||||
end
|
||||
|
|
@ -1 +0,0 @@
|
|||
Evolution.select("METHINKS IT IS LIKE A WEASEL")
|
||||
|
|
@ -15,7 +15,7 @@ defmodule Evolution do
|
|||
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)
|
||||
|> mutate(to_charlist(target),0)
|
||||
|> Log.found
|
||||
end
|
||||
|
||||
|
|
@ -28,16 +28,17 @@ defmodule Evolution do
|
|||
|
||||
# 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)
|
||||
Log.show(prev,i)
|
||||
mutate(prev,target,i+1)
|
||||
else
|
||||
mutate(parent,target,i+1)
|
||||
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)]
|
||||
[parent | (for _ <- 1..100, do: mutation(parent,rate))]
|
||||
|> Enum.max_by(fn n -> fitness(n,target) end)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,22 @@
|
|||
function evolve(parent,target,mutation_rate,num_children)
|
||||
println("Initial parent is $parent, its fitness is $(fitness(parent,target))")
|
||||
gens=0
|
||||
while parent!=target
|
||||
children=[mutate(parent,mutation_rate) for i=1:num_children]
|
||||
bestfit,best=findmax(map(child->fitness(child,target),children))
|
||||
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")
|
||||
function evolve(parent::String, target::String, mutrate::Float64, nchild::Int)
|
||||
fitness(a, b::String=target) = count(l == t for (l, t) in zip(a, b))
|
||||
function mutate(str::String, rate::Float64=mutrate)
|
||||
L = split(" ABCDEFGHIJKLMNOPQRSTUVWXYZ", "")
|
||||
r = collect(rand() < rate ? rand(L) : c for c in str)
|
||||
return string(r...)
|
||||
end
|
||||
println("Initial parent is $parent, its fitness is $(fitness(parent))")
|
||||
gens = 0
|
||||
while parent != target
|
||||
children = collect(mutate(parent, mutrate) for i in 1:nchild)
|
||||
bestfit, best = findmax(fitness.(children))
|
||||
parent = children[best]
|
||||
gens += 1
|
||||
if gens % 10 == 0
|
||||
println("After $gens generations, the new parent is $parent and its fitness is $(fitness(parent))")
|
||||
end
|
||||
end
|
||||
println("After $gens generations, the parent evolved into the target $target")
|
||||
end
|
||||
|
||||
fitness(s1,s2)=count(x->x,convert(Array{Char,1},s1).==convert(Array{Char,1},s2))
|
||||
|
||||
function mutate(s,rate)
|
||||
new_s=""
|
||||
for c in s
|
||||
new_s*=string(rand()<rate?
|
||||
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rand(1:27)]:c)
|
||||
end
|
||||
return new_s
|
||||
end
|
||||
|
||||
evolve("IU RFSGJABGOLYWF XSMFXNIABKT","METHINKS IT IS LIKE A WEASEL",0.08998,100)
|
||||
evolve("IU RFSGJABGOLYWF XSMFXNIABKT", "METHINKS IT IS LIKE A WEASEL", 0.08998, 100)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
import java.util.*
|
||||
|
||||
val target = "METHINKS IT IS LIKE A WEASEL"
|
||||
val validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
|
||||
|
||||
val random = Random()
|
||||
|
||||
fun randomChar() = validChars[random.nextInt(validChars.length)]
|
||||
fun hammingDistance(s1: String, s2: String) =
|
||||
s1.zip(s2).map { if (it.first == it.second) 0 else 1 }.sum()
|
||||
|
||||
fun fitness(s1: String) = target.length - hammingDistance(s1, target)
|
||||
|
||||
fun mutate(s1: String, mutationRate: Double) =
|
||||
s1.map { if (random.nextDouble() > mutationRate) it else randomChar() }
|
||||
.joinToString(separator = "")
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val initialString = (0 until target.length).map { randomChar() }.joinToString(separator = "")
|
||||
|
||||
println(initialString)
|
||||
println(mutate(initialString, 0.2))
|
||||
|
||||
val mutationRate = 0.05
|
||||
val childrenPerGen = 50
|
||||
|
||||
var i = 0
|
||||
var currVal = initialString
|
||||
while (currVal != target) {
|
||||
i += 1
|
||||
currVal = (0..childrenPerGen).map { mutate(currVal, mutationRate) }.maxBy { fitness(it) }!!
|
||||
}
|
||||
println("Evolution found target after $i generations")
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ constant mutate_chance = .08;
|
|||
constant @alphabet = flat 'A'..'Z',' ';
|
||||
constant C = 100;
|
||||
|
||||
sub mutate { $^string.subst(/./, { rand < mutate_chance ?? @alphabet.pick !! $/ }, :g) }
|
||||
sub mutate { [~] (rand < mutate_chance ?? @alphabet.pick !! $_ for $^string.comb) }
|
||||
sub fitness { [+] $^string.comb Zeq state @ = target.comb }
|
||||
|
||||
loop (
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ actor Main
|
|||
var i: USize = 0
|
||||
while i < trial.size() do
|
||||
try
|
||||
if trial(i) == _target(i) then
|
||||
if trial(i)? == _target(i)? then
|
||||
ret_val = ret_val + 1
|
||||
end
|
||||
end
|
||||
|
|
@ -64,7 +64,7 @@ actor Main
|
|||
if rnd_real <= rate then
|
||||
let rnd_int: U64 = _rand.int(_possibilities.size().u64())
|
||||
try
|
||||
ret_val.push(_possibilities(rnd_int.usize()))
|
||||
ret_val.push(_possibilities(rnd_int.usize())?)
|
||||
end
|
||||
else
|
||||
ret_val.push(char)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ fitness: parse arg x; $=0; do k=1 for Ltar; $=$+(substr(x,k,1)==substr(target,
|
|||
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 RANSOM*/
|
||||
do j=1 for Ltar; r=random(1,100000) /*REXX's max for RANDOM*/
|
||||
if .00001*r<=rate then $=$ || substr(abc,r//Labc+1, 1)
|
||||
else $=$ || substr(x ,j , 1)
|
||||
end /*j*/
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
/*REXX program demonstrates an evolutionary algorithm (using mutation).*/
|
||||
parse arg children MR seed . /*get options (maybe) from C.L. */
|
||||
if children=='' then children = 10 /*# of children produced each gen*/
|
||||
if MR =='' then MR = "4%" /*the char Mutation Rate each gen*/
|
||||
if right(MR,1)=='%' then MR=strip(MR,,"%")/100 /*expressed as %? Adjust*/
|
||||
if seed\=='' then call random ,,seed /*allow the runs to be repeatable*/
|
||||
abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' ; Labc=length(abc)
|
||||
|
||||
do i=0 for Labc /*define array (faster compare), */
|
||||
A.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 array (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 str,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)
|
||||
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*/
|
||||
parent=almost
|
||||
end /*gen*/
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*───────────────────────────────────FITNESS subroutine─────────────────*/
|
||||
fitness: parse arg x; hit=0; do k=1 for Ltar
|
||||
hit=hit + (substr(x,k,1) == T.k)
|
||||
end /*k*/
|
||||
return hit
|
||||
/*───────────────────────────────────MUTATE subroutine──────────────────*/
|
||||
mutate: parse arg x,rate,? /*set ? to a null, x=string. */
|
||||
do j=1 for Ltar; r=random(1, 100000)
|
||||
if .00001*r<=rate then do; _=r//Labc; ?=? || A._; end
|
||||
else ?=? || substr(x,j,1)
|
||||
end /*j*/
|
||||
return ?
|
||||
57
Task/Evolutionary-algorithm/Scheme/evolutionary-algorithm.ss
Normal file
57
Task/Evolutionary-algorithm/Scheme/evolutionary-algorithm.ss
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
(import (scheme base)
|
||||
(scheme write)
|
||||
(srfi 27)) ; random numbers
|
||||
|
||||
(random-source-randomize! default-random-source)
|
||||
|
||||
(define target "METHINKS IT IS LIKE A WEASEL") ; target string
|
||||
(define C 100) ; size of population
|
||||
(define p 0.1) ; chance any char is mutated
|
||||
|
||||
;; return a random character in given range
|
||||
(define (random-char)
|
||||
(string-ref "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
|
||||
(random-integer 27)))
|
||||
|
||||
;; compute distance of given string from target
|
||||
(define (fitness str)
|
||||
(apply +
|
||||
(map (lambda (c1 c2) (if (char=? c1 c2) 0 1))
|
||||
(string->list str)
|
||||
(string->list target))))
|
||||
|
||||
;; mutate given parent string, returning a new string
|
||||
(define (mutate str)
|
||||
(string-map (lambda (c)
|
||||
(if (< (random-real) p)
|
||||
(random-char)
|
||||
c))
|
||||
str))
|
||||
|
||||
;; create a population by mutating parent,
|
||||
;; returning a list of variations
|
||||
(define (make-population parent)
|
||||
(do ((pop '() (cons (mutate parent) pop)))
|
||||
((= C (length pop)) pop)))
|
||||
|
||||
;; find the most fit candidate in given list
|
||||
(define (find-best candidates)
|
||||
(define (select-best a b)
|
||||
(if (< (fitness a) (fitness b)) a b))
|
||||
;
|
||||
(do ((best (car candidates) (select-best best (car rem)))
|
||||
(rem (cdr candidates) (cdr rem)))
|
||||
((null? rem) best)))
|
||||
|
||||
;; create first parent from random characters
|
||||
;; of same size as target string
|
||||
(define (initial-parent)
|
||||
(do ((res '() (cons (random-char) res)))
|
||||
((= (length res) (string-length target))
|
||||
(list->string res))))
|
||||
|
||||
;; run the search
|
||||
(do ((parent (initial-parent) (find-best (cons parent (make-population parent))))) ; select best from parent and population
|
||||
((string=? parent target)
|
||||
(display (string-append "Found: " parent "\n")))
|
||||
(display parent) (newline))
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
10 LET A$="ABCDEFGHIJKLMNOPQRSTUVWXYZ "
|
||||
20 LET T$="METHINKS IT IS LIKE A WEASEL"
|
||||
30 LET L=LEN T$
|
||||
40 LET C=10
|
||||
50 LET M=0.05
|
||||
60 LET G=0
|
||||
70 DIM C$(C,L)
|
||||
80 LET P$=""
|
||||
90 FOR I=1 TO L
|
||||
100 LET P$=P$+A$(INT (RND*LEN A$)+1)
|
||||
110 NEXT I
|
||||
120 PRINT AT 1,0;P$
|
||||
130 LET S$=P$
|
||||
140 GOSUB 390
|
||||
150 LET N=R
|
||||
160 PRINT AT 1,30;N
|
||||
170 PRINT AT 0,4;G
|
||||
180 IF P$=T$ THEN GOTO 440
|
||||
190 FOR I=1 TO C
|
||||
200 FOR J=1 TO L
|
||||
210 LET C$(I,J)=P$(J)
|
||||
220 IF RND<=M THEN LET C$(I,J)=A$(INT (RND*LEN A$)+1)
|
||||
230 PRINT AT I+2,J-1;C$(I,J)
|
||||
240 NEXT J
|
||||
250 PRINT AT I+2,30;" "
|
||||
260 NEXT I
|
||||
270 LET F=0
|
||||
280 FOR I=1 TO C
|
||||
290 LET S$=C$(I)
|
||||
300 GOSUB 390
|
||||
310 PRINT AT I+2,30;R
|
||||
320 IF R>N THEN LET F=I
|
||||
330 IF R>N THEN LET N=R
|
||||
340 NEXT I
|
||||
350 IF F>0 THEN LET P$=C$(F)
|
||||
360 LET G=G+1
|
||||
370 PRINT AT 1,0;P$
|
||||
380 GOTO 160
|
||||
390 LET R=0
|
||||
400 FOR K=1 TO L
|
||||
410 IF S$(K)=T$(K) THEN LET R=R+1
|
||||
420 NEXT K
|
||||
430 RETURN
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
'This is the string we want to "evolve" to. Any string of any length will
|
||||
'do as long as it consists only of upper case letters and spaces.
|
||||
|
||||
Target = "METHINKS IT IS LIKE A WEASEL"
|
||||
|
||||
'This is the pool of letters that will be selected at random for a mutation
|
||||
|
||||
letters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
||||
'A mutation rate of 0.5 means that there is a 50% chance that one letter
|
||||
'will be mutated at random in the next child
|
||||
|
||||
mutation_rate = 0.5
|
||||
|
||||
'Set for 10 children per generation
|
||||
|
||||
Dim child(10)
|
||||
|
||||
'Generate the first guess as random letters
|
||||
|
||||
Randomize
|
||||
Parent = ""
|
||||
|
||||
for i = 1 to len(Target)
|
||||
Parent = Parent & Mid(letters,Random(1,Len(letters)),1)
|
||||
next
|
||||
|
||||
gen = 0
|
||||
|
||||
Do
|
||||
bestfit = 0
|
||||
bestind = 0
|
||||
|
||||
gen = gen + 1
|
||||
|
||||
'make n copies of the current string and find the one
|
||||
'that best matches the target string
|
||||
|
||||
For i = 0 to ubound(child)
|
||||
|
||||
child(i) = Mutate(Parent, mutation_rate)
|
||||
|
||||
fit = Fitness(Target, child(i))
|
||||
|
||||
If fit > bestfit Then
|
||||
bestfit = fit
|
||||
bestind = i
|
||||
End If
|
||||
|
||||
Next
|
||||
|
||||
'Select the child that has the best fit with the target string
|
||||
|
||||
Parent = child(bestind)
|
||||
Wscript.Echo parent, "(fit=" & bestfit & ")"
|
||||
|
||||
Loop Until Parent = Target
|
||||
|
||||
Wscript.Echo vbcrlf & "Generations = " & gen
|
||||
|
||||
'apply a random mutation to a random character in a string
|
||||
|
||||
Function Mutate ( ByVal str , ByVal rate )
|
||||
|
||||
Dim pos 'a random position in the string'
|
||||
Dim ltr 'a new letter chosen at random '
|
||||
|
||||
If rate > Rnd(1) Then
|
||||
|
||||
ltr = Mid(letters,Random(1,len(letters)),1)
|
||||
pos = Random(1,len(str))
|
||||
str = Left(str, pos - 1) & ltr & Mid(str, pos + 1)
|
||||
|
||||
End If
|
||||
|
||||
Mutate = str
|
||||
|
||||
End Function
|
||||
|
||||
'returns the number of letters in the two strings that match
|
||||
|
||||
Function Fitness (ByVal str , ByVal ref )
|
||||
|
||||
Dim i
|
||||
|
||||
Fitness = 0
|
||||
|
||||
For i = 1 To Len(str)
|
||||
If Mid(str, i, 1) = Mid(ref, i, 1) Then Fitness = Fitness + 1
|
||||
Next
|
||||
|
||||
End Function
|
||||
|
||||
'Return a random integer in the range lower to upper (inclusive)
|
||||
|
||||
Private Function Random ( lower , upper )
|
||||
Random = Int((upper - lower + 1) * Rnd + lower)
|
||||
End Function
|
||||
14
Task/Evolutionary-algorithm/Zkl/evolutionary-algorithm.zkl
Normal file
14
Task/Evolutionary-algorithm/Zkl/evolutionary-algorithm.zkl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
const target = "METHINKS IT IS LIKE A WEASEL";
|
||||
const C = 100; // Number of children in each generation.
|
||||
const P = 0.05; // Mutation probability.
|
||||
const A2ZS = ["A".."Z"].walk().append(" ").concat();
|
||||
fcn fitness(s){ Utils.zipWith('!=,target,s).sum(0) } // bigger is worser
|
||||
fcn rnd{ A2ZS[(0).random(27)] }
|
||||
fcn mutate(s){ s.apply(fcn(c){ if((0.0).random(1) < P) rnd() else c }) }
|
||||
|
||||
parent := target.len().pump(String,rnd); // random string of "A..Z "
|
||||
gen:=0; do{ // mutate C copies of parent and pick the fittest
|
||||
parent = (0).pump(C,List,T(Void,parent),mutate)
|
||||
.reduce(fcn(a,b){ if(fitness(a)<fitness(b)) a else b });
|
||||
println("Gen %2d, dist=%2d: %s".fmt(gen+=1, fitness(parent), parent));
|
||||
}while(parent != target);
|
||||
Loading…
Add table
Add a link
Reference in a new issue