Paste: GP
Author: | jeff |
Mode: | factor |
Date: | Tue, 13 Jan 2009 22:08:45 |
Plain Text |
USING: kernel accessors math combinators sequences continuations random
arrays math.order sorting quotations grouping fry prettyprint
io locals ;
IN: ga
: nop ( -- ) ;
: test-quot-on-stack ( stack quot -- stack )
'[ _ _ with-datastack ] [ drop f ] recover ;
: rand-in-%? ( n -- ? ) 100 random > ;
TUPLE: genome
{ sequence initial: f }
{ fitness initial: f } ;
: <genome> ( -- obj ) \ genome new ;
: seq>genome ( seq -- obj ) <genome> swap >>sequence ;
TUPLE: ga population-size possible-genes
crossover-rate mutation-rate genome-length
training-input-stack training-output-stack
{ population initial: f }
{ #generation initial: 0 }
{ evaluated? initial: f } ;
GENERIC: rand-gene> ( ga -- gene )
GENERIC: genome-decoder ( genome ga -- obj )
GENERIC: calculate-genome-fitness ( genome ga -- )
GENERIC: generate-random-genome-sequence ( ga -- seq )
GENERIC: renew-population ( ga -- ga )
GENERIC: compare-output-to-awaited-result ( stack ga -- x )
GENERIC: genome-stack-formalizer ( quot ga -- quot )
<PRIVATE
: sequence-mutate ( seq ga -- seq )
[ mutation-rate>> ] [ ] bi
'[ _ rand-in-%? [ drop _ rand-gene> ] when ] map ;
: genome-mutate ( genome ga -- )
[ sequence-mutate ] curry change-sequence drop ;
: mutate-population ( ga -- ga )
[ ] [ population>> 1 tail ] [ ] tri
[ genome-mutate ] curry each ;
: sequence-crossover ( seq seq -- seq seq )
[ dup length 1+ random cut ] bi@
spin [ append ] 2bi@ ;
: genome-crossover ( genome genome -- genome genome )
2dup [ sequence>> ] bi@
sequence-crossover
swapd
[ >>sequence ] 2bi@ ;
: sort-genome-seq ( seq -- seq )
[ [ fitness>> ] compare ] sort ;
: order-population ( ga -- ga )
[ [ fitness>> ] filter
sort-genome-seq
] change-population ;
: calculate-fitness ( ga -- ga )
[ ]
[ population>> ]
[ '[ _ calculate-genome-fitness ] ]
tri each ;
: evaluate-population ( ga -- ga )
calculate-fitness
order-population
t >>evaluated? ;
: n-random-genomes ( n ga -- seq )
'[ _ generate-random-genome-sequence seq>genome ]
replicate ;
: crossover-population ( ga -- ga )
dup crossover-rate>>
'[ unclip clone tuck clone
[ _ rand-in-%?
[ clone genome-crossover drop ]
[ drop ] if
] curry map
swap prefix
] change-population ;
: complete-population ( ga -- ga )
dup [ population-size>> ] [ population>> length ] bi -
over n-random-genomes
[ append ] curry change-population ;
: execute-genome ( genome ga -- ) genome-decoder call ; inline
PRIVATE>
: init-population ( ga -- ga )
dup
[ population-size>> ] keep
n-random-genomes >>population
0 >>#generation
f >>evaluated? ;
: new-generation ( ga -- ga )
dup population>> length 0 =
[ init-population ] [ renew-population ] if
f >>evaluated?
[ 1+ ] change-#generation ;
: ga-step ( ga -- ga )
new-generation
evaluate-population ;
: best-genome> ( ga -- genome ) population>> first ;
: best-fitness> ( ga -- x ) best-genome> fitness>> ;
: ga-execute ( ga -- ) [ best-genome> ] keep execute-genome ;
: ga-situation ( ga -- ga )
[ ] [ "generation: " write #generation>> . ] [ population>> ] tri
[ first
[ "best genome: " write sequence>> . ]
[ "best fitness: " write fitness>> . ] bi
] [ 2drop "nothing good to display" . ] recover ;
:: (n-ga-step) ( ga n -- ga )
n
[ 1- dup 1 < ga best-fitness> 0 = or ]
[ ga ga-step drop ]
[ drop ga ]
until ;
: n-ga-step ( ga n -- ga )
[ ga-step ] dip (n-ga-step) ;
: ga-step. ( ga -- ga ) ga-step ga-situation ;
: n-ga-step. ( ga n -- ga ) n-ga-step ga-situation ;
M: ga rand-gene> possible-genes>> random ;
M: ga genome-decoder drop sequence>> >quotation ;
M: ga genome-stack-formalizer drop ;
M: ga calculate-genome-fitness
over sequence>> length 0 = [ drop f ] [
[ ]
[ nip training-input-stack>> ]
[ [ genome-decoder ] keep genome-stack-formalizer ]
2tri
test-quot-on-stack
[ swap compare-output-to-awaited-result ] [ drop f ] if*
] if
>>fitness drop
;
M: ga renew-population
mutate-population
complete-population
crossover-population ;
M: ga generate-random-genome-sequence
[ genome-length>> ] keep
[ rand-gene> ] curry replicate ;
Author: | jeff |
Mode: | factor |
Date: | Tue, 13 Jan 2009 22:11:21 |
Plain Text |
TUPLE: 24game-player < ga ;
: <24game-player> ( -- obj )
24game-player new
30 >>population-size
{ + - * / rot swap nop } >>possible-genes
30 >>crossover-rate
30 >>mutation-rate
3 >>genome-length
{ 17 2 5 1 } >>training-input-stack
{ 24 } >>training-output-stack
init-population
evaluate-population ;
M: 24game-player compare-output-to-awaited-result
training-output-stack>>
2dup [ length ] bi@ =
[ [ first ] bi@ - abs ] [ 2drop f ] if ;
Author: | jeff |
Mode: | factor |
Date: | Tue, 13 Jan 2009 22:14:23 |
Plain Text |
TUPLE: function-finder < ga ;
: <function-finder> ( -- obj )
function-finder new
50 >>population-size
{ swap over drop nip dup nop 1 2 3 4 5 6 sgn min max neg mod rem + - * / -1 -2 -1 -3 -4 } >>possible-genes
10 >>crossover-rate
30 >>mutation-rate
5 >>genome-length
{ { 1 2 3 4 } } >>training-input-stack
{ { 2 4 6 8 } } >>training-output-stack
init-population
evaluate-population ;
M: function-finder genome-stack-formalizer drop [ map ] curry ;
M: function-finder compare-output-to-awaited-result
training-output-stack>>
2dup [ length 1 = ] bi@ and
[
[ first ] bi@
2dup [ length ] bi@ =
[
[ - abs ] 2map sum
] [ 2drop 1000 ] if
] [ 2drop f ] if ;
M: function-finder genome-decoder drop sequence>> >quotation ;
New Annotation