module Moo.GeneticAlgorithm.StopCondition where


import Moo.GeneticAlgorithm.Types


evalCond :: (Cond a) -> Population a -> Bool
evalCond :: Cond a -> Population a -> Bool
evalCond (Generations Int
n) Population a
_  = Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
evalCond (IfObjective [Objective] -> Bool
cond) Population a
p = [Objective] -> Bool
cond ([Objective] -> Bool)
-> (Population a -> [Objective]) -> Population a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Phenotype a -> Objective) -> Population a -> [Objective]
forall a b. (a -> b) -> [a] -> [b]
map Phenotype a -> Objective
forall a. Phenotype a -> Objective
takeObjectiveValue (Population a -> Bool) -> Population a -> Bool
forall a b. (a -> b) -> a -> b
$ Population a
p
evalCond (GensNoChange Int
n [Objective] -> b
_ Maybe (b, Int)
Nothing) Population a
_ = Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1
evalCond (GensNoChange Int
n [Objective] -> b
f (Just (b
prev, Int
count))) Population a
p =
    let new :: b
new = [Objective] -> b
f ([Objective] -> b)
-> (Population a -> [Objective]) -> Population a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Phenotype a -> Objective) -> Population a -> [Objective]
forall a b. (a -> b) -> [a] -> [b]
map Phenotype a -> Objective
forall a. Phenotype a -> Objective
takeObjectiveValue (Population a -> b) -> Population a -> b
forall a b. (a -> b) -> a -> b
$ Population a
p
    in  (b
new b -> b -> Bool
forall a. Eq a => a -> a -> Bool
== b
prev) Bool -> Bool -> Bool
&& (Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n)
evalCond (Or Cond a
c1 Cond a
c2) Population a
x = Cond a -> Population a -> Bool
forall a. Cond a -> Population a -> Bool
evalCond Cond a
c1 Population a
x Bool -> Bool -> Bool
|| Cond a -> Population a -> Bool
forall a. Cond a -> Population a -> Bool
evalCond Cond a
c2 Population a
x
evalCond (And Cond a
c1 Cond a
c2) Population a
x = Cond a -> Population a -> Bool
forall a. Cond a -> Population a -> Bool
evalCond Cond a
c1 Population a
x Bool -> Bool -> Bool
&& Cond a -> Population a -> Bool
forall a. Cond a -> Population a -> Bool
evalCond Cond a
c2 Population a
x


updateCond :: Population a -> Cond a -> Cond a
updateCond :: Population a -> Cond a -> Cond a
updateCond Population a
_ (Generations Int
n) = Int -> Cond a
forall a. Int -> Cond a
Generations (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
updateCond Population a
p (GensNoChange Int
n [Objective] -> b
f Maybe (b, Int)
Nothing) =
     -- called 1st time _after_ the 1st iteration

    let counter :: Maybe (b, Int)
counter = ((b, Int) -> Maybe (b, Int)
forall a. a -> Maybe a
Just ([Objective] -> b
f ((Phenotype a -> Objective) -> Population a -> [Objective]
forall a b. (a -> b) -> [a] -> [b]
map Phenotype a -> Objective
forall a. Phenotype a -> Objective
takeObjectiveValue Population a
p), Int
1))
    in Int -> ([Objective] -> b) -> Maybe (b, Int) -> Cond a
forall a b.
Eq b =>
Int -> ([Objective] -> b) -> Maybe (b, Int) -> Cond a
GensNoChange Int
n [Objective] -> b
f Maybe (b, Int)
counter
updateCond Population a
p (GensNoChange Int
n [Objective] -> b
f (Just (b
v, Int
c))) =
    let v' :: b
v' = [Objective] -> b
f ((Phenotype a -> Objective) -> Population a -> [Objective]
forall a b. (a -> b) -> [a] -> [b]
map Phenotype a -> Objective
forall a. Phenotype a -> Objective
takeObjectiveValue Population a
p) in if b
v' b -> b -> Bool
forall a. Eq a => a -> a -> Bool
== b
v
       then Int -> ([Objective] -> b) -> Maybe (b, Int) -> Cond a
forall a b.
Eq b =>
Int -> ([Objective] -> b) -> Maybe (b, Int) -> Cond a
GensNoChange Int
n [Objective] -> b
f ((b, Int) -> Maybe (b, Int)
forall a. a -> Maybe a
Just (b
v, Int
cInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1))
       else Int -> ([Objective] -> b) -> Maybe (b, Int) -> Cond a
forall a b.
Eq b =>
Int -> ([Objective] -> b) -> Maybe (b, Int) -> Cond a
GensNoChange Int
n [Objective] -> b
f ((b, Int) -> Maybe (b, Int)
forall a. a -> Maybe a
Just (b
v', Int
1))
updateCond Population a
p (And Cond a
c1 Cond a
c2) = Cond a -> Cond a -> Cond a
forall a. Cond a -> Cond a -> Cond a
And (Population a -> Cond a -> Cond a
forall a. Population a -> Cond a -> Cond a
updateCond Population a
p Cond a
c1) (Population a -> Cond a -> Cond a
forall a. Population a -> Cond a -> Cond a
updateCond Population a
p Cond a
c2)
updateCond Population a
p (Or Cond a
c1 Cond a
c2) = Cond a -> Cond a -> Cond a
forall a. Cond a -> Cond a -> Cond a
Or (Population a -> Cond a -> Cond a
forall a. Population a -> Cond a -> Cond a
updateCond Population a
p Cond a
c1) (Population a -> Cond a -> Cond a
forall a. Population a -> Cond a -> Cond a
updateCond Population a
p Cond a
c2)
updateCond Population a
_ Cond a
c = Cond a
c