Rename Topic to T, fix T Eq instance, fix fitness calculation
This commit is contained in:
parent
5f4e212414
commit
531cb74aac
15
default.nix
15
default.nix
|
@ -1,14 +1,21 @@
|
||||||
{ mkDerivation, base, monad-loops, MonadRandom, protolude
|
{ mkDerivation, base, bytestring, cassava, monad-loops, MonadRandom
|
||||||
, QuickCheck, quickcheck-instances, random, random-fu
|
, protolude, QuickCheck, quickcheck-instances, random, random-fu
|
||||||
, random-shuffle, stdenv, text
|
, random-shuffle, stdenv, text
|
||||||
}:
|
}:
|
||||||
mkDerivation {
|
mkDerivation {
|
||||||
pname = "GA-PFP";
|
pname = "ga";
|
||||||
version = "0.1.0.0";
|
version = "0.1.0.0";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
|
isLibrary = true;
|
||||||
|
isExecutable = true;
|
||||||
libraryHaskellDepends = [
|
libraryHaskellDepends = [
|
||||||
base monad-loops MonadRandom protolude QuickCheck
|
base cassava monad-loops MonadRandom protolude QuickCheck
|
||||||
quickcheck-instances random random-fu random-shuffle text
|
quickcheck-instances random random-fu random-shuffle text
|
||||||
];
|
];
|
||||||
|
executableHaskellDepends = [
|
||||||
|
base bytestring cassava monad-loops MonadRandom protolude
|
||||||
|
QuickCheck quickcheck-instances random random-fu random-shuffle
|
||||||
|
text
|
||||||
|
];
|
||||||
license = stdenv.lib.licenses.gpl3;
|
license = stdenv.lib.licenses.gpl3;
|
||||||
}
|
}
|
||||||
|
|
3
ga.cabal
3
ga.cabal
|
@ -30,6 +30,7 @@ library
|
||||||
, Seminar
|
, Seminar
|
||||||
, Pretty
|
, Pretty
|
||||||
, SS19
|
, SS19
|
||||||
|
, WS19
|
||||||
|
|
||||||
|
|
||||||
executable ga
|
executable ga
|
||||||
|
@ -43,7 +44,6 @@ executable ga
|
||||||
, QuickCheck
|
, QuickCheck
|
||||||
, quickcheck-instances
|
, quickcheck-instances
|
||||||
, text
|
, text
|
||||||
, protolude
|
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
|
@ -51,3 +51,4 @@ executable ga
|
||||||
, Seminar
|
, Seminar
|
||||||
, Pretty
|
, Pretty
|
||||||
, SS19
|
, SS19
|
||||||
|
, WS19
|
||||||
|
|
13
src/GA.hs
13
src/GA.hs
|
@ -4,6 +4,7 @@
|
||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
{-# LANGUAGE NoImplicitPrelude #-}
|
{-# LANGUAGE NoImplicitPrelude #-}
|
||||||
{-# LANGUAGE TupleSections #-}
|
{-# LANGUAGE TupleSections #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module GA where
|
module GA where
|
||||||
|
|
||||||
|
@ -161,7 +162,13 @@ Runs the GA and prints the @nResult@ best individuals.
|
||||||
ga' nParents nX pop term nResult = do
|
ga' nParents nX pop term nResult = do
|
||||||
pop <- ga nParents nX pop term
|
pop <- ga nParents nX pop term
|
||||||
res <- bests nResult pop
|
res <- bests nResult pop
|
||||||
sequence $ putText . pretty <$> res
|
sequence $ format <$> res
|
||||||
|
where
|
||||||
|
-- TODO this has to be done nicer
|
||||||
|
format :: (Individual i, MonadIO m, Pretty i) => i -> m ()
|
||||||
|
format s = do
|
||||||
|
f <- liftIO $ fitness s
|
||||||
|
putText $ show f <> "\n" <> pretty s
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Runs the GA, using in each iteration
|
Runs the GA, using in each iteration
|
||||||
|
@ -194,9 +201,11 @@ ga nParents nX pop term = ga' nParents nX pop term 0
|
||||||
-- traceShow (length is') $ return ()
|
-- traceShow (length is') $ return ()
|
||||||
iWorsts <- worst nParents pop
|
iWorsts <- worst nParents pop
|
||||||
-- traceShow (length iWorsts) $ return ()
|
-- traceShow (length iWorsts) $ return ()
|
||||||
|
let popClean = foldr L.delete (NE.toList . unPop $ pop) iWorsts
|
||||||
|
-- traceShow (length popClean) $ return ()
|
||||||
-- for the fromList to not fail, n < length pop
|
-- for the fromList to not fail, n < length pop
|
||||||
-- replace the worst ones
|
-- replace the worst ones
|
||||||
let pop' = Pop $ i :| is' <> foldr L.delete (NE.toList . unPop $ pop) iWorsts
|
let pop' = Pop $ i :| is' <> popClean
|
||||||
-- replace fitness proportionally
|
-- replace fitness proportionally
|
||||||
-- let pop' = Pop <$> proportionate (length pop) (pop <> Pop is')
|
-- let pop' = Pop <$> proportionate (length pop) (pop <> Pop is')
|
||||||
if term pop' t
|
if term pop' t
|
||||||
|
|
13
src/Main.hs
13
src/Main.hs
|
@ -1,17 +1,12 @@
|
||||||
{-# LANGUAGE NoImplicitPrelude #-}
|
{-# LANGUAGE NoImplicitPrelude #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
import Protolude
|
import Protolude
|
||||||
|
import WS19
|
||||||
|
|
||||||
import GA
|
|
||||||
import SS19
|
|
||||||
|
|
||||||
|
|
||||||
main = do
|
main = do
|
||||||
pop <- mkPop
|
pop <- mkPop
|
||||||
ga' 2 1 pop (\_ t -> t > 100) 10
|
ga' 2 1 pop (steps 10000) 10
|
||||||
putStrLn "Done."
|
putText "Done."
|
||||||
|
|
||||||
|
|
||||||
mkPop = population 100 (I prios [])
|
mkPop = population 100 (I prios [])
|
||||||
|
|
|
@ -45,39 +45,42 @@ instance Pretty Student where
|
||||||
The seminar GA is about giving topics to students. If there are not enough
|
The seminar GA is about giving topics to students. If there are not enough
|
||||||
topics, some students might get assigned 'NoTopic'.
|
topics, some students might get assigned 'NoTopic'.
|
||||||
-}
|
-}
|
||||||
data Topic
|
data T
|
||||||
= Topic Text
|
= T Text
|
||||||
| NoTopic
|
| NoT
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
'Topic' is not 'Maybe' because this 'Eq' instance is different ('Nothing' @==@
|
'Topic' is not 'Maybe' because this 'Eq' instance is different ('Nothing' @==@
|
||||||
'Nothing' but 'NoTopic' @/=@ 'NoTopic').
|
'Nothing' but 'NoTopic' @/=@ 'NoTopic').
|
||||||
-}
|
-}
|
||||||
instance Eq Topic where
|
instance Eq T where
|
||||||
Topic x == Topic y = x == y
|
T x == T y = x == y
|
||||||
NoTopic == _ = False
|
-- NoT == _ = False
|
||||||
_ == NoTopic = False
|
-- _ == NoT = False
|
||||||
|
NoT == NoT = True
|
||||||
|
NoT == _ = False
|
||||||
|
_ == NoT = False
|
||||||
|
|
||||||
instance Arbitrary Topic where
|
instance Arbitrary T where
|
||||||
arbitrary = oneof [Topic <$> arbitrary, return NoTopic]
|
arbitrary = oneof [T <$> arbitrary, return NoT]
|
||||||
|
|
||||||
instance Pretty Topic where
|
instance Pretty T where
|
||||||
pretty (Topic s) = s
|
pretty (T s) = s
|
||||||
pretty NoTopic = "Kein Thema"
|
pretty NoT = "Kein Thema"
|
||||||
|
|
||||||
topicToMaybe (Topic x) = Just x
|
topicToMaybe (T x) = Just x
|
||||||
topicToMaybe NoTopic = Nothing
|
topicToMaybe NoT = Nothing
|
||||||
|
|
||||||
type Priorities = [(Student, [(Topic, Int)])]
|
type Priorities = [(Student, [(T, Int)])]
|
||||||
|
|
||||||
students :: Priorities -> [Student]
|
students :: Priorities -> [Student]
|
||||||
students = fmap fst
|
students = fmap fst
|
||||||
|
|
||||||
topics :: Priorities -> [Topic]
|
topics :: Priorities -> [T]
|
||||||
topics p = topics' ++ padding
|
topics p = topics' ++ padding
|
||||||
where
|
where
|
||||||
padding = replicate (length (students p) - length topics') NoTopic
|
padding = replicate (length (students p) - length topics') NoT
|
||||||
topics' = nub . join $ fmap fst . snd <$> p
|
topics' = nub . join $ fmap fst . snd <$> p
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
|
@ -85,11 +88,11 @@ The priority of topics that have not been assigned a priority is the sum of all
|
||||||
priorities given by all the students. The priority of 'NoTopic' is one more than
|
priorities given by all the students. The priority of 'NoTopic' is one more than
|
||||||
that value.
|
that value.
|
||||||
-}
|
-}
|
||||||
prioOf :: Priorities -> Student -> Topic -> Int
|
prioOf :: Priorities -> Student -> T -> Int
|
||||||
prioOf p _ NoTopic = (1 +) . sum $ (sum . fmap snd) . snd <$> p
|
prioOf p _ NoT = (1 +) . sum $ (sum . fmap snd) . snd <$> p
|
||||||
prioOf p s t = maybe (prioOf p s NoTopic) identity $ lookup s p >>= lookup t
|
prioOf p s t = maybe (prioOf p s NoT) identity $ lookup s p >>= lookup t
|
||||||
|
|
||||||
type Assignment = [(Student, Topic)]
|
type Assignment = [(Student, T)]
|
||||||
|
|
||||||
data I = I Priorities Assignment
|
data I = I Priorities Assignment
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
@ -98,10 +101,10 @@ instance Pretty I where
|
||||||
pretty i@(I p a) =
|
pretty i@(I p a) =
|
||||||
T.unlines (gene <$> a)
|
T.unlines (gene <$> a)
|
||||||
where
|
where
|
||||||
gene :: (Student, Topic) -> Text
|
gene :: (Student, T) -> Text
|
||||||
gene (s, t) =
|
gene (s, t) =
|
||||||
pretty s <> ": " <> pretty t <> prio s t
|
pretty s <> ": " <> pretty t <> prio s t
|
||||||
prio :: Student -> Topic -> Text
|
prio :: Student -> T -> Text
|
||||||
prio s t = " (" <> show (prioOf p s t) <> ")"
|
prio s t = " (" <> show (prioOf p s t) <> ")"
|
||||||
|
|
||||||
instance Individual I where
|
instance Individual I where
|
||||||
|
@ -110,7 +113,8 @@ instance Individual I where
|
||||||
sample $ I p . zip (nub $ students p) <$> shuffle (nub $ topics p)
|
sample $ I p . zip (nub $ students p) <$> shuffle (nub $ topics p)
|
||||||
|
|
||||||
fitness (I p a) =
|
fitness (I p a) =
|
||||||
return . (1 /) . sum $ fromIntegral . uncurry (prioOf p) <$> a
|
return . (fromIntegral (prioOf p undefined NoT) /) . sum
|
||||||
|
$ fromIntegral . uncurry (prioOf p) <$> a
|
||||||
|
|
||||||
mutate (I p a) = do
|
mutate (I p a) = do
|
||||||
x <- sample $ Uniform 0 (length a - 1)
|
x <- sample $ Uniform 0 (length a - 1)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user