forked from nsmryan/HEAL
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTest.hs
More file actions
145 lines (126 loc) · 4.51 KB
/
Test.hs
File metadata and controls
145 lines (126 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
{-# LANGUAGE BangPatterns #-}
module Main (
main,
rndPop,
rgeprecomb,
wrapPop,
reify,
wrapV,
fRndPop
) where
import EA
import EAMonad
import Randomly
import Postfix
import Maybe
import SymReg
import Selection
import Operators
import LinF
import qualified GeneticOperators as G
import Control.Monad
import Data.Monoid
import qualified Data.Foldable as F
import qualified Data.Vector as V
import qualified Data.IntSet as S
import qualified Data.IntMap as M
import qualified Data.Traversable as Tr
codonLength :: [a] -> [b] -> Int
codonLength ops terms = (1+) $ ceiling $ logBase 2 (fromIntegral $ max (length ops) (length terms))
--create pop
rndPop ps is cs = do
inds <- V.replicateM ps $! V.replicateM (is*cs) nextBool
return $! wrapPop inds
fRndPop ps is cs = fmut 0.5 $ finit ps (finit (is*cs) True)
wrapV v = linf (V.length v) $ \i -> v V.! i
wrapPop pop = wrapV $ V.map wrapV pop
reify (LinF s f) = let pop = V.generate s (\y -> V.generate (fsize (f y)) (\ x -> findex (f y) x)) in
-- ugly strictness hack
(V.foldl (\p i -> (V.foldl (\i l -> l `seq` i ) i i) `seq` p) pop pop) `seq` pop
rewrap = wrapPop . reify
orOn f b g = if b then g else f
--mutation
fmut pm (LinF s pop) = do
let indlen = G.count (pop 0)
let ms = ceiling $ (pm *) $ fromIntegral (s*indlen)
muts <- replicateM ms $ nextInt s
pnts <- replicateM ms $ nextInt indlen
let addlocus map i l = M.insertWith S.union i (S.singleton l) map
let mapping = foldl (\ map (i, p) -> addlocus map i p) M.empty (zip muts pnts)
return $ linf s $ \y -> let (LinF s' ind) = pop y in
linf s' $ \x -> maybe (ind x) (\set -> orOn id (S.member x set) not (ind x)) (M.lookup y mapping)
frot pr cs (LinF s pop) = do
let indlen = G.count (pop 0)
let rs = ceiling $ (pr *) $ fromIntegral s
inds <- replicateM rs $ nextInt s
rawrots <- forM inds $ \ _ -> nextInt indlen
let rots = map (\rp -> (rp `div` cs) * cs) rawrots
let mapping = M.fromList $ zip inds rots
return $ linf s $ \ y -> let (LinF s' ind) = pop y in
linf s' $ \x -> maybe (ind x) (\i -> ind $ (i+x) `mod` s') (M.lookup y mapping)
fcross1 pc1 (LinF s pop) = do
let indlen = G.count (pop 0)
let cs = ceiling $ ((pc1 / 2.0) *) $ fromIntegral s
rands <- shuffle [0..s-1]
let (first, second) = splitAt cs $ take (2*cs) rands
cps <- replicateM cs (nextInt cs)
let firsts = M.fromList $ zip first $ zip second cps
let seconds = M.fromList $ zip second $ zip first cps
let inrange x y (y', cap) = if x < cap then y else y'
let notinrange x y (y', cap) = if x >= cap then y else y'
let getGuy x y set t = fmap (t x y) (M.lookup y set)
let find y x = getGuy x y firsts inrange `mplus` getGuy x y seconds notinrange
return $ linf s $ \y -> let (LinF s' ind) = pop y in
linf s' $ \x -> maybe (ind x) (\y -> G.index (pop y) x) (find y x)
fcross2 pc2 pop = do
pop' <- fcross1 pc2 pop
fcross1 pc2 pop'
tournselect (LinF s pop) = do
pop' <- V.replicateM s $ tourny pop s
return $ linf s $ \y -> fst $ pop (G.index pop' y)
tourny p s = do
i <- nextInt s
i' <- nextInt s
b <- test 0.75
let f = snd $ p i
let f' = snd $ p i'
let better = if f > f' then i else i'
let worse = if f <= f' then i else i'
return $ if b then better else worse
rgeprecomb cs pm pr pc1 pc2 pop =
fmut pm pop >>= frot pr cs >>=
fcross1 pc1 >>= fcross2 pc2 >>= return . rewrap
ps = 1000
is = 100
gens = 500
pm = 0.02
pr = 0.02
pc1 = 0.7
pc2 = 0.7
main = do
(p, e, l, g) <- runEAIO (rgep ps is pm pr pc1 pc2 gens ops terms eval) ()
writeFile "rtestlf" l
ops = [plus, minus, mult, divide]
terms = [var] ++ constants [1, 2, 3, 5, 7]
f x = (3*((x+1)^3)) + (2*((x+1)^2)) + (x+1)
testcases = uniformCases (-10, 10) 21 f
eval = return . resError testcases 10000
rgep ps is pm pr pc1 pc2 gens ops terms eval = let cs = codonLength ops terms in
--ga (fRndPop ps is cs)
ga (rndPop ps is cs)
(\p -> printBest p >>= evaluate (eval . postfix . cdns2syms cs ops terms))
tournselect
(rgeprecomb cs pm pr pc1 pc2)
True
(maxGens gens)
cdns2syms cs ops terms cdns = sym : syms where
index = F.foldl' (\i b -> i*2 + if b then 0 else 1) 0 $ G.rest (G.take cs cdns)
symset = if G.first cdns then ops else terms
sym = symset !! (index `mod` length symset)
syms = if G.isEmpty cdns' then [] else cdns2syms cs ops terms cdns'
where cdns' = G.drop cs cdns
bitsToString s = F.foldl' (++) "" (fmap (\b -> if b then "1" else "0") s)
printBest pop = do
gens <- getGens
if gens `mod` 50 == 0 then record (F.foldl' (\a b -> b ++ "\n" ++ a) "" (fmap bitsToString pop)) else record ""
return $ pop