Data update
This commit is contained in:
parent
5150844a7d
commit
4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
target: "METHINKS IT IS LIKE A WEASEL"
|
||||
alphabet: [` `] ++ @`A`..`Z`
|
||||
alphabet: [' '] ++ @'A'..'Z'
|
||||
p: 0.05
|
||||
c: 100
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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!");
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
@ -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
|
||||
!***************************************************************************************************
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 = ""
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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))];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue