-
Notifications
You must be signed in to change notification settings - Fork 0
/
GenPerm.hs
148 lines (122 loc) · 4.36 KB
/
GenPerm.hs
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
145
146
147
148
import Moo.GeneticAlgorithm.Binary
import Control.Arrow (first)
import Control.Monad (when)
import Data.List (intercalate, sortBy, permutations)
import Data.Ord (comparing)
import NaturalLanguageModule (naturalismDefault)
import Moo.GeneticAlgorithm.Continuous (getRandomGenomes)
import BlindtextModule (cryptotext1)
import SnModule (perm, Direction (..), PermKey)
import TypeModule
import Reordering (combineMutationOps, completeShiftMutate, swapMutate, listswapMutate, revMutate, blockSwapMutate, shuffelMutate, shiftMutate, initializeEnumGenome, edgeCrossover)
{-
Sorting a list (of Characters) using a genetic algorythm.
The output should be readable for human, but for a nice
plot with gnuplot you can paste this in "plot_output"...
set terminal postscript eps enhanced color font 'Helvetica,10'
set xlabel 'Generations'
set ylabel 'sorting fittnes'
set output 'output.eps'
set key bottom box
plot 'output.txt' using 1:2 with lines lc rgb 'red' lw 4 title 'best value',\
'output.txt' using 1:3 with lines lc rgb 'dark-grey' title 'median value',\
'output.txt' using 1:4 with lines lc rgb 'grey' title 'worst value'
...and this in "runGensort.sh"...
#!/bin/bash
ghc --make GenSort.hs
time ./GenSort > output.txt
gnuplot -p plot_output.plt
filelength=$(wc -l < output.txt)
echo "Final Generation: $(($filelength - 6))"
tail -5 output.txt
... and run it with ./runGensort
-}
period = 26
genomesize = period
-- stopconditions (they are very high)
maxiters = 1000000
minFittness = 100750
timeLimit = 1200 -- in seconds
problem :: Problem Char
problem = cryptotext1
popsize :: Int
popsize = 9
selection :: SelectionOp a
selection = rouletteSelect 5
crossover :: (Ord a) => CrossoverOp a
crossover =
edgeCrossover 2
--noCrossover
--orderCrossover 0.3
--uniformCrossover 0.3
mutation :: MutationOp a
mutation =
combineMutationOps [shiftMutate, completeShiftMutate]
--shiftMutate
--listswapMutate
--blockSwapMutate
elitesize = 1
-- sortingFittnes ls == 1 is aquivalent to ls == sort ls
natFitnes :: Problem Char -> PermKey -> Double
natFitnes problem genome =
naturalismDefault (perm Decrypt genome problem)
-- /P (fromIntegral . twoOutOf . length) problem
where
twoOutOf :: Int -> Int
twoOutOf 1 = 0
twoOutOf n = n - 1 + twoOutOf (n-1)
showGenome :: Problem Char -> PermKey -> String
showGenome problem genome = "#Genome " ++ show genome
++ "\n#makes " ++ (begining . show) problem
++ "\n#to " ++ (begining . show . perm Decrypt genome) problem
++ "\n#(natFitnes: " ++ show (natFitnes problem genome) ++ ")"
where
showBits :: [Bool] -> String
showBits = concatMap (show . fromEnum)
geneticAlgorithm :: Problem Char -> IO (Population Int)
geneticAlgorithm problem = do
runIO (initializeEnumGenome popsize period) $ loopIO
[DoEvery 1 (logStats problem), TimeLimit timeLimit]
(Or (Generations maxiters) (IfObjective (any (>= minFittness))))
nextGen
where
nextGen :: StepGA Rand Int
nextGen = nextGeneration Maximizing fitness selection elitesize crossover mutation
fitness :: [Genome Int] -> Population Int
fitness = map (\ genome -> (genome, natFitnes problem genome))
-- Gnuplotreadable statistics for 1 Generation
logStats :: Problem Char -> Int -> Population Int -> IO ()
logStats problem iterno pop = do
when (iterno == 0) $
putStrLn "# generation medianValue bestValue"
let gs = map takeGenome . bestFirst Maximizing $ pop -- genomes
let best = head gs
let median = gs !! (length gs `div` 2)
let worst = last gs
putStrLn $ unwords [ show iterno
, (begining . show . natFitnes problem) best
, (braces . show) best
, (begining . show . natFitnes problem) median
, (braces . show) median
, (begining . show . natFitnes problem) worst
, (braces . show) worst
, (take 10 . show . perm Decrypt best) problem
]
where
braces :: String -> String
braces str = "(" ++ str ++ ")"
main :: IO()
main = do
finalPop <- geneticAlgorithm problem
let winner = takeGenome . head . bestFirst Maximizing $ finalPop
putStrLn $ showGenome problem winner
return ()
begining :: String -> String
begining xs = take n xs -- ++ "..."
where n = 6
-- Dealing with Genomes
-- just for testing
printAllPossibleSolutions :: IO()
printAllPossibleSolutions = putStrLn . unlines . map show . sortBy (comparing snd) . zip genomes . map (natFitnes problem) $ genomes
where
genomes = permutations . take period $ [1..]