Data update

This commit is contained in:
Ingy döt Net 2026-02-01 16:33:20 -08:00
parent 5150844a7d
commit 4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions

View file

@ -1,162 +1,162 @@
MRATE: equ 26 ; Chance of mutation (MRATE/256)
COPIES: equ 100 ; Amount of copies to make
fname1: equ 5Dh ; First filename on command line (used for RNG seed)
fname2: equ 6Dh ; Second filename (also used for RNG seed)
org 100h
;;; Make random seed from the two CP/M 'filenames'
lxi b,rnddat
lxi h,fname1
xra a
call seed ; First four bytes from fn1 make X
call seed ; Second four bytes from fn1 make A
mvi l,fname2
call seed ; First four bytes from fn2 make B
call seed ; Second four bytes from fn2 make C
;;; Create the first parent (random string)
lxi h,parent
mvi e,tgtsz-1
genchr: call rndchr ; Get random character
mov m,a ; Store it
inx h
dcr e
jnz genchr
mvi m,'$' ; CP/M string terminator
;;; Main loop
loop: lxi d,parent
push d
call puts ; Print current parent
pop h ; Calculate fitness
call fitnes
xra a ; If it is 0, all characters match,
ora d
rz ; So we stop.
lxi h,kids ; Otherwise, set HL to start of children,
mvi a,0FFh ; Initialize maximum fitness value
sta maxfit
mvi a,COPIES ; Initialize copy counter
sta copies
;;; Make copies
copy: push h ; Store the place where the copy will go
call mutcpy ; Make a mutated copy of the parent
pop h ; Get the place where the copy went
push h ; But keep it on the stack
call fitnes ; Calculate the fitness of that copy
pop h ; Get place where copy went
lda maxfit ; Get current best fitness
cmp d ; Compare to fitness of current copy
jc next ; If it wasn't better, next copy
shld maxptr ; If it was better, store pointer
mov a,d
sta maxfit ; And new max fitness
next: lxi b,tgtsz ; Get place for next copy
dad b
xchg ; Keep in DE
lxi h,copies
dcr m ; Any copies left to make?
xchg
jnz copy ; Then make another copy
lhld maxptr ; Otherwise, get location of copy with best fitness
lxi b,parent ; Make that the new parent
pcopy: mov a,m ; Get character from copy
inx h
stax b ; Store into location of parent
inx b
cpi '$' ; Check for string terminator
jnz pcopy ; If it isn't, copy next character
jmp loop ; Otherwise, mutate new parent
;;; Make a copy of the parent, mutate it, and store it at [HL].
mutcpy: lxi b,parent
mcloop: ldax b ; Get current character
inx b
mov m,a ; Write it to new location
inx h
cpi '$' ; Was it the string terminator?
rz ; Then stop
call rand ; Otherwise, get random value
cpi MRATE ; Should we mutate this character?
jnc mcloop ; If not, just copy next character
call rndchr ; Otherwise, get a random character
dcx h ; And store it instead of the character we had
mov m,a
inx h
jmp mcloop
;;; Calculate fitness of candidate under [HL], fitness is
;;; returned in D. Fitness is "inverted", i.e. a fitness of 0
;;; means everything matches.
fitnes: lxi b,target
lxi d,tgtsz ; E=counter, D=fitness
floop: dcr e ; Done yet?
rz ; If so, return.
ldax b ; Get target character
inx b
cmp m ; Compare to current character
inx h
jz floop ; If they match, don't do anything
inr d ; If they don't match, count this
jmp floop
;;; Generate a random uppercase letter, or a space
;;; Return in A, other registers preserved
rndchr: call rand ; Get a random value
ani 31 ; from 0 to 31
cpi 28 ; If 28 or higher,
jnc rndchr ; get another value
adi 'A' ; Make uppercase letter
cpi 'Z'+1 ; If the result is 'Z' or lower,
rc ; then return it,
mvi a,' ' ; otherwise return a space
ret
;;; Load 4 bytes from [HL] and use them, plus A, as part of seed
;;; in [BC]
seed: mvi e,4 ; 4 bytes
sloop: xra m
inx h
dcr e
jnz sloop
stax b
inx b
ret
;;; Random number generator using XABC algorithm
rand: push h
lxi h,rnddat
inr m ; X++
mov a,m ; X
inx h
xra m ; ^ C
inx h
xra m ; ^ A
mov m,a ; -> A
inx h
add m ; + B
mov m,a ; -> B
rar ; >>1 (ish)
dcx h
xra m ; ^ A
dcx h
add m ; + C
mov m,a ; -> C
pop h
ret
;;; Print string to console using CP/M, saving all registers
puts: push h
push d
push b
push psw
mvi c,9 ; CP/M print string
call 5
lxi d,nl ; Print a newline as well
mvi c,9
call 5
pop b
pop d
pop h
pop psw
ret
nl: db 13,10,'$'
target: db 'METHINKS IT IS LIKE A WEASEL$'
tgtsz: equ $-target
rnddat: ds 4 ; RNG state
copies: ds 1 ; Copies left to make
maxfit: ds 1 ; Best fitness seen
maxptr: ds 2 ; Pointer to copy with best fitness
parent: equ $ ; Store current parent here
kids: equ $+tgtsz ; Store mutated copies here
MRATE: equ 26 ; Chance of mutation (MRATE/256)
COPIES: equ 100 ; Amount of copies to make
fname1: equ 5Dh ; First filename on command line (used for RNG seed)
fname2: equ 6Dh ; Second filename (also used for RNG seed)
org 100h
;;; Make random seed from the two CP/M 'filenames'
lxi b,rnddat
lxi h,fname1
xra a
call seed ; First four bytes from fn1 make X
call seed ; Second four bytes from fn1 make A
mvi l,fname2
call seed ; First four bytes from fn2 make B
call seed ; Second four bytes from fn2 make C
;;; Create the first parent (random string)
lxi h,parent
mvi e,tgtsz-1
genchr: call rndchr ; Get random character
mov m,a ; Store it
inx h
dcr e
jnz genchr
mvi m,'$' ; CP/M string terminator
;;; Main loop
loop: lxi d,parent
push d
call puts ; Print current parent
pop h ; Calculate fitness
call fitnes
xra a ; If it is 0, all characters match,
ora d
rz ; So we stop.
lxi h,kids ; Otherwise, set HL to start of children,
mvi a,0FFh ; Initialize maximum fitness value
sta maxfit
mvi a,COPIES ; Initialize copy counter
sta copies
;;; Make copies
copy: push h ; Store the place where the copy will go
call mutcpy ; Make a mutated copy of the parent
pop h ; Get the place where the copy went
push h ; But keep it on the stack
call fitnes ; Calculate the fitness of that copy
pop h ; Get place where copy went
lda maxfit ; Get current best fitness
cmp d ; Compare to fitness of current copy
jc next ; If it wasn't better, next copy
shld maxptr ; If it was better, store pointer
mov a,d
sta maxfit ; And new max fitness
next: lxi b,tgtsz ; Get place for next copy
dad b
xchg ; Keep in DE
lxi h,copies
dcr m ; Any copies left to make?
xchg
jnz copy ; Then make another copy
lhld maxptr ; Otherwise, get location of copy with best fitness
lxi b,parent ; Make that the new parent
pcopy: mov a,m ; Get character from copy
inx h
stax b ; Store into location of parent
inx b
cpi '$' ; Check for string terminator
jnz pcopy ; If it isn't, copy next character
jmp loop ; Otherwise, mutate new parent
;;; Make a copy of the parent, mutate it, and store it at [HL].
mutcpy: lxi b,parent
mcloop: ldax b ; Get current character
inx b
mov m,a ; Write it to new location
inx h
cpi '$' ; Was it the string terminator?
rz ; Then stop
call rand ; Otherwise, get random value
cpi MRATE ; Should we mutate this character?
jnc mcloop ; If not, just copy next character
call rndchr ; Otherwise, get a random character
dcx h ; And store it instead of the character we had
mov m,a
inx h
jmp mcloop
;;; Calculate fitness of candidate under [HL], fitness is
;;; returned in D. Fitness is "inverted", i.e. a fitness of 0
;;; means everything matches.
fitnes: lxi b,target
lxi d,tgtsz ; E=counter, D=fitness
floop: dcr e ; Done yet?
rz ; If so, return.
ldax b ; Get target character
inx b
cmp m ; Compare to current character
inx h
jz floop ; If they match, don't do anything
inr d ; If they don't match, count this
jmp floop
;;; Generate a random uppercase letter, or a space
;;; Return in A, other registers preserved
rndchr: call rand ; Get a random value
ani 31 ; from 0 to 31
cpi 28 ; If 28 or higher,
jnc rndchr ; get another value
adi 'A' ; Make uppercase letter
cpi 'Z'+1 ; If the result is 'Z' or lower,
rc ; then return it,
mvi a,' ' ; otherwise return a space
ret
;;; Load 4 bytes from [HL] and use them, plus A, as part of seed
;;; in [BC]
seed: mvi e,4 ; 4 bytes
sloop: xra m
inx h
dcr e
jnz sloop
stax b
inx b
ret
;;; Random number generator using XABC algorithm
rand: push h
lxi h,rnddat
inr m ; X++
mov a,m ; X
inx h
xra m ; ^ C
inx h
xra m ; ^ A
mov m,a ; -> A
inx h
add m ; + B
mov m,a ; -> B
rar ; >>1 (ish)
dcx h
xra m ; ^ A
dcx h
add m ; + C
mov m,a ; -> C
pop h
ret
;;; Print string to console using CP/M, saving all registers
puts: push h
push d
push b
push psw
mvi c,9 ; CP/M print string
call 5
lxi d,nl ; Print a newline as well
mvi c,9
call 5
pop b
pop d
pop h
pop psw
ret
nl: db 13,10,'$'
target: db 'METHINKS IT IS LIKE A WEASEL$'
tgtsz: equ $-target
rnddat: ds 4 ; RNG state
copies: ds 1 ; Copies left to make
maxfit: ds 1 ; Best fitness seen
maxptr: ds 2 ; Pointer to copy with best fitness
parent: equ $ ; Store current parent here
kids: equ $+tgtsz ; Store mutated copies here

View file

@ -1,123 +1,123 @@
bits 16
cpu 8086
MRATE: equ 26 ; Mutation rate (MRATE/256)
COPIES: equ 100 ; Amount of copies to make
gettim: equ 02Ch ; MS-DOS get time function
pstr: equ 9 ; MS-DOS print string
section .text
org 100h
;;; Use MS-DOS time to set random seed
mov ah,gettim
int 21h
mov [rnddat],cx
mov [rnddat+2],dx
;;; Make first parent (random characters)
mov di,parent
mov cx,target.size-1
getchr: call rndchr ; Get random character
stosb ; Store in parent
loop getchr
mov al,'$' ; Write string terminator
stosb
;;; Main loop.
loop: mov bx,parent ; Print current parent
mov dx,bx
call puts
call fitnes ; Check fitness
test cl,cl ; If zero, we're done
jnz nxmut ; If not, do another mutation
ret ; Quit to DOS
nxmut: mov dl,0FFh ; DL = best fitness yet
mov di,kids ; Set DI to start of memory for children
mov ch,COPIES ; CH = amount of copies to make
xor bp,bp
;;; Make copy, mutate, and test fitness
copy: mov bx,di ; Let BX = where next copy will go
call mutcpy ; Make the copy (and adjust DI)
call fitnes ; Check fitness
cmp cl,dl ; Is it better than the previous best one?
ja next ; If not, just do the next one,
mov dl,cl ; Otherwise, this is now the best one
lea bp,[di-target.size] ; Store a pointer to it in BP
next: dec ch ; One copy less
jnz copy ; Make another copy if we need to
mov si,bp ; We're done, the best child becomes
mov di,parent ; the parent for the next generation
mov cx,target.size
rep movsb
jmp loop ; Next generation
;;; Make copy of parent, mutating as we go, and store at [DI]
mutcpy: mov si,parent
.loop: lodsb ; Get byte from parent
stosb ; Store in copy
cmp al,'$' ; Is it '$'?
je .out ; Then we're done
call rand ; Otherwise, should we mutate?
cmp al,MRATE
ja .loop ; If not, do next character
call rndchr ; But if so, get random character,
mov [di-1],al ; and overwrite the current character.
jmp .loop ; Then do the next character.
.out: ret
;;; Get fitness of character in [BX]
fitnes: mov si,target
xor cl,cl ; Fitness
.loop: lodsb ; Get target character
cmp al,'$' ; Done?
je .out ; Then stop
cmp al,[bx] ; Equal to character under [BX]?
lahf ; Keep flags
inc bx ; Increment BX
sahf ; Restore flags (was al=[bx]?)
je .loop ; If equal, do next character
inc cx ; Otherwise, count this as a mismatch
jmp .loop
.out: ret
;;; Generate random character, [A-Z] or space.
rndchr: call rand ; Get random number
and al,31 ; Lower five bits
cmp al,27 ; One of 27 characters?
jae rndchr ; If not, get new random number
add al,'A' ; Make uppercase letter
cmp al,'Z' ; More than 'Z'?
jbe .out ; If not, it's OK
mov al,' ' ; Otherwise, give a space
.out: ret
;;; Random number generator using XABC algorithm
;;; Returns random byte in AL
rand: push cx
push dx
mov cx,[rnddat] ; CH=X CL=A
mov dx,[rnddat+2] ; DH=B DL=C
inc ch ; X++
xor cl,ch ; A ^= X
xor cl,dl ; A ^= C
add dh,cl ; B += A
mov al,dh ; C' = B
shr al,1 ; C' >>= 1
xor al,cl ; C' ^= A
add al,dl ; C' += C
mov dl,al ; C = C'
mov [rnddat],cx
mov [rnddat+2],dx
pop dx
pop cx
ret
;;; Print string in DX, plus a newline, saving registers
puts: push ax
push dx
mov ah,pstr
int 21h
mov dx,nl
int 21h
pop dx
pop ax
ret
section .data
nl: db 13,10,'$'
target: db 'METHINKS IT IS LIKE A WEASEL$'
.size: equ $-target
section .bss
rnddat: resb 4 ; RNG state
parent: resb target.size ; Place to store current parent
kids: resb COPIES*target.size ; Place to store children
bits 16
cpu 8086
MRATE: equ 26 ; Mutation rate (MRATE/256)
COPIES: equ 100 ; Amount of copies to make
gettim: equ 02Ch ; MS-DOS get time function
pstr: equ 9 ; MS-DOS print string
section .text
org 100h
;;; Use MS-DOS time to set random seed
mov ah,gettim
int 21h
mov [rnddat],cx
mov [rnddat+2],dx
;;; Make first parent (random characters)
mov di,parent
mov cx,target.size-1
getchr: call rndchr ; Get random character
stosb ; Store in parent
loop getchr
mov al,'$' ; Write string terminator
stosb
;;; Main loop.
loop: mov bx,parent ; Print current parent
mov dx,bx
call puts
call fitnes ; Check fitness
test cl,cl ; If zero, we're done
jnz nxmut ; If not, do another mutation
ret ; Quit to DOS
nxmut: mov dl,0FFh ; DL = best fitness yet
mov di,kids ; Set DI to start of memory for children
mov ch,COPIES ; CH = amount of copies to make
xor bp,bp
;;; Make copy, mutate, and test fitness
copy: mov bx,di ; Let BX = where next copy will go
call mutcpy ; Make the copy (and adjust DI)
call fitnes ; Check fitness
cmp cl,dl ; Is it better than the previous best one?
ja next ; If not, just do the next one,
mov dl,cl ; Otherwise, this is now the best one
lea bp,[di-target.size] ; Store a pointer to it in BP
next: dec ch ; One copy less
jnz copy ; Make another copy if we need to
mov si,bp ; We're done, the best child becomes
mov di,parent ; the parent for the next generation
mov cx,target.size
rep movsb
jmp loop ; Next generation
;;; Make copy of parent, mutating as we go, and store at [DI]
mutcpy: mov si,parent
.loop: lodsb ; Get byte from parent
stosb ; Store in copy
cmp al,'$' ; Is it '$'?
je .out ; Then we're done
call rand ; Otherwise, should we mutate?
cmp al,MRATE
ja .loop ; If not, do next character
call rndchr ; But if so, get random character,
mov [di-1],al ; and overwrite the current character.
jmp .loop ; Then do the next character.
.out: ret
;;; Get fitness of character in [BX]
fitnes: mov si,target
xor cl,cl ; Fitness
.loop: lodsb ; Get target character
cmp al,'$' ; Done?
je .out ; Then stop
cmp al,[bx] ; Equal to character under [BX]?
lahf ; Keep flags
inc bx ; Increment BX
sahf ; Restore flags (was al=[bx]?)
je .loop ; If equal, do next character
inc cx ; Otherwise, count this as a mismatch
jmp .loop
.out: ret
;;; Generate random character, [A-Z] or space.
rndchr: call rand ; Get random number
and al,31 ; Lower five bits
cmp al,27 ; One of 27 characters?
jae rndchr ; If not, get new random number
add al,'A' ; Make uppercase letter
cmp al,'Z' ; More than 'Z'?
jbe .out ; If not, it's OK
mov al,' ' ; Otherwise, give a space
.out: ret
;;; Random number generator using XABC algorithm
;;; Returns random byte in AL
rand: push cx
push dx
mov cx,[rnddat] ; CH=X CL=A
mov dx,[rnddat+2] ; DH=B DL=C
inc ch ; X++
xor cl,ch ; A ^= X
xor cl,dl ; A ^= C
add dh,cl ; B += A
mov al,dh ; C' = B
shr al,1 ; C' >>= 1
xor al,cl ; C' ^= A
add al,dl ; C' += C
mov dl,al ; C = C'
mov [rnddat],cx
mov [rnddat+2],dx
pop dx
pop cx
ret
;;; Print string in DX, plus a newline, saving registers
puts: push ax
push dx
mov ah,pstr
int 21h
mov dx,nl
int 21h
pop dx
pop ax
ret
section .data
nl: db 13,10,'$'
target: db 'METHINKS IT IS LIKE A WEASEL$'
.size: equ $-target
section .bss
rnddat: resb 4 ; RNG state
parent: resb target.size ; Place to store current parent
kids: resb COPIES*target.size ; Place to store children

View file

@ -1,124 +0,0 @@
with Ada.Text_IO;
with Ada.Numerics.Discrete_Random;
with Ada.Numerics.Float_Random;
with Ada.Strings.Fixed;
with Ada.Strings.Maps;
procedure Evolution is
-- only upper case characters allowed, and space, which uses '@' in
-- internal representation (allowing subtype of Character).
subtype DNA_Char is Character range '@' .. 'Z';
-- DNA string is as long as target string.
subtype DNA_String is String (1 .. 28);
-- target string translated to DNA_Char string
Target : constant DNA_String := "METHINKS@IT@IS@LIKE@A@WEASEL";
-- calculate the 'closeness' to the target DNA.
-- it returns a number >= 0 that describes how many chars are correct.
-- can be improved much to make evolution better, but keep simple for
-- this example.
function Fitness (DNA : DNA_String) return Natural is
Result : Natural := 0;
begin
for Position in DNA'Range loop
if DNA (Position) = Target (Position) then
Result := Result + 1;
end if;
end loop;
return Result;
end Fitness;
-- output the DNA using the mapping
procedure Output_DNA (DNA : DNA_String; Prefix : String := "") is
use Ada.Strings.Maps;
Output_Map : Character_Mapping;
begin
Output_Map := To_Mapping
(From => To_Sequence (To_Set (('@'))),
To => To_Sequence (To_Set ((' '))));
Ada.Text_IO.Put (Prefix);
Ada.Text_IO.Put (Ada.Strings.Fixed.Translate (DNA, Output_Map));
Ada.Text_IO.Put_Line (", fitness: " & Integer'Image (Fitness (DNA)));
end Output_DNA;
-- DNA_Char is a discrete type, use Ada RNG
package Random_Char is new Ada.Numerics.Discrete_Random (DNA_Char);
DNA_Generator : Random_Char.Generator;
-- need generator for floating type, too
Float_Generator : Ada.Numerics.Float_Random.Generator;
-- returns a mutated copy of the parent, applying the given mutation rate
function Mutate (Parent : DNA_String;
Mutation_Rate : Float)
return DNA_String
is
Result : DNA_String := Parent;
begin
for Position in Result'Range loop
if Ada.Numerics.Float_Random.Random (Float_Generator) <= Mutation_Rate
then
Result (Position) := Random_Char.Random (DNA_Generator);
end if;
end loop;
return Result;
end Mutate;
-- genetic algorithm to evolve the string
-- could be made a function returning the final string
procedure Evolve (Child_Count : Positive := 100;
Mutation_Rate : Float := 0.2)
is
type Child_Array is array (1 .. Child_Count) of DNA_String;
-- determine the fittest of the candidates
function Fittest (Candidates : Child_Array) return DNA_String is
The_Fittest : DNA_String := Candidates (1);
begin
for Candidate in Candidates'Range loop
if Fitness (Candidates (Candidate)) > Fitness (The_Fittest)
then
The_Fittest := Candidates (Candidate);
end if;
end loop;
return The_Fittest;
end Fittest;
Parent, Next_Parent : DNA_String;
Children : Child_Array;
Loop_Counter : Positive := 1;
begin
-- initialize Parent
for Position in Parent'Range loop
Parent (Position) := Random_Char.Random (DNA_Generator);
end loop;
Output_DNA (Parent, "First: ");
while Parent /= Target loop
-- mutation loop
for Child in Children'Range loop
Children (Child) := Mutate (Parent, Mutation_Rate);
end loop;
Next_Parent := Fittest (Children);
-- don't allow weaker children as the parent
if Fitness (Next_Parent) > Fitness (Parent) then
Parent := Next_Parent;
end if;
-- output every 20th generation
if Loop_Counter mod 20 = 0 then
Output_DNA (Parent, Integer'Image (Loop_Counter) & ": ");
end if;
Loop_Counter := Loop_Counter + 1;
end loop;
Output_DNA (Parent, "Final (" & Integer'Image (Loop_Counter) & "): ");
end Evolve;
begin
-- initialize the random number generators
Random_Char.Reset (DNA_Generator);
Ada.Numerics.Float_Random.Reset (Float_Generator);
-- evolve!
Evolve;
end Evolution;

View file

@ -1,5 +1,5 @@
target: "METHINKS IT IS LIKE A WEASEL"
alphabet: [` `] ++ @`A`..`Z`
alphabet: [' '] ++ @'A'..'Z'
p: 0.05
c: 100

View file

@ -2,55 +2,55 @@ output := ""
target := "METHINKS IT IS LIKE A WEASEL"
targetLen := StrLen(target)
Loop, 26
possibilities_%A_Index% := Chr(A_Index+64) ; A-Z
possibilities_%A_Index% := Chr(A_Index+64) ; A-Z
possibilities_27 := " "
C := 100
parent := ""
Loop, %targetLen%
{
Random, randomNum, 1, 27
Random, randomNum, 1, 27
parent .= possibilities_%randomNum%
}
Loop,
{
If (target = parent)
Break
If (Mod(A_Index,10) = 0)
output .= A_Index ": " parent ", fitness: " fitness(parent, target) "`n"
bestFit := 0
Loop, %C%
If ((fitness := fitness(spawn := mutate(parent), target)) > bestFit)
bestSpawn := spawn , bestFit := fitness
parent := bestFit > fitness(parent, target) ? bestSpawn : parent
iter := A_Index
If (target = parent)
Break
If (Mod(A_Index,10) = 0)
output .= A_Index ": " parent ", fitness: " fitness(parent, target) "`n"
bestFit := 0
Loop, %C%
If ((fitness := fitness(spawn := mutate(parent), target)) > bestFit)
bestSpawn := spawn , bestFit := fitness
parent := bestFit > fitness(parent, target) ? bestSpawn : parent
iter := A_Index
}
output .= parent ", " iter
MsgBox, % output
ExitApp
mutate(parent) {
local output, replaceChar, newChar
output := ""
Loop, %targetLen%
{
Random, replaceChar, 0, 9
If (replaceChar != 0)
output .= SubStr(parent, A_Index, 1)
else
{
Random, newChar, 1, 27
output .= possibilities_%newChar%
}
}
Return output
local output, replaceChar, newChar
output := ""
Loop, %targetLen%
{
Random, replaceChar, 0, 9
If (replaceChar != 0)
output .= SubStr(parent, A_Index, 1)
else
{
Random, newChar, 1, 27
output .= possibilities_%newChar%
}
}
Return output
}
fitness(string, target) {
totalFit := 0
Loop, % StrLen(string)
If (SubStr(string, A_Index, 1) = SubStr(target, A_Index, 1))
totalFit++
Return totalFit
totalFit := 0
Loop, % StrLen(string)
If (SubStr(string, A_Index, 1) = SubStr(target, A_Index, 1))
totalFit++
Return totalFit
}

View file

@ -12,56 +12,56 @@ const char tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
/* returns random integer from 0 to n - 1 */
int irand(int n)
{
int r, rand_max = RAND_MAX - (RAND_MAX % n);
while((r = rand()) >= rand_max);
return r / (rand_max / n);
int r, rand_max = RAND_MAX - (RAND_MAX % n);
while((r = rand()) >= rand_max);
return r / (rand_max / n);
}
/* number of different chars between a and b */
int unfitness(const char *a, const char *b)
{
int i, sum = 0;
for (i = 0; a[i]; i++)
sum += (a[i] != b[i]);
return sum;
int i, sum = 0;
for (i = 0; a[i]; i++)
sum += (a[i] != b[i]);
return sum;
}
/* each char of b has 1/MUTATE chance of differing from a */
void mutate(const char *a, char *b)
{
int i;
for (i = 0; a[i]; i++)
b[i] = irand(MUTATE) ? a[i] : tbl[irand(CHOICE)];
int i;
for (i = 0; a[i]; i++)
b[i] = irand(MUTATE) ? a[i] : tbl[irand(CHOICE)];
b[i] = '\0';
b[i] = '\0';
}
int main()
{
int i, best_i, unfit, best, iters = 0;
char specimen[COPIES][sizeof(target) / sizeof(char)];
int i, best_i, unfit, best, iters = 0;
char specimen[COPIES][sizeof(target) / sizeof(char)];
/* init rand string */
for (i = 0; target[i]; i++)
specimen[0][i] = tbl[irand(CHOICE)];
specimen[0][i] = 0;
/* init rand string */
for (i = 0; target[i]; i++)
specimen[0][i] = tbl[irand(CHOICE)];
specimen[0][i] = 0;
do {
for (i = 1; i < COPIES; i++)
mutate(specimen[0], specimen[i]);
do {
for (i = 1; i < COPIES; i++)
mutate(specimen[0], specimen[i]);
/* find best fitting string */
for (best_i = i = 0; i < COPIES; i++) {
unfit = unfitness(target, specimen[i]);
if(unfit < best || !i) {
best = unfit;
best_i = i;
}
}
/* find best fitting string */
for (best_i = i = 0; i < COPIES; i++) {
unfit = unfitness(target, specimen[i]);
if(unfit < best || !i) {
best = unfit;
best_i = i;
}
}
if (best_i) strcpy(specimen[0], specimen[best_i]);
printf("iter %d, score %d: %s\n", iters++, best, specimen[0]);
} while (best);
if (best_i) strcpy(specimen[0], specimen[best_i]);
printf("iter %d, score %d: %s\n", iters++, best, specimen[0]);
} while (best);
return 0;
return 0;
}

View file

@ -1,88 +0,0 @@
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

@ -1,49 +1,49 @@
import ceylon.random {
DefaultRandom
DefaultRandom
}
shared void run() {
value mutationRate = 0.05;
value childrenPerGeneration = 100;
value target = "METHINKS IT IS LIKE A WEASEL";
value alphabet = {' ', *('A'..'Z')};
value random = DefaultRandom();
value randomLetter => random.nextElement(alphabet);
function fitness(String a, String b) =>
count {for([c1, c2] in zipPairs(a, b)) c1 == c2};
function mutate(String string) =>
String {
for(letter in string)
if(random.nextFloat() < mutationRate)
then randomLetter
else letter
};
function makeCopies(String string) =>
{for(i in 1..childrenPerGeneration) mutate(string)};
function chooseFittest(String+ children) =>
children
.map((String element) => element->fitness(element, target))
.max(increasingItem)
.key;
variable value parent = String {for(i in 1..target.size) randomLetter};
variable value generationCount = 0;
function display() => print("``generationCount``: ``parent``");
display();
while(parent != target) {
parent = chooseFittest(parent, *makeCopies(parent));
generationCount++;
display();
}
print("mutated into target in ``generationCount`` generations!");
value mutationRate = 0.05;
value childrenPerGeneration = 100;
value target = "METHINKS IT IS LIKE A WEASEL";
value alphabet = {' ', *('A'..'Z')};
value random = DefaultRandom();
value randomLetter => random.nextElement(alphabet);
function fitness(String a, String b) =>
count {for([c1, c2] in zipPairs(a, b)) c1 == c2};
function mutate(String string) =>
String {
for(letter in string)
if(random.nextFloat() < mutationRate)
then randomLetter
else letter
};
function makeCopies(String string) =>
{for(i in 1..childrenPerGeneration) mutate(string)};
function chooseFittest(String+ children) =>
children
.map((String element) => element->fitness(element, target))
.max(increasingItem)
.key;
variable value parent = String {for(i in 1..target.size) randomLetter};
variable value generationCount = 0;
function display() => print("``generationCount``: ``parent``");
display();
while(parent != target) {
parent = chooseFittest(parent, *makeCopies(parent));
generationCount++;
display();
}
print("mutated into target in ``generationCount`` generations!");
}

View file

@ -1,23 +1,23 @@
(defun unfit (s1 s2)
(loop for a across s1
for b across s2 count(char/= a b)))
for b across s2 count(char/= a b)))
(defun mutate (str alp n) ; n: number of chars to mutate
(let ((out (copy-seq str)))
(dotimes (i n) (setf (char out (random (length str)))
(char alp (random (length alp)))))
(char alp (random (length alp)))))
out))
(defun evolve (changes alpha target)
(loop for gen from 1
with f2 with s2
with str = (mutate target alpha 100)
with fit = (unfit target str)
while (plusp fit) do
(setf s2 (mutate str alpha changes)
f2 (unfit target s2))
(when (> fit f2)
(setf str s2 fit f2)
(format t "~5d: ~a (~d)~%" gen str fit))))
with f2 with s2
with str = (mutate target alpha 100)
with fit = (unfit target str)
while (plusp fit) do
(setf s2 (mutate str alpha changes)
f2 (unfit target s2))
(when (> fit f2)
(setf str s2 fit f2)
(format t "~5d: ~a (~d)~%" gen str fit))))
(evolve 1 " ABCDEFGHIJKLMNOPQRSTUVWXYZ" "METHINKS IT IS LIKE A WEASEL")

View file

@ -3,36 +3,36 @@
(vector-push ALPHABET " ")
(define (fitness source target) ;; score >=0, best is 0
(for/sum [(s source)(t target)]
(if (= s t) 0 1)))
(for/sum [(s source)(t target)]
(if (= s t) 0 1)))
(define (mutate source rate)
(for/string [(s source)]
(if (< (random) rate) [ALPHABET (random 27)] s)))
(for/string [(s source)]
(if (< (random) rate) [ALPHABET (random 27)] s)))
(define (select parent target rate copies (copy) (score))
(define best (fitness parent target))
(define selected parent)
(for [(i copies)]
(set! copy (mutate parent rate))
(set! score (fitness copy target))
(when (< score best)
(set! selected copy)
(set! best score)))
selected )
(define best (fitness parent target))
(define selected parent)
(for [(i copies)]
(set! copy (mutate parent rate))
(set! score (fitness copy target))
(when (< score best)
(set! selected copy)
(set! best score)))
selected )
(define MUTATION_RATE 0.05) ;; 5% chances to change
(define COPIES 100)
(define TARGET "METHINKS IT IS LIKE A WEASEL")
(define (task (rate MUTATION_RATE) (copies COPIES) (target TARGET) (score))
(define parent ;; random source
(for/string
(define parent ;; random source
(for/string
[(i (string-length target))] [ALPHABET (random 27)]))
(for [(i (in-naturals))]
(set! score (fitness parent target))
(writeln i parent 'score score)
#:break (zero? score)
(set! parent (select parent target rate copies))
))
(for [(i (in-naturals))]
(set! score (fitness parent target))
(writeln i parent 'score score)
#:break (zero? score)
(set! parent (select parent target rate copies))
))

View file

@ -8,7 +8,7 @@ const string AllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int C = 100;
const real P = 0.05r;
rnd = randomGenerator;
rnd = Random;
randomChar
= AllowedCharacters[rnd.nextInt(AllowedCharacters.Length)];
@ -62,7 +62,7 @@ class EvoAlgorithm : Enumerator
enumerable() => _target;
}
public program()
public Program()
{
var attempt := new Integer();
EvoAlgorithm.new(Target,C).forEach::(current)

View file

@ -1,51 +0,0 @@
constant table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
function random_generation(integer len)
sequence s
s = rand(repeat(length(table),len))
for i = 1 to len do
s[i] = table[s[i]]
end for
return s
end function
function mutate(sequence s, integer n)
for i = 1 to length(s) do
if rand(n) = 1 then
s[i] = table[rand(length(table))]
end if
end for
return s
end function
function fitness(sequence probe, sequence target)
atom sum
sum = 0
for i = 1 to length(target) do
sum += power(find(target[i], table) - find(probe[i], table), 2)
end for
return sqrt(sum/length(target))
end function
constant target = "METHINKS IT IS LIKE A WEASEL", C = 30, MUTATE = 15
sequence parent, specimen
integer iter, best
atom fit, best_fit
parent = random_generation(length(target))
iter = 0
while not equal(parent,target) do
best_fit = fitness(parent, target)
printf(1,"Iteration: %3d, \"%s\", deviation %g\n", {iter, parent, best_fit})
specimen = repeat(parent,C+1)
best = C+1
for i = 1 to C do
specimen[i] = mutate(specimen[i], MUTATE)
fit = fitness(specimen[i], target)
if fit < best_fit then
best_fit = fit
best = i
end if
end for
parent = specimen[best]
iter += 1
end while
printf(1,"Finally, \"%s\"\n",{parent})

View file

@ -1,135 +1,135 @@
!***************************************************************************************************
module evolve_routines
module evolve_routines
!***************************************************************************************************
implicit none
!the target string:
character(len=*),parameter :: targ = 'METHINKS IT IS LIKE A WEASEL'
contains
implicit none
!the target string:
character(len=*),parameter :: targ = 'METHINKS IT IS LIKE A WEASEL'
contains
!***************************************************************************************************
!********************************************************************
pure elemental function fitness(member) result(n)
pure elemental function fitness(member) result(n)
!********************************************************************
! The fitness function. The lower the value, the better the match.
! It is zero if they are identical.
!********************************************************************
implicit none
integer :: n
character(len=*),intent(in) :: member
integer :: i
n=0
do i=1,len(targ)
n = n + abs( ichar(targ(i:i)) - ichar(member(i:i)) )
end do
implicit none
integer :: n
character(len=*),intent(in) :: member
integer :: i
n=0
do i=1,len(targ)
n = n + abs( ichar(targ(i:i)) - ichar(member(i:i)) )
end do
!********************************************************************
end function fitness
end function fitness
!********************************************************************
!********************************************************************
pure elemental subroutine mutate(member,factor)
pure elemental subroutine mutate(member,factor)
!********************************************************************
! mutate a member of the population.
!********************************************************************
implicit none
character(len=*),intent(inout) :: member !population member
real,intent(in) :: factor !mutation factor
integer,parameter :: n_chars = 27 !number of characters in set
character(len=n_chars),parameter :: chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '
real :: rnd_val
integer :: i,j,n
n = len(member)
do i=1,n
rnd_val = rand()
if (rnd_val<=factor) then !mutate this element
rnd_val = rand()
j = int(rnd_val*n_chars)+1 !an integer between 1 and n_chars
member(i:i) = chars(j:j)
end if
end do
implicit none
character(len=*),intent(inout) :: member !population member
real,intent(in) :: factor !mutation factor
integer,parameter :: n_chars = 27 !number of characters in set
character(len=n_chars),parameter :: chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '
real :: rnd_val
integer :: i,j,n
n = len(member)
do i=1,n
rnd_val = rand()
if (rnd_val<=factor) then !mutate this element
rnd_val = rand()
j = int(rnd_val*n_chars)+1 !an integer between 1 and n_chars
member(i:i) = chars(j:j)
end if
end do
!********************************************************************
end subroutine mutate
end subroutine mutate
!********************************************************************
!***************************************************************************************************
end module evolve_routines
end module evolve_routines
!***************************************************************************************************
!***************************************************************************************************
program evolve
program evolve
!***************************************************************************************************
! The main program
!***************************************************************************************************
use evolve_routines
implicit none
!Tuning parameters:
integer,parameter :: seed = 12345 !random number generator seed
integer,parameter :: max_iter = 10000 !maximum number of iterations
integer,parameter :: population_size = 200 !size of the population
real,parameter :: factor = 0.04 ![0,1] mutation factor
integer,parameter :: iprint = 5 !print every iprint iterations
!local variables:
integer :: i,iter
integer,dimension(1) :: i_best
character(len=len(targ)),dimension(population_size) :: population
!initialize random number generator:
call srand(seed)
!create initial population:
! [the first element of the population will hold the best member]
population(1) = 'PACQXJB CQPWEYKSVDCIOUPKUOJY' !initial guess
iter=0
write(*,'(A10,A30,A10)') 'iter','best','fitness'
write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
do
iter = iter + 1 !iteration counter
!write the iteration:
if (mod(iter,iprint)==0) write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
!check exit conditions:
if ( iter>max_iter .or. fitness(population(1))==0 ) exit
!copy best member and mutate:
population = population(1)
do i=2,population_size
call mutate(population(i),factor)
end do
!select the new best population member:
! [the best has the lowest value]
i_best = minloc(fitness(population))
population(1) = population(i_best(1))
end do
!write the last iteration:
if (mod(iter,iprint)/=0) write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
if (iter>max_iter) then
write(*,*) 'No solution found.'
else
write(*,*) 'Solution found.'
end if
use evolve_routines
implicit none
!Tuning parameters:
integer,parameter :: seed = 12345 !random number generator seed
integer,parameter :: max_iter = 10000 !maximum number of iterations
integer,parameter :: population_size = 200 !size of the population
real,parameter :: factor = 0.04 ![0,1] mutation factor
integer,parameter :: iprint = 5 !print every iprint iterations
!local variables:
integer :: i,iter
integer,dimension(1) :: i_best
character(len=len(targ)),dimension(population_size) :: population
!initialize random number generator:
call srand(seed)
!create initial population:
! [the first element of the population will hold the best member]
population(1) = 'PACQXJB CQPWEYKSVDCIOUPKUOJY' !initial guess
iter=0
write(*,'(A10,A30,A10)') 'iter','best','fitness'
write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
do
iter = iter + 1 !iteration counter
!write the iteration:
if (mod(iter,iprint)==0) write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
!check exit conditions:
if ( iter>max_iter .or. fitness(population(1))==0 ) exit
!copy best member and mutate:
population = population(1)
do i=2,population_size
call mutate(population(i),factor)
end do
!select the new best population member:
! [the best has the lowest value]
i_best = minloc(fitness(population))
population(1) = population(i_best(1))
end do
!write the last iteration:
if (mod(iter,iprint)/=0) write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
if (iter>max_iter) then
write(*,*) 'No solution found.'
else
write(*,*) 'Solution found.'
end if
!***************************************************************************************************
end program evolve
end program evolve
!***************************************************************************************************

View file

@ -1,51 +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
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
#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
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
#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
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 {
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)
}
write("At generation " || gen || " we found a string with perfect fitness at " || current_fitness || " reading: " || parent)
end

View file

@ -68,8 +68,8 @@ if (!Array.prototype.map) {
/* ------------------------------------- Generator -------------------------------------
* Generates a fixed length gene sequence via a gene strategy object.
* The gene strategy object must have two functions:
* - "create": returns create a new gene
* - "mutate(existingGene)": returns mutation of an existing gene
* - "create": returns create a new gene
* - "mutate(existingGene)": returns mutation of an existing gene
*/
function Generator(length, mutationRate, geneStrategy) {
this.size = length;
@ -119,9 +119,9 @@ Population.prototype.spawn = function (parent) {
/* ------------------------------------- Evolver -------------------------------------
* Attempts to converge a population based a fitness strategy object.
* The fitness strategy object must have three function
* - "score(individual)": returns a score for an individual.
* - "compare(scoreA, scoreB)": return true if scoreA is better (ie more fit) then scoreB
* - "done( score )": return true if score is acceptable (ie we have successfully converged).
* - "score(individual)": returns a score for an individual.
* - "compare(scoreA, scoreB)": return true if scoreA is better (ie more fit) then scoreB
* - "done( score )": return true if score is acceptable (ie we have successfully converged).
*/
function Evolver(size, generator, fitness) {
this.done = false;

View file

@ -3,37 +3,37 @@ local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
local c, p = 100, 0.06
local function fitness(s)
local score = #target
for i = 1,#target do
if s:sub(i,i) == target:sub(i,i) then score = score - 1 end
end
return score
local score = #target
for i = 1,#target do
if s:sub(i,i) == target:sub(i,i) then score = score - 1 end
end
return score
end
local function mutate(s, rate)
local result, idx = ""
for i = 1,#s do
if math.random() < rate then
idx = math.random(#alphabet)
result = result .. alphabet:sub(idx,idx)
else
result = result .. s:sub(i,i)
end
end
return result, fitness(result)
local result, idx = ""
for i = 1,#s do
if math.random() < rate then
idx = math.random(#alphabet)
result = result .. alphabet:sub(idx,idx)
else
result = result .. s:sub(i,i)
end
end
return result, fitness(result)
end
local function randomString(len)
local result, idx = ""
for i = 1,len do
idx = math.random(#alphabet)
result = result .. alphabet:sub(idx,idx)
end
return result
local result, idx = ""
for i = 1,len do
idx = math.random(#alphabet)
result = result .. alphabet:sub(idx,idx)
end
return result
end
local function printStep(step, s, fit)
print(string.format("%04d: ", step) .. s .. " [" .. fit .."]")
print(string.format("%04d: ", step) .. s .. " [" .. fit .."]")
end
math.randomseed(os.time())
@ -42,11 +42,11 @@ printStep(0, parent, fitness(parent))
local step = 0
while parent ~= target do
local bestFitness, bestChild, child, fitness = #target + 1
for i = 1,c do
child, fitness = mutate(parent, p)
if fitness < bestFitness then bestFitness, bestChild = fitness, child end
end
parent, step = bestChild, step + 1
printStep(step, parent, bestFitness)
local bestFitness, bestChild, child, fitness = #target + 1
for i = 1,c do
child, fitness = mutate(parent, p)
if fitness < bestFitness then bestFitness, bestChild = fitness, child end
end
parent, step = bestChild, step + 1
printStep(step, parent, bestFitness)
end

View file

@ -5,7 +5,7 @@ Gen: 4 | Fitness: 322 | KI8M5LAS<41>GJ<47>IS<49>SP<53>@)D<>V@
JCP
Gen: 5 | Fitness: 295 | UAUR08AS<EFBFBD>GJ<EFBFBD>IS<EFBFBD>8HG*<EFBFBD>+<EFBFBD>=C?UB(
Gen: 6 | Fitness: 259 | VCUQH35S<EFBFBD>HR4.L<EFBFBD>ISJQ%J<EFBFBD>OC*T=E
Gen: 7 | Fitness: 226 | LFB8GPET(LODKQ<EFBFBD>KQ<K E*PEMA6I
Gen: 7 | Fitness: 226 | LFB8GPET(LODKQ<EFBFBD>KQ<K E*PEMA6I
Gen: 8 | Fitness: 192 | EPKOLCIR<EFBFBD>QQ<EFBFBD>NF<EFBFBD>QG:B(D/U>BQGF
Gen: 9 | Fitness: 159 | N8R7?SOU<EFBFBD>NO$OK O?K?!;<EFBFBD>MB?QHG
Gen: 10 | Fitness: 146 | TGN@EQR4)PS%IS#TFJQ%A!U>BVLI

View file

@ -8,77 +8,77 @@ rand = new(Random)
// returns a random string of the specified length
def rand_string(length)
global tbl
global rand
global tbl
global rand
ret = ""
ret = ""
for i in range(1, length)
ret += tbl[rand.getInt(len(tbl))]
end
for i in range(1, length)
ret += tbl[rand.getInt(len(tbl))]
end
return ret
return ret
end
// gets the fitness of a given string
def fitness(string)
global target
fit = 0
global target
fit = 0
for i in range(0, len(string) - 1)
if string[i] != target[i]
fit -= 1
end
end
for i in range(0, len(string) - 1)
if string[i] != target[i]
fit -= 1
end
end
return fit
return fit
end
// mutates the specified string with a chance of 0.09 by default
def mutate(string)
global chance
global rand
global tbl
mutated = string
global chance
global rand
global tbl
mutated = string
for i in range(0, len(mutated) - 1)
if rand.getFloat() <= chance
mutated[i] = tbl[rand.getInt(len(tbl))]
end
end
for i in range(0, len(mutated) - 1)
if rand.getFloat() <= chance
mutated[i] = tbl[rand.getInt(len(tbl))]
end
end
return mutated
return mutated
end
// a function to find the index of the string with the best fitness
def most_fit(strlist)
global target
best_score = -(len(target) + 1)
best_index = 0
for j in range(0, len(strlist) - 1)
fit = fitness(strlist[j])
if fit > best_score
best_index = j
best_score = fit
end
end
global target
return {best_index, best_score}
best_score = -(len(target) + 1)
best_index = 0
for j in range(0, len(strlist) - 1)
fit = fitness(strlist[j])
if fit > best_score
best_index = j
best_score = fit
end
end
return {best_index, best_score}
end
parent = rand_string(len(target)); iter = 1
while parent != target
children = {}
children = {}
for i in range(1, 30)
children.append(mutate(parent))
end
for i in range(1, 30)
children.append(mutate(parent))
end
fit = most_fit(children)
parent = children[fit[0]]
print format("iter %d, score %d: %s\n", iter, fit[1], parent)
fit = most_fit(children)
parent = children[fit[0]]
print format("iter %d, score %d: %s\n", iter, fit[1], parent)
iter += 1
iter += 1
end

View file

@ -4,43 +4,43 @@ 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]);
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]);
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);
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;
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,108 +1,108 @@
PROGRAM EVOLUTION (OUTPUT);
CONST
TARGET = 'METHINKS IT IS LIKE A WEASEL';
COPIES = 100; (* 100 children in each generation. *)
RATE = 1000; (* About one character in 1000 will be a mutation. *)
TARGET = 'METHINKS IT IS LIKE A WEASEL';
COPIES = 100; (* 100 children in each generation. *)
RATE = 1000; (* About one character in 1000 will be a mutation. *)
TYPE
STRLIST = ARRAY [1..COPIES] OF STRING;
STRLIST = ARRAY [1..COPIES] OF STRING;
FUNCTION RANDCHAR : CHAR;
(* Generate a random letter or space. *)
VAR RANDNUM : INTEGER;
BEGIN
RANDNUM := RANDOM(27);
IF RANDNUM = 26 THEN
RANDCHAR := ' '
ELSE
RANDCHAR := CHR(RANDNUM + ORD('A'))
RANDNUM := RANDOM(27);
IF RANDNUM = 26 THEN
RANDCHAR := ' '
ELSE
RANDCHAR := CHR(RANDNUM + ORD('A'))
END;
FUNCTION RANDSTR (SIZE : INTEGER) : STRING;
(* Generate a random string. *)
VAR
N : INTEGER;
S : STRING;
N : INTEGER;
S : STRING;
BEGIN
S := '';
FOR N := 1 TO SIZE DO
INSERT(RANDCHAR, S, 1);
RANDSTR := S
S := '';
FOR N := 1 TO SIZE DO
INSERT(RANDCHAR, S, 1);
RANDSTR := S
END;
FUNCTION FITNESS (CANDIDATE, GOAL : STRING) : INTEGER;
(* Count the number of correct letters in the correct places *)
VAR N, MATCHES : INTEGER;
BEGIN
MATCHES := 0;
FOR N := 1 TO LENGTH(GOAL) DO
IF CANDIDATE[N] = GOAL[N] THEN
MATCHES := MATCHES + 1;
FITNESS := MATCHES
MATCHES := 0;
FOR N := 1 TO LENGTH(GOAL) DO
IF CANDIDATE[N] = GOAL[N] THEN
MATCHES := MATCHES + 1;
FITNESS := MATCHES
END;
FUNCTION MUTATE (RATE : INTEGER; S : STRING) : STRING;
(* Randomly alter a string. Characters change with probability 1/RATE. *)
VAR
N : INTEGER;
CHANGE : BOOLEAN;
N : INTEGER;
CHANGE : BOOLEAN;
BEGIN
FOR N := 1 TO LENGTH(TARGET) DO
BEGIN
CHANGE := RANDOM(RATE) = 0;
IF CHANGE THEN
S[N] := RANDCHAR
END;
MUTATE := S
FOR N := 1 TO LENGTH(TARGET) DO
BEGIN
CHANGE := RANDOM(RATE) = 0;
IF CHANGE THEN
S[N] := RANDCHAR
END;
MUTATE := S
END;
PROCEDURE REPRODUCE (RATE : INTEGER; PARENT : STRING; VAR CHILDREN : STRLIST);
(* Generate children with random mutations. *)
VAR N : INTEGER;
BEGIN
FOR N := 1 TO COPIES DO
CHILDREN[N] := MUTATE(RATE, PARENT)
FOR N := 1 TO COPIES DO
CHILDREN[N] := MUTATE(RATE, PARENT)
END;
FUNCTION FITTEST(CHILDREN : STRLIST; GOAL : STRING) : STRING;
(* Measure the fitness of each child and return the fittest. *)
(* If multiple children equally match the target, then return the first. *)
VAR
MATCHES, MOST_MATCHES, BEST_INDEX, N : INTEGER;
MATCHES, MOST_MATCHES, BEST_INDEX, N : INTEGER;
BEGIN
MOST_MATCHES := 0;
BEST_INDEX := 1;
FOR N := 1 TO COPIES DO
BEGIN
MATCHES := FITNESS(CHILDREN[N], GOAL);
IF MATCHES > MOST_MATCHES THEN
BEGIN
MOST_MATCHES := MATCHES;
BEST_INDEX := N
END
END;
FITTEST := CHILDREN[BEST_INDEX]
MOST_MATCHES := 0;
BEST_INDEX := 1;
FOR N := 1 TO COPIES DO
BEGIN
MATCHES := FITNESS(CHILDREN[N], GOAL);
IF MATCHES > MOST_MATCHES THEN
BEGIN
MOST_MATCHES := MATCHES;
BEST_INDEX := N
END
END;
FITTEST := CHILDREN[BEST_INDEX]
END;
VAR
PARENT, BEST_CHILD : STRING;
CHILDREN : STRLIST;
GENERATIONS : INTEGER;
PARENT, BEST_CHILD : STRING;
CHILDREN : STRLIST;
GENERATIONS : INTEGER;
BEGIN
RANDOMIZE;
GENERATIONS := 0;
PARENT := RANDSTR(LENGTH(TARGET));
WHILE NOT (PARENT = TARGET) DO
BEGIN
IF (GENERATIONS MOD 100) = 0 THEN WRITELN(PARENT);
GENERATIONS := GENERATIONS + 1;
REPRODUCE(RATE, PARENT, CHILDREN);
BEST_CHILD := FITTEST(CHILDREN, TARGET);
IF FITNESS(PARENT, TARGET) < FITNESS(BEST_CHILD, TARGET) THEN
PARENT := BEST_CHILD
END;
WRITE('The string was matched in ');
WRITELN(GENERATIONS, ' generations.')
RANDOMIZE;
GENERATIONS := 0;
PARENT := RANDSTR(LENGTH(TARGET));
WHILE NOT (PARENT = TARGET) DO
BEGIN
IF (GENERATIONS MOD 100) = 0 THEN WRITELN(PARENT);
GENERATIONS := GENERATIONS + 1;
REPRODUCE(RATE, PARENT, CHILDREN);
BEST_CHILD := FITTEST(CHILDREN, TARGET);
IF FITNESS(PARENT, TARGET) < FITNESS(BEST_CHILD, TARGET) THEN
PARENT := BEST_CHILD
END;
WRITE('The string was matched in ');
WRITELN(GENERATIONS, ' generations.')
END.

View file

@ -2,10 +2,10 @@ use "random"
actor Main
let _env: Env
let _rand: MT = MT // Mersenne Twister
let _rand: MT = MT // Mersenne Twister
let _target: String = "METHINKS IT IS LIKE A WEASEL"
let _possibilities: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
let _c: U16 = 100 // number of spawn per generation
let _c: U16 = 100 // number of spawn per generation
let _min_mutate_rate: F64 = 0.09
let _perfect_fitness: USize = _target.size()
var _parent: String = ""

View file

@ -1,7 +1,7 @@
target("METHINKS IT IS LIKE A WEASEL").
rndAlpha(64, 32). % Generate a single random character
rndAlpha(P, P). % 32 is a space, and 65->90 are upper case
rndAlpha(P, P). % 32 is a space, and 65->90 are upper case
rndAlpha(Ch) :- random(N), P is truncate(64+(N*27)), !, rndAlpha(P, Ch).
rndTxt(0, []). % Generate some random text (fixed length)
@ -17,16 +17,16 @@ mutate(P, [H|Txt], [H|Mut]) :- random(R), R < P, !, mutate(P, Txt, Mut).
mutate(P, [_|Txt], [M|Mut]) :- rndAlpha(M), !, mutate(P, Txt, Mut).
weasel(Tries, _, _, mutation(0, Result)) :- % No differences=success
format('~w~4|:~w~3| - ~s\n', [Tries, 0, Result]).
weasel(Tries, Chance, Target, mutation(S, Value)) :- % output progress
format('~w~4|:~w~3| - ~s\n', [Tries, S, Value]), !, % and call again
weasel(Tries, Chance, Target, Value).
format('~w~4|:~w~3| - ~s\n', [Tries, 0, Result]).
weasel(Tries, Chance, Target, mutation(S, Value)) :- % output progress
format('~w~4|:~w~3| - ~s\n', [Tries, S, Value]), !, % and call again
weasel(Tries, Chance, Target, Value).
weasel(Tries, Chance, Target, Start) :-
findall(mutation(S,M), % Generate 30 mutations, select the best.
(between(1, 30, _), mutate(Chance, Start, M), score(M,S,Target)),
Mutations), % List of 30 mutations and their scores
sort(Mutations, [Best|_]), succ(Tries, N),
!, weasel(N, Chance, Target, Best).
findall(mutation(S,M), % Generate 30 mutations, select the best.
(between(1, 30, _), mutate(Chance, Start, M), score(M,S,Target)),
Mutations), % List of 30 mutations and their scores
sort(Mutations, [Best|_]), succ(Tries, N),
!, weasel(N, Chance, Target, Best).
weasel :- % Chance->probability for a mutation, T=Target, Start=initial text
target(T), length(T, Len), rndTxt(Len, Start), Chance is 1 - (1/(Len+1)),
!, weasel(0, Chance, T, Start).
target(T), length(T, Len), rndTxt(Len, Start), Chance is 1 - (1/(Len+1)),
!, weasel(0, Chance, T, Start).

View file

@ -5,19 +5,19 @@ AllowedChars := " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
initializeParent(randChars(1)) := AllowedChars[randChars];
Fitness(target(1), current(1)) :=
let
fit[i] := true when target[i] = current[i];
in
size(fit);
let
fit[i] := true when target[i] = current[i];
in
size(fit);
Mutate(letter(0), rate(0), randRate(0), randChar(0)) :=
letter when randRate > rate
else
AllowedChars[randChar];
letter when randRate > rate
else
AllowedChars[randChar];
evolve(target(1), parent(1), C(0), P(0), rateRands(2), charRands(2)) :=
let
mutations[i] := Mutate(parent, P, rateRands[i], charRands[i]) foreach i within 1 ... C;
fitnesses := Fitness(target, mutations);
in
mutations[firstIndexOf(fitnesses, vectorMax(fitnesses))];
let
mutations[i] := Mutate(parent, P, rateRands[i], charRands[i]) foreach i within 1 ... C;
fitnesses := Fitness(target, mutations);
in
mutations[firstIndexOf(fitnesses, vectorMax(fitnesses))];

View file

@ -6,45 +6,45 @@ using namespace std;
int main(int argc, char** argv)
{
int threads = 0;
int threads = 0;
char* targetString = "METHINKS IT IS LIKE A WEASEL";
if(argc > 1) targetString = argv[1];
int C = 100;
if(argc > 2) C = atoi(argv[2]);
SL_FLOAT P = 0.05;
if(argc > 3) P = atof(argv[3]);
int seed = time(NULL);
if(argc > 4) seed = atoi(argv[4]);
char* targetString = "METHINKS IT IS LIKE A WEASEL";
if(argc > 1) targetString = argv[1];
int C = 100;
if(argc > 2) C = atoi(argv[2]);
SL_FLOAT P = 0.05;
if(argc > 3) P = atof(argv[3]);
int seed = time(NULL);
if(argc > 4) seed = atoi(argv[4]);
int targetDims[] = {strlen(targetString), 0};
Sequence<char> target((void*)targetString, targetDims);
int targetDims[] = {strlen(targetString), 0};
Sequence<char> target((void*)targetString, targetDims);
sl_init(threads);
sl_init(threads);
Sequence<char> parent;
Sequence<char> newParent;
Sequence<int> parentRands;
sl_create(seed++, 1, 27, target.size(), threads, parentRands);
sl_initializeParent(parentRands, threads, parent);
Sequence<char> parent;
Sequence<char> newParent;
Sequence<int> parentRands;
sl_create(seed++, 1, 27, target.size(), threads, parentRands);
sl_initializeParent(parentRands, threads, parent);
Sequence< Sequence<int> > charRands;
Sequence< Sequence<SL_FLOAT> > rateRands;
Sequence< Sequence<int> > charRands;
Sequence< Sequence<SL_FLOAT> > rateRands;
cout << "Start:\t" << parent << endl;
for(int i = 1; !(parent == target); i++)
{
sl_create(seed++, 1, 27, C, target.size(), threads, charRands);
sl_create(seed++, 0.0, 1.0, C, target.size(), threads, rateRands);
cout << "Start:\t" << parent << endl;
for(int i = 1; !(parent == target); i++)
{
sl_create(seed++, 1, 27, C, target.size(), threads, charRands);
sl_create(seed++, 0.0, 1.0, C, target.size(), threads, rateRands);
sl_evolve(target, parent, C, P, rateRands, charRands, threads, newParent);
parent = newParent;
sl_evolve(target, parent, C, P, rateRands, charRands, threads, newParent);
parent = newParent;
cout << "#" << i << ":\t" << parent << endl;
}
cout << "End:\t" << parent << endl;
cout << "#" << i << ":\t" << parent << endl;
}
cout << "End:\t" << parent << endl;
sl_done();
sl_done();
return 0;
return 0;
}

View file

@ -21,7 +21,7 @@ proc fitness s {
global target
set count 0
foreach c1 $s c2 $target {
if {$c1 eq $c2} {incr count}
if {$c1 eq $c2} {incr count}
}
return [expr {$count/double([llength $target])}]
}
@ -32,14 +32,14 @@ proc mutateRate {parent} {
proc mutate {rate} {
global charset parent
foreach c $parent {
lappend result [expr {rand() <= $rate ? randchar($charset) : $c}]
lappend result [expr {rand() <= $rate ? randchar($charset) : $c}]
}
return $result
}
proc que {} {
global iterations parent
puts [format "#%-4i, fitness %4.1f%%, '%s'" \
$iterations [expr {[fitness $parent]*100}] [join $parent {}]]
$iterations [expr {[fitness $parent]*100}] [join $parent {}]]
}
while {$parent ne $target} {
@ -47,7 +47,7 @@ while {$parent ne $target} {
if {!([incr iterations] % 100)} que
set copies [list [list $parent [fitness $parent]]]
for {set i 0} {$i < $C} {incr i} {
lappend copies [list [set copy [mutate $rate]] [fitness $copy]]
lappend copies [list [set copy [mutate $rate]] [fitness $copy]]
}
set parent [lindex [lsort -real -decreasing -index 1 $copies] 0 0]
}

View file

@ -13,7 +13,7 @@ set C 100
proc fitnessByEquality {target s} {
set count 0
foreach c1 $s c2 $target {
if {$c1 eq $c2} {incr count}
if {$c1 eq $c2} {incr count}
}
return [expr {$count / double([llength $target])}]
}
@ -29,7 +29,7 @@ proc mutationRate {individual} {
# Mutate a string at a particular rate (per character)
proc mutate {parent rate} {
foreach c $parent {
lappend child [expr {rand() <= $rate ? randchar() : $c}]
lappend child [expr {rand() <= $rate ? randchar() : $c}]
}
return $child
}
@ -37,7 +37,7 @@ proc mutate {parent rate} {
# Pretty printer
proc prettyPrint {iterations parent} {
puts [format "#%-4i, fitness %5.1f%%, '%s'" $iterations \
[expr {[fitness $parent]*100}] [join $parent {}]]
[expr {[fitness $parent]*100}] [join $parent {}]]
}
# The evolutionary algorithm itself
@ -48,18 +48,18 @@ proc evolve {initialString} {
set parent [split $initialString {}]
for {set iterations 0} {[fitness $parent] < 1} {incr iterations} {
set rate [mutationRate $parent]
set rate [mutationRate $parent]
if {$iterations % 100 == 0} {
prettyPrint $iterations $parent
}
if {$iterations % 100 == 0} {
prettyPrint $iterations $parent
}
set copies [list [list $parent [fitness $parent]]]
for {set i 0} {$i < $C} {incr i} {
lappend copies [list \
[set copy [mutate $parent $rate]] [fitness $copy]]
}
set parent [lindex [lsort -real -decreasing -index 1 $copies] 0 0]
set copies [list [list $parent [fitness $parent]]]
for {set i 0} {$i < $C} {incr i} {
lappend copies [list \
[set copy [mutate $parent $rate]] [fitness $copy]]
}
set parent [lindex [lsort -real -decreasing -index 1 $copies] 0 0]
}
puts ""
prettyPrint $iterations $parent

View file

@ -1,60 +0,0 @@
Option explicit
Function rand(l,u) rand= Int((u-l+1)*Rnd+l): End Function
Function fitness(i)
Dim d,j
d=0
For j=1 To lmod
If Mid(model,j,1)=Mid(cpy(i),j,1) Then d=d+1
Next
fitness=d
End Function
Sub mutate(i)
Dim j
cpy(i)=""
For j=1 To lmod
If Rnd<mut Then
cpy(i)=cpy(i)& Chr(rand(lb,ub))
Else
cpy(i)=cpy(i)& Mid(cpy(0),j,1)
End If
Next
End sub
Sub print(s):
On Error Resume Next
WScript.stdout.WriteLine (s)
If err= &h80070006& Then WScript.Echo " Please run this script with CScript": WScript.quit
End Sub
Dim model,lmod,ub,lb,c,cpy,fit,best,i,d,mut,cnt
model="METHINKS IT IS LIKE A WEASEL"
model=Replace(model," ","@")
lmod=Len(model)
Randomize Timer
ub=Asc("Z")
lb=Asc("@")
c=10
mut=.05
best=0
ReDim cpy(c)
For i=0 To lmod-1
cpy(best)=cpy(best)& chr(rand(lb,ub))
Next
best=0
cnt=0
do
cpy(0)=cpy(best)
fit=0
For i=1 To c
mutate(i)
d=fitness(i)
If d>fit Then fit=d:best=i
Next
cnt=cnt+1
If (fit=lmod) Or ((cnt mod 10)=0) Then print cnt &" " & fit & " "& Replace (cpy(best),"@"," ")
Loop While fit <>lmod

View file

@ -9,6 +9,6 @@ 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 });
.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);