Compare commits
3 Commits
57cf1452bf
...
c261fcdfbb
Author | SHA1 | Date | |
---|---|---|---|
|
c261fcdfbb | ||
|
f79355e4c1 | ||
|
6435f4aca2 |
|
@ -50,6 +50,7 @@ library
|
||||||
, Szenario191
|
, Szenario191
|
||||||
, LambdaCalculus
|
, LambdaCalculus
|
||||||
, IrisDataset
|
, IrisDataset
|
||||||
|
, IrisData
|
||||||
|
|
||||||
executable haga
|
executable haga
|
||||||
build-depends: base
|
build-depends: base
|
||||||
|
@ -83,6 +84,7 @@ executable haga
|
||||||
, Szenario191
|
, Szenario191
|
||||||
, LambdaCalculus
|
, LambdaCalculus
|
||||||
, IrisDataset
|
, IrisDataset
|
||||||
|
, IrisData
|
||||||
|
|
||||||
executable haga-test
|
executable haga-test
|
||||||
build-depends: base
|
build-depends: base
|
||||||
|
@ -117,3 +119,4 @@ executable haga-test
|
||||||
, Szenario191
|
, Szenario191
|
||||||
, LambdaCalculus
|
, LambdaCalculus
|
||||||
, IrisDataset
|
, IrisDataset
|
||||||
|
, IrisData
|
||||||
|
|
40
src/GA.hs
40
src/GA.hs
|
@ -20,7 +20,7 @@
|
||||||
-- In order to use it for a certain problem, basically, you have to make your
|
-- In order to use it for a certain problem, basically, you have to make your
|
||||||
-- solution type an instance of 'Individual' and then simply call the 'run'
|
-- solution type an instance of 'Individual' and then simply call the 'run'
|
||||||
-- function.
|
-- function.
|
||||||
module GA (Environment, new, population, mutate, crossover1, crossover, nX, Evaluator, fitness, calc, Individual, GA.run, Tournament (..), N, R, Population, steps, bests, runTests) where
|
module GA (Environment, new, population, mutate, crossover1, crossover, nX, Fitness, getR, Evaluator, fitness,fitness', calc, Individual, GA.run, Tournament (..), N, R, Population, steps, bests, runTests) where
|
||||||
|
|
||||||
import Control.Arrow hiding (first, second)
|
import Control.Arrow hiding (first, second)
|
||||||
import Data.List.NonEmpty ((<|))
|
import Data.List.NonEmpty ((<|))
|
||||||
|
@ -83,13 +83,16 @@ class (Pretty e, Individual i) => Environment i e | e -> i where
|
||||||
-- |
|
-- |
|
||||||
-- An Evaluator that Individuals of type i can be evaluated by
|
-- An Evaluator that Individuals of type i can be evaluated by
|
||||||
-- It stores all information required to evaluate an individuals fitness
|
-- It stores all information required to evaluate an individuals fitness
|
||||||
class (Individual i) => Evaluator i e where
|
class (Individual i, Fitness r) => Evaluator i e r | i -> e r where
|
||||||
-- |
|
-- |
|
||||||
-- An individual's fitness. Higher values are considered “better”.
|
-- An individual's fitness. Higher values are considered “better”.
|
||||||
--
|
--
|
||||||
-- We explicitely allow fitness values to be have any sign (see, for example,
|
-- We explicitely allow fitness values to be have any sign (see, for example,
|
||||||
-- 'proportionate1').
|
-- 'proportionate1').
|
||||||
fitness :: e -> i -> R
|
fitness :: e -> i -> R
|
||||||
|
fitness env i = getR ( fitness' env i)
|
||||||
|
|
||||||
|
fitness' :: e -> i -> r
|
||||||
|
|
||||||
-- TODO kinda hacky?!?
|
-- TODO kinda hacky?!?
|
||||||
calc :: e -> Population i -> IO e
|
calc :: e -> Population i -> IO e
|
||||||
|
@ -98,6 +101,12 @@ class (Individual i) => Evaluator i e where
|
||||||
|
|
||||||
class (Pretty i, Ord i) => Individual i
|
class (Pretty i, Ord i) => Individual i
|
||||||
|
|
||||||
|
class (Show i) => Fitness i where
|
||||||
|
getR :: i -> R
|
||||||
|
|
||||||
|
instance Fitness Double where
|
||||||
|
getR d = d
|
||||||
|
|
||||||
-- |
|
-- |
|
||||||
-- Populations are just basic non-empty lists.
|
-- Populations are just basic non-empty lists.
|
||||||
type Population i = NonEmpty i
|
type Population i = NonEmpty i
|
||||||
|
@ -149,18 +158,18 @@ bestsBy' k f pop
|
||||||
|
|
||||||
-- |
|
-- |
|
||||||
-- The @k@ worst individuals in the population (and the rest of the population).
|
-- The @k@ worst individuals in the population (and the rest of the population).
|
||||||
worst :: (Individual i, Evaluator i e) => e -> N -> Population i -> (NonEmpty i, [i])
|
worst :: (Individual i, Evaluator i e r) => e -> N -> Population i -> (NonEmpty i, [i])
|
||||||
worst e k = bestsBy k (negate . fitness e)
|
worst e k = bestsBy k (negate . fitness e)
|
||||||
|
|
||||||
-- |
|
-- |
|
||||||
-- The @k@ best individuals in the population (and the rest of the population).
|
-- The @k@ best individuals in the population (and the rest of the population).
|
||||||
bests :: (Individual i, Evaluator i e) => e -> N -> Population i -> (NonEmpty i, [i])
|
bests :: (Individual i, Evaluator i e r) => e -> N -> Population i -> (NonEmpty i, [i])
|
||||||
bests e k = bestsBy k (fitness e)
|
bests e k = bestsBy k (fitness e)
|
||||||
|
|
||||||
-- TODO add top x percent parent selection (select n guys, sort by fitness first)
|
-- TODO add top x percent parent selection (select n guys, sort by fitness first)
|
||||||
|
|
||||||
reproduce ::
|
reproduce ::
|
||||||
(Individual i, Environment i env, Evaluator i eval, SelectionType s) =>
|
(Individual i, Environment i env, Evaluator i eval r, SelectionType s) =>
|
||||||
eval ->
|
eval ->
|
||||||
env ->
|
env ->
|
||||||
-- | Mechanism for selecting parents
|
-- | Mechanism for selecting parents
|
||||||
|
@ -176,7 +185,7 @@ reproduce eval env selectT nParents pop = do
|
||||||
return pop'
|
return pop'
|
||||||
|
|
||||||
selectBest ::
|
selectBest ::
|
||||||
(Individual i, Evaluator i eval) =>
|
(Individual i, Evaluator i eval r) =>
|
||||||
eval ->
|
eval ->
|
||||||
-- | Elitism ratio @pElite@
|
-- | Elitism ratio @pElite@
|
||||||
R ->
|
R ->
|
||||||
|
@ -197,7 +206,7 @@ selectBest eval pElite pop nPop = do
|
||||||
else return $ elitists <> (fst $ bests eval (nPop - length elitists) (NE.fromList rest))
|
else return $ elitists <> (fst $ bests eval (nPop - length elitists) (NE.fromList rest))
|
||||||
|
|
||||||
run ::
|
run ::
|
||||||
(Individual i, Evaluator i eval, Environment i env, SelectionType s) =>
|
(Individual i, Evaluator i eval r, Environment i env, SelectionType s) =>
|
||||||
eval ->
|
eval ->
|
||||||
env ->
|
env ->
|
||||||
-- | Mechanism for selecting parents
|
-- | Mechanism for selecting parents
|
||||||
|
@ -209,18 +218,15 @@ run ::
|
||||||
-- | Population size
|
-- | Population size
|
||||||
N ->
|
N ->
|
||||||
Termination i ->
|
Termination i ->
|
||||||
Producer (Int, R) IO (Population i)
|
Producer (Int, r) IO (Population i)
|
||||||
run eval env selectionType nParents pElite nPop term = do
|
run eval env selectionType nParents pElite nPop term = do
|
||||||
mwc <- liftIO createSystemRandom
|
mwc <- liftIO createSystemRandom
|
||||||
let smpl = ((sampleFrom mwc) :: RVar a -> IO a)
|
let smpl = ((sampleFrom mwc) :: RVar a -> IO a)
|
||||||
firstPop <- liftIO $ smpl $ (population env nPop)
|
firstPop <- liftIO $ smpl $ (population env nPop)
|
||||||
_ <- liftIO $ putText $ pretty $ NE.head firstPop
|
|
||||||
firstPop <- liftIO $ smpl $ (population env nPop)
|
|
||||||
_ <- liftIO $ putText $ pretty $ NE.head firstPop
|
|
||||||
res <- runIter eval 0 firstPop smpl
|
res <- runIter eval 0 firstPop smpl
|
||||||
return res
|
return res
|
||||||
where
|
where
|
||||||
runIter eval count pop smpl =
|
runIter eval count pop smpl = (
|
||||||
if term pop count
|
if term pop count
|
||||||
then do
|
then do
|
||||||
return pop
|
return pop
|
||||||
|
@ -229,10 +235,10 @@ run eval env selectionType nParents pElite nPop term = do
|
||||||
withKids <- liftIO $ smpl $ reproduce eval env selectionType nParents pop
|
withKids <- liftIO $ smpl $ reproduce eval env selectionType nParents pop
|
||||||
eval <- liftIO $ calc eval withKids
|
eval <- liftIO $ calc eval withKids
|
||||||
resPop <- liftIO $ smpl $ selectBest eval pElite withKids nPop
|
resPop <- liftIO $ smpl $ selectBest eval pElite withKids nPop
|
||||||
let fBest = fitness eval $ NE.head $ fst $ bests eval 1 resPop
|
let fBest = fitness' eval $ NE.head $ fst $ bests eval 1 resPop
|
||||||
Pipes.yield (count, fBest)
|
Pipes.yield (count, fBest)
|
||||||
res <- runIter eval (count + 1) resPop smpl
|
res <- runIter eval (count + 1) resPop smpl
|
||||||
return res
|
return res)
|
||||||
|
|
||||||
-- * Selection mechanisms
|
-- * Selection mechanisms
|
||||||
|
|
||||||
|
@ -242,7 +248,7 @@ run eval env selectionType nParents pElite nPop term = do
|
||||||
data Tournament = Tournament N
|
data Tournament = Tournament N
|
||||||
|
|
||||||
class SelectionType t where
|
class SelectionType t where
|
||||||
select :: (Individual i, Evaluator i e) => t -> N -> Population i -> e -> RVar (NonEmpty i)
|
select :: (Individual i, Evaluator i e r) => t -> N -> Population i -> e -> RVar (NonEmpty i)
|
||||||
|
|
||||||
-- type Selection m i = N -> Population i -> m (NonEmpty i)
|
-- type Selection m i = N -> Population i -> m (NonEmpty i)
|
||||||
|
|
||||||
|
@ -252,7 +258,7 @@ instance SelectionType Tournament where
|
||||||
-- |
|
-- |
|
||||||
-- Selects one individual from the population using tournament selection.
|
-- Selects one individual from the population using tournament selection.
|
||||||
tournament1 ::
|
tournament1 ::
|
||||||
(Individual i, Evaluator i e) =>
|
(Individual i, Evaluator i e r) =>
|
||||||
e ->
|
e ->
|
||||||
-- | Tournament size
|
-- | Tournament size
|
||||||
N ->
|
N ->
|
||||||
|
@ -323,7 +329,7 @@ instance Environment Integer IntTestEnviroment where
|
||||||
|
|
||||||
data NoData = NoData deriving (Eq)
|
data NoData = NoData deriving (Eq)
|
||||||
|
|
||||||
instance Evaluator Integer NoData where
|
instance Evaluator Integer NoData Double where
|
||||||
fitness _ = fromIntegral . negate
|
fitness _ = fromIntegral . negate
|
||||||
|
|
||||||
prop_children_asManyAsParents ::
|
prop_children_asManyAsParents ::
|
||||||
|
|
149
src/IrisDataset.hs
Normal file
149
src/IrisDataset.hs
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE NoImplicitPrelude #-}
|
||||||
|
|
||||||
|
module IrisDataset
|
||||||
|
( module LambdaCalculus,
|
||||||
|
module IrisDataset,
|
||||||
|
module IrisData,
|
||||||
|
module GA,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import qualified Data.ByteString.Lazy as B
|
||||||
|
import Data.Csv
|
||||||
|
import qualified Data.List.NonEmpty as NE
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import Data.Random
|
||||||
|
import Data.Random.Distribution.Uniform
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Data.Tuple.Extra
|
||||||
|
import qualified Debug.Trace as DB
|
||||||
|
import GA
|
||||||
|
import LambdaCalculus
|
||||||
|
import IrisData
|
||||||
|
import qualified Language.Haskell.Interpreter as Hint
|
||||||
|
import qualified Language.Haskell.Interpreter.Unsafe as Hint
|
||||||
|
import Protolude
|
||||||
|
import qualified Type.Reflection as Ref
|
||||||
|
|
||||||
|
irisLE :: LambdaEnviroment
|
||||||
|
irisLE =
|
||||||
|
LambdaEnviroment
|
||||||
|
{ functions =
|
||||||
|
Map.fromList
|
||||||
|
[ ((Ref.SomeTypeRep (Ref.TypeRep @(Float -> Float -> Float))), ["(+)", "(-)", "(*)"]),
|
||||||
|
((Ref.SomeTypeRep (Ref.TypeRep @(Float -> Float -> Bool))), ["(>)", "(==)", "(>=)"]),
|
||||||
|
((Ref.SomeTypeRep (Ref.TypeRep @(IrisClass -> IrisClass -> Bool))), ["(==)"]),
|
||||||
|
((Ref.SomeTypeRep (Ref.TypeRep @(Bool -> Float -> Float -> Float))), ["if'"]),
|
||||||
|
((Ref.SomeTypeRep (Ref.TypeRep @(Bool -> Bool -> Bool))), ["(&&)", "(||)"]),
|
||||||
|
((Ref.SomeTypeRep (Ref.TypeRep @(Bool -> IrisClass -> IrisClass -> IrisClass))), ["if'"])
|
||||||
|
],
|
||||||
|
constants =
|
||||||
|
Map.fromList
|
||||||
|
[ ((Ref.SomeTypeRep (Ref.TypeRep @(Float))), [(fmap show (uniform 0 10 :: RVar Float))]),
|
||||||
|
((Ref.SomeTypeRep (Ref.TypeRep @(Bool))), [(fmap show (uniform True False :: RVar Bool))]),
|
||||||
|
((Ref.SomeTypeRep (Ref.TypeRep @(IrisClass))), [(fmap show (enumUniform Setosa Versicolor :: RVar IrisClass))])
|
||||||
|
],
|
||||||
|
targetType = (Ref.SomeTypeRep (Ref.TypeRep @(Float -> Float -> Float -> Float -> IrisClass))),
|
||||||
|
maxDepth = 10,
|
||||||
|
weights =
|
||||||
|
ExpressionWeights
|
||||||
|
{ lambdaSpucker = 1,
|
||||||
|
lambdaSchlucker = 1,
|
||||||
|
symbol = 1,
|
||||||
|
variable = 2,
|
||||||
|
constant = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
irisLEE :: LamdaExecutionEnv
|
||||||
|
irisLEE =
|
||||||
|
LamdaExecutionEnv
|
||||||
|
{ -- For now these need to define all available functions and types. Generic functions can be used.
|
||||||
|
imports = ["IrisDataset"],
|
||||||
|
-- Path to a CSV file containing the training dataset
|
||||||
|
trainingDataset = "./iris.csv",
|
||||||
|
-- Path to a CSV file containing the dataset results
|
||||||
|
trainingDatasetRes = "./res.csv",
|
||||||
|
trainingData =
|
||||||
|
( map fst irisTrainingData,
|
||||||
|
map snd irisTrainingData
|
||||||
|
),
|
||||||
|
exTargetType = (Ref.SomeTypeRep (Ref.TypeRep @(Float -> Float -> Float -> Float -> IrisClass))),
|
||||||
|
-- todo: kindaHacky
|
||||||
|
results = Map.empty
|
||||||
|
}
|
||||||
|
|
||||||
|
data LamdaExecutionEnv = LamdaExecutionEnv
|
||||||
|
{ -- For now these need to define all available functions and types. Generic functions can be used.
|
||||||
|
imports :: [Text],
|
||||||
|
-- Path to a CSV file containing the training dataset
|
||||||
|
trainingDataset :: FilePath,
|
||||||
|
-- Path to a CSV file containing the dataset results
|
||||||
|
trainingDatasetRes :: FilePath,
|
||||||
|
trainingData :: ([(Float, Float, Float, Float)], [IrisClass]),
|
||||||
|
exTargetType :: TypeRep,
|
||||||
|
-- todo: kindaHacky
|
||||||
|
results :: Map TypeRequester FittnesRes
|
||||||
|
}
|
||||||
|
|
||||||
|
data FittnesRes = FittnesRes
|
||||||
|
{ total :: R,
|
||||||
|
fitnessTotal :: R,
|
||||||
|
fitnessGeoMean :: R,
|
||||||
|
fitnessMean :: R,
|
||||||
|
accuracy :: Int,
|
||||||
|
biasDist :: R,
|
||||||
|
biasSize :: R
|
||||||
|
}
|
||||||
|
deriving (Show)
|
||||||
|
|
||||||
|
instance Fitness FittnesRes where
|
||||||
|
getR = total
|
||||||
|
|
||||||
|
instance Evaluator TypeRequester LamdaExecutionEnv FittnesRes where
|
||||||
|
fitness' env tr = (results env) Map.! tr
|
||||||
|
|
||||||
|
calc env pop = do
|
||||||
|
let toAdd = NE.filter (\k -> not (Map.member k (results env))) pop
|
||||||
|
toInsert <- Hint.runInterpreter (evalResults env toAdd)
|
||||||
|
let insertPair (key, val) m = Map.insert key val m
|
||||||
|
let res = foldr insertPair (results env) (fromRight undefined toInsert)
|
||||||
|
return env {results = res}
|
||||||
|
|
||||||
|
|
||||||
|
evalResults :: LamdaExecutionEnv -> [TypeRequester] -> Hint.InterpreterT IO [(TypeRequester, FittnesRes)]
|
||||||
|
evalResults ex trs = mapM (evalResult ex) trs
|
||||||
|
|
||||||
|
evalResult :: LamdaExecutionEnv -> TypeRequester -> Hint.InterpreterT IO (TypeRequester, FittnesRes)
|
||||||
|
evalResult ex tr = do
|
||||||
|
Hint.setImports $ (map T.unpack (imports ex)) ++ ["Protolude"]
|
||||||
|
Hint.unsafeSetGhcOption "-O2"
|
||||||
|
result <- Hint.interpret (T.unpack (toLambdaExpressionS tr)) (Hint.as :: Float -> Float -> Float -> Float -> IrisClass)
|
||||||
|
let res = map (\(a, b, c, d) -> result a b c d) (fst (trainingData ex))
|
||||||
|
let resAndTarget = (zip (snd (trainingData ex)) res)
|
||||||
|
let acc = (foldr (\ts s -> if ((fst ts) == (snd ts)) then s + 1 else s) 0 resAndTarget) :: Int
|
||||||
|
let biasWellDistributed = (foldr (*) 1 (map (\ty -> (foldr (\ts s -> if ((snd ts) == ty) then s + 1 else s) 1 resAndTarget)) ([minBound .. maxBound] :: [IrisClass]) :: [R])) ** (1 / 3) -- 1 (schlecht) bis 51 (gut)
|
||||||
|
let biasSmall = exp (-(fromIntegral (countTrsR tr))) -- 0 (schlecht) bis 1 (gut)
|
||||||
|
let fitness' = meanOfAccuricyPerClass resAndTarget
|
||||||
|
let score = fitness' + (biasSmall - 1)
|
||||||
|
return
|
||||||
|
( tr,
|
||||||
|
FittnesRes
|
||||||
|
{ total = score,
|
||||||
|
fitnessTotal = fitness',
|
||||||
|
fitnessMean = meanOfAccuricyPerClass resAndTarget,
|
||||||
|
fitnessGeoMean = geomeanOfDistributionAccuracy resAndTarget,
|
||||||
|
accuracy = acc,
|
||||||
|
biasDist = biasWellDistributed,
|
||||||
|
biasSize = biasSmall
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if' :: Bool -> a -> a -> a
|
||||||
|
if' True e _ = e
|
||||||
|
if' False _ e = e
|
||||||
|
|
|
@ -62,21 +62,22 @@ exampleLE =
|
||||||
weights =
|
weights =
|
||||||
ExpressionWeights
|
ExpressionWeights
|
||||||
{ lambdaSpucker = 1,
|
{ lambdaSpucker = 1,
|
||||||
lambdaSchlucker = 1,
|
lambdaSchlucker = 2,
|
||||||
symbol = 1,
|
symbol = 2,
|
||||||
variable = 1,
|
variable = 10,
|
||||||
constant = 1
|
constant = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type BoundVars = [TypeRep]
|
type BoundVars = [TypeRep]
|
||||||
|
|
||||||
|
|
||||||
-- we need a dynamic typ with a concept of equality here, should we want to interpret the result, instead of compiling it...
|
-- we need a dynamic typ with a concept of equality here, should we want to interpret the result, instead of compiling it...
|
||||||
type ConVal = Text
|
type ConVal = Text
|
||||||
|
|
||||||
-- LambdaSpucker - adds TypeRequester#1 as bound var and returns the result of TypeRequester#2
|
-- LambdaSpucker - adds TypeRequester#1 as bound var and returns the result of TypeRequester#2
|
||||||
|
|
||||||
data LambdaExpression = LambdaSpucker TypeRequester TypeRequester BoundVars | LambdaSchlucker TypeRequester BoundVars | Symbol ConVal [TypeRequester] BoundVars | Var TypeRep Int [TypeRequester] BoundVars | Constan ConVal deriving (Eq, Ord)
|
data LambdaExpression = LambdaSpucker TypeRequester TypeRequester BoundVars | LambdaSchlucker TypeRequester BoundVars | Symbol ConVal [TypeRequester] BoundVars | Var TypeRep Int [TypeRequester] BoundVars | Constan ConVal deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
asList :: LambdaExpression -> [TypeRequester]
|
asList :: LambdaExpression -> [TypeRequester]
|
||||||
asList (LambdaSpucker tr1 tr2 _) = [tr1, tr2]
|
asList (LambdaSpucker tr1 tr2 _) = [tr1, tr2]
|
||||||
|
@ -85,7 +86,7 @@ asList (Symbol _ trs _) = trs
|
||||||
asList (Var _ _ trs _) = trs
|
asList (Var _ _ trs _) = trs
|
||||||
asList (Constan _) = []
|
asList (Constan _) = []
|
||||||
|
|
||||||
data TypeRequester = TR TypeRep (Maybe LambdaExpression) BoundVars deriving (Eq, Ord)
|
data TypeRequester = TR TypeRep (Maybe LambdaExpression) BoundVars deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
toLambdaExpressionS :: TypeRequester -> Text
|
toLambdaExpressionS :: TypeRequester -> Text
|
||||||
toLambdaExpressionS (TR typeRep (Just lambdaExpression) boundVars) = "((" <> eToLambdaExpressionS lambdaExpression <> ") :: (" <> show typeRep <> "))"
|
toLambdaExpressionS (TR typeRep (Just lambdaExpression) boundVars) = "((" <> eToLambdaExpressionS lambdaExpression <> ") :: (" <> show typeRep <> "))"
|
||||||
|
@ -163,7 +164,7 @@ doTypesMatch toGen available = elem toGen (available : (repeatedly (lastMay . ty
|
||||||
|
|
||||||
genLambdaSpucker :: LambdaEnviroment -> Int -> TypeRep -> BoundVars -> RVar LambdaExpression
|
genLambdaSpucker :: LambdaEnviroment -> Int -> TypeRep -> BoundVars -> RVar LambdaExpression
|
||||||
genLambdaSpucker env@(LambdaEnviroment functions constants _ _ weights) depthLeft target boundVar = do
|
genLambdaSpucker env@(LambdaEnviroment functions constants _ _ weights) depthLeft target boundVar = do
|
||||||
lamdaTypeLength <- uniform 1 3
|
lamdaTypeLength <- uniform 1 4
|
||||||
lambaTypes <- replicateM lamdaTypeLength (randomElement (Map.keys constants))
|
lambaTypes <- replicateM lamdaTypeLength (randomElement (Map.keys constants))
|
||||||
let lambaType = foldr1 mkFunTy lambaTypes
|
let lambaType = foldr1 mkFunTy lambaTypes
|
||||||
lamdaVarTypeRequester <- genTypeRequester env depthLeft lambaType boundVar
|
lamdaVarTypeRequester <- genTypeRequester env depthLeft lambaType boundVar
|
||||||
|
@ -260,7 +261,7 @@ instance Environment TypeRequester LambdaEnviroment where
|
||||||
-- findIndicesWhere' (tr:trs) f indx = (findIndicesWhere tr f indx) ++ (findIndicesWhere' trs f (indx + countTrsR tr))
|
-- findIndicesWhere' (tr:trs) f indx = (findIndicesWhere tr f indx) ++ (findIndicesWhere' trs f (indx + countTrsR tr))
|
||||||
|
|
||||||
replaceAtR :: Int -> TypeRequester -> TypeRequester -> TypeRequester
|
replaceAtR :: Int -> TypeRequester -> TypeRequester -> TypeRequester
|
||||||
replaceAtR 0 _ with = with
|
replaceAtR 1 _ with = with
|
||||||
replaceAtR i (TR tm (Just le) bV) with = TR tm (Just (replaceAt (i - 1) le with)) bV
|
replaceAtR i (TR tm (Just le) bV) with = TR tm (Just (replaceAt (i - 1) le with)) bV
|
||||||
replaceAtR _ (TR _ Nothing _) _ = undefined
|
replaceAtR _ (TR _ Nothing _) _ = undefined
|
||||||
|
|
||||||
|
@ -276,7 +277,7 @@ replaceInSubtreeWithIndex indexLeft (tr : trs) with = if countTrsR tr >= indexLe
|
||||||
replaceInSubtreeWithIndex _ [] _ = undefined
|
replaceInSubtreeWithIndex _ [] _ = undefined
|
||||||
|
|
||||||
depthLeftAndTypeAtR :: TypeRequester -> Int -> Int -> (Int, TypeRequester)
|
depthLeftAndTypeAtR :: TypeRequester -> Int -> Int -> (Int, TypeRequester)
|
||||||
depthLeftAndTypeAtR t 0 depthLeft = ((depthLeft - 1), t)
|
depthLeftAndTypeAtR t 1 depthLeft = ((depthLeft - 1), t)
|
||||||
depthLeftAndTypeAtR (TR _ (Just le) _) indexLeft depthLeft = depthLeftAndTypeAt le (indexLeft - 1) (depthLeft - 1)
|
depthLeftAndTypeAtR (TR _ (Just le) _) indexLeft depthLeft = depthLeftAndTypeAt le (indexLeft - 1) (depthLeft - 1)
|
||||||
depthLeftAndTypeAtR (TR _ Nothing _) indexLeft depthLeft = undefined
|
depthLeftAndTypeAtR (TR _ Nothing _) indexLeft depthLeft = undefined
|
||||||
|
|
||||||
|
@ -458,10 +459,41 @@ toLambdaExpressionShort (TR _ (Nothing) _) = "Invalid Lambda Epr"
|
||||||
|
|
||||||
eToLambdaExpressionShort :: LambdaExpression -> Text
|
eToLambdaExpressionShort :: LambdaExpression -> Text
|
||||||
eToLambdaExpressionShort (LambdaSpucker typeRequester1 typeRequester2 boundVars) = "(\\l" <> showSanifid (last boundVars) <> show (count boundVars (last boundVars) - 1) <> " -> " <> toLambdaExpressionShort typeRequester2 <> ") " <> toLambdaExpressionShort typeRequester1
|
eToLambdaExpressionShort (LambdaSpucker typeRequester1 typeRequester2 boundVars) = "(\\l" <> showSanifid (last boundVars) <> show (count boundVars (last boundVars) - 1) <> " -> " <> toLambdaExpressionShort typeRequester2 <> ") " <> toLambdaExpressionShort typeRequester1
|
||||||
eToLambdaExpressionShort (LambdaSchlucker typeRequester boundVars) = "()\\l" <> showSanifid (last boundVars) <> show (count boundVars (last boundVars) - 1) <> " -> " <> toLambdaExpressionShort typeRequester <> ")"
|
eToLambdaExpressionShort (LambdaSchlucker typeRequester boundVars) = "(\\l" <> showSanifid (last boundVars) <> show (count boundVars (last boundVars) - 1) <> " -> " <> toLambdaExpressionShort typeRequester <> ")"
|
||||||
eToLambdaExpressionShort (Symbol (valS) typeRequesters _) = valS <> " " <> (unwords (map toLambdaExpressionShort typeRequesters))
|
eToLambdaExpressionShort (Symbol (valS) typeRequesters _) = valS <> " " <> (unwords (map toLambdaExpressionShort typeRequesters))
|
||||||
eToLambdaExpressionShort (Var typeRep int typeRequesters _) = "l" <> showSanifid typeRep <> show int <> " " <> (unwords (map toLambdaExpressionShort typeRequesters))
|
eToLambdaExpressionShort (Var typeRep int typeRequesters _) = "l" <> showSanifid typeRep <> show int <> " " <> (unwords (map toLambdaExpressionShort typeRequesters))
|
||||||
eToLambdaExpressionShort (Constan (valS)) = valS
|
eToLambdaExpressionShort (Constan (valS)) = valS
|
||||||
|
|
||||||
res :: Int -> ResClass
|
res :: Int -> ResClass
|
||||||
res = ((\lInt0 -> ((iteClass ((eqInt ((lInt0) :: (Int)) ((1) :: (Int))) :: (Bool)) ((Class1) :: (ResClass)) ((iteClass ((eqInt ((lInt0) :: (Int)) ((2) :: (Int))) :: (Bool)) ((Class2) :: (ResClass)) ((iteClass ((eqInt ((lInt0) :: (Int)) ((3) :: (Int))) :: (Bool)) ((Class3) :: (ResClass)) ((Class3) :: (ResClass))) :: (ResClass))) :: (ResClass))) :: (ResClass))) :: (Int -> ResClass))
|
res = ((\lInt0 -> ((iteClass ((eqInt ((lInt0) :: (Int)) ((1) :: (Int))) :: (Bool)) ((Class1) :: (ResClass)) ((iteClass ((eqInt ((lInt0) :: (Int)) ((2) :: (Int))) :: (Bool)) ((Class2) :: (ResClass)) ((iteClass ((eqInt ((lInt0) :: (Int)) ((3) :: (Int))) :: (Bool)) ((Class3) :: (ResClass)) ((Class3) :: (ResClass))) :: (ResClass))) :: (ResClass))) :: (ResClass))) :: (Int -> ResClass))
|
||||||
|
|
||||||
|
|
||||||
|
meanOfAccuricyPerClass :: (Enum r, Bounded r, Eq r) => [(r, r)] -> R
|
||||||
|
meanOfAccuricyPerClass results = mean $ map (accuracyInClass results) [minBound .. maxBound]
|
||||||
|
|
||||||
|
geomeanOfAccuricyPerClass :: (Enum r, Bounded r, Eq r) => [(r, r)] -> R
|
||||||
|
geomeanOfAccuricyPerClass results = geomean $ map (accuracyInClass results) [minBound .. maxBound]
|
||||||
|
|
||||||
|
geomeanOfDistributionAccuracy :: (Enum r, Bounded r, Eq r) => [(r, r)] -> R
|
||||||
|
geomeanOfDistributionAccuracy results = geomean $ map (distributionAccuracyForClass results) [minBound .. maxBound]
|
||||||
|
|
||||||
|
distributionAccuracyForClass :: (Eq r) => [(r, r)] -> r -> R
|
||||||
|
distributionAccuracyForClass results clas = (1 - (min 1 (fromIntegral (abs ((length (inResClass results clas)) - (length (inClass results clas)))) / fromIntegral (length (inClass results clas))))) * 100
|
||||||
|
|
||||||
|
mean :: (Show f, Floating f) => [f] -> f
|
||||||
|
mean values = (sum values) * (1 / (fromIntegral (length values)))
|
||||||
|
|
||||||
|
geomean :: (Show f, Floating f) => [f] -> f
|
||||||
|
geomean values = (product values) ** (1 / (fromIntegral (length values)))
|
||||||
|
|
||||||
|
accuracyInClass :: (Eq r) => [(r, r)] -> r -> R
|
||||||
|
accuracyInClass results clas = ((accuracy'(inResClass results clas)) * 100) / fromIntegral (length (inClass results clas))
|
||||||
|
|
||||||
|
inClass :: (Eq r) => [(r, r)] -> r -> [(r, r)]
|
||||||
|
inClass results clas = (filter ((clas ==) . fst) results)
|
||||||
|
|
||||||
|
inResClass :: (Eq r) => [(r, r)] -> r -> [(r, r)]
|
||||||
|
inResClass results clas = (filter ((clas ==) . snd) results)
|
||||||
|
|
||||||
|
accuracy' :: (Eq r) => [(r, r)] -> R
|
||||||
|
accuracy' results = fromIntegral $ length (filter (\(target, res) -> (res == target)) results)
|
||||||
|
|
21
src/Main.hs
21
src/Main.hs
|
@ -8,7 +8,8 @@ import Pretty
|
||||||
import Protolude hiding (for)
|
import Protolude hiding (for)
|
||||||
import System.IO
|
import System.IO
|
||||||
-- import Szenario212Pun
|
-- import Szenario212Pun
|
||||||
import Szenario191
|
-- import Szenario191
|
||||||
|
import IrisDataset
|
||||||
|
|
||||||
data Options = Options
|
data Options = Options
|
||||||
{ iterations :: !N,
|
{ iterations :: !N,
|
||||||
|
@ -31,7 +32,7 @@ options =
|
||||||
( long "population-size"
|
( long "population-size"
|
||||||
<> short 'p'
|
<> short 'p'
|
||||||
<> metavar "N"
|
<> metavar "N"
|
||||||
<> value 1000
|
<> value 50
|
||||||
<> help "Population size"
|
<> help "Population size"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,16 +49,18 @@ main :: IO ()
|
||||||
main =
|
main =
|
||||||
execParser optionsWithHelp >>= \opts -> do
|
execParser optionsWithHelp >>= \opts -> do
|
||||||
hSetBuffering stdout NoBuffering
|
hSetBuffering stdout NoBuffering
|
||||||
let env = AssignmentEnviroment (students prios, topics prios)
|
let env = irisLE
|
||||||
let selType = Tournament 20
|
let selType = Tournament 3
|
||||||
let run' = run prios env selType 20 (5 / 100) (populationSize opts) (steps (iterations opts)) :: Producer (Int, R) IO (Population Assignment)
|
let run' = run irisLEE env selType 40 (5 / 100) (populationSize opts) (steps (iterations opts))
|
||||||
pop' <-
|
pop' <-
|
||||||
runEffect (for run' logCsv)
|
runEffect (for run' logCsv)
|
||||||
let (res, _) = bests prios 5 pop'
|
|
||||||
mapM_ format res
|
irisLE <- calc irisLEE pop'
|
||||||
|
let (res, _) = bests irisLE 5 pop'
|
||||||
|
mapM_ (format irisLE) res
|
||||||
where
|
where
|
||||||
format s = do
|
format irisL s = do
|
||||||
let f = fitness prios s
|
let f = fitness' irisL s
|
||||||
putErrText $ show f <> "\n" <> pretty s
|
putErrText $ show f <> "\n" <> pretty s
|
||||||
logCsv = putText . csv
|
logCsv = putText . csv
|
||||||
csv (t, f) = show t <> " " <> show f
|
csv (t, f) = show t <> " " <> show f
|
||||||
|
|
|
@ -159,8 +159,8 @@ prioOf' p (Just _) Nothing = lowestPriority p + 2
|
||||||
prioOf' p Nothing (Just _) = lowestPriority p + 2
|
prioOf' p Nothing (Just _) = lowestPriority p + 2
|
||||||
prioOf' p (Just s) (Just t) = prioOf p s t
|
prioOf' p (Just s) (Just t) = prioOf p s t
|
||||||
|
|
||||||
instance Evaluator Assignment Priorities where
|
instance Evaluator Assignment Priorities R where
|
||||||
fitness prio assment =
|
fitness' prio assment =
|
||||||
negate . sum $ fromIntegral . uncurry (prioOf' prio) <$> assment
|
negate . sum $ fromIntegral . uncurry (prioOf' prio) <$> assment
|
||||||
|
|
||||||
-- |
|
-- |
|
||||||
|
|
Loading…
Reference in New Issue
Block a user