{-# language FlexibleInstances #-}
module MachineLearning.Model.Fitness 
  ( evalTrain
  , evalTest
  , selectValidTerms
  ) where
import Data.Bifunctor
import Data.Maybe            (fromJust)
import Data.Vector.Storable  (Vector)
import Data.Vector           ((!))
import Numeric.LinearAlgebra ((<\>))
import Numeric.ModalInterval      (Kaucher, inf, sup, width, singleton)
import qualified Numeric.ModalInterval as Interval 
import Control.Monad.Reader
import qualified Data.Vector.Storable  as VS
import qualified Data.Vector           as V
import qualified Numeric.LinearAlgebra as LA
import Data.Maybe (fromMaybe)
import MachineLearning.Model.Measure       (Measure)
import MachineLearning.Model.Regression    (nonlinearFit, evalPenalty, fitTask, predictTask, applyMeasures)
import MachineLearning.TIR       (TIR(..),  Individual(..), Dataset, Constraint, assembleTree, replaceConsts)
import MachineLearning.Utils.Config       (Task(..), Penalty)
import Data.SRTree                (SRTree(..), Function, OptIntPow(..), evalTree, evalTreeMap, evalFun, inverseFunc, countNodes)
import Data.SRTree.Print
selectValidTerms :: TIR -> V.Vector (Kaucher Double) -> TIR
selectValidTerms :: TIR -> Vector (Kaucher Double) -> TIR
selectValidTerms tir :: TIR
tir@(TIR Function
_ Sigma
p Sigma
q) Vector (Kaucher Double)
domains = TIR
tir{ _p :: Sigma
_p=Sigma
p', _q :: Sigma
_q=Sigma
q' }
  where
    p' :: Sigma
p' = Sigma -> Sigma
forall {a}.
[(a, Function, [(Int, Int)])] -> [(a, Function, [(Int, Int)])]
selectValid Sigma
p
    q' :: Sigma
q' = Sigma -> Sigma
forall {a}.
[(a, Function, [(Int, Int)])] -> [(a, Function, [(Int, Int)])]
selectValid Sigma
q
    
    selectValid :: [(a, Function, [(Int, Int)])] -> [(a, Function, [(Int, Int)])]
selectValid = ((a, Function, [(Int, Int)]) -> Bool)
-> [(a, Function, [(Int, Int)])] -> [(a, Function, [(Int, Int)])]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(a
_, Function
g, [(Int, Int)]
ps) -> Kaucher Double -> Bool
isValidInterval (Kaucher Double -> Bool) -> Kaucher Double -> Bool
forall a b. (a -> b) -> a -> b
$ Function -> Kaucher Double -> Kaucher Double
forall val. Floating val => Function -> val -> val
evalFun Function
g ([(Int, Int)] -> Kaucher Double
evalPi [(Int, Int)]
ps))
    evalPi :: [(Int, Int)] -> Kaucher Double
evalPi      = ((Int, Int) -> Kaucher Double -> Kaucher Double)
-> Kaucher Double -> [(Int, Int)] -> Kaucher Double
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(Int
ix, Int
k) Kaucher Double
acc -> Kaucher Double
acc Kaucher Double -> Kaucher Double -> Kaucher Double
forall a. Num a => a -> a -> a
* (Vector (Kaucher Double)
domains Vector (Kaucher Double) -> Int -> Kaucher Double
forall a. Vector a -> Int -> a
! Int
ix Kaucher Double -> Int -> Kaucher Double
forall a. OptIntPow a => a -> Int -> a
^. Int
k)) Kaucher Double
1 
{-# INLINE selectValidTerms #-}
isValidInterval :: Kaucher Double -> Bool
isValidInterval = Bool -> Bool
not(Bool -> Bool)
-> (Kaucher Double -> Bool) -> Kaucher Double -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Kaucher Double -> Bool
isInvalidInterval
{-# INLINE isValidInterval #-}
isInvalidInterval :: Kaucher Double -> Bool                        
isInvalidInterval :: Kaucher Double -> Bool
isInvalidInterval Kaucher Double
ys =  Kaucher Double -> Bool
forall a. Kaucher a -> Bool
Interval.isEmpty Kaucher Double
ys 
                     Bool -> Bool -> Bool
|| Kaucher Double -> Bool
forall a. Kaucher a -> Bool
Interval.isInvalid Kaucher Double
ys
                     Bool -> Bool -> Bool
|| Double -> Bool
forall a. RealFloat a => a -> Bool
isInfinite Double
ys1 Bool -> Bool -> Bool
|| Double -> Bool
forall a. RealFloat a => a -> Bool
isInfinite Double
ys2 
                     Bool -> Bool -> Bool
|| Double
ys2 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
ys1 
                     Bool -> Bool -> Bool
|| Double -> Double
forall a. Num a => a -> a
abs Double
ys1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
1e50 Bool -> Bool -> Bool
|| Double -> Double
forall a. Num a => a -> a
abs Double
ys2 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
1e50
                     Bool -> Bool -> Bool
|| Double -> Bool
forall a. RealFloat a => a -> Bool
isNaN Double
ys1 Bool -> Bool -> Bool
|| Double -> Bool
forall a. RealFloat a => a -> Bool
isNaN Double
ys2
                     Bool -> Bool -> Bool
|| Kaucher Double -> Double
forall a. Num a => Kaucher a -> a
width Kaucher Double
ys Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1e-8
  where
    ys1 :: Double
ys1 = Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe (-Double
1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
0) (Maybe Double -> Double) -> Maybe Double -> Double
forall a b. (a -> b) -> a -> b
$ Kaucher Double -> Maybe Double
forall a. Kaucher a -> Maybe a
inf Kaucher Double
ys
    ys2 :: Double
ys2 = Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe (Double
1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
0) (Maybe Double -> Double) -> Maybe Double -> Double
forall a b. (a -> b) -> a -> b
$ Kaucher Double -> Maybe Double
forall a. Kaucher a -> Maybe a
sup Kaucher Double
ys
{-# INLINE isInvalidInterval #-}            
evalTrain :: Task                          
          -> Bool                          
          -> [Measure]                     
          -> Constraint                    
          -> Penalty                       
          -> V.Vector (Kaucher Double)     
          -> Dataset Double                
          -> Vector Double                 
          -> Dataset Double                
          -> Vector Double                 
          -> Individual 
          -> Individual
evalTrain :: Task
-> Bool
-> [Measure]
-> Constraint
-> Penalty
-> Vector (Kaucher Double)
-> Dataset Double
-> Vector Double
-> Dataset Double
-> Vector Double
-> Individual
-> Individual
evalTrain Task
task Bool
isRefit [Measure]
measures Constraint
cnstrFun Penalty
penalty Vector (Kaucher Double)
domains Dataset Double
xss_train Vector Double
ys_train Dataset Double
xss_val Vector Double
ys_val Individual
sol
  | Bool -> Bool
not Bool
isRefit Bool -> Bool -> Bool
&& (Bool -> Bool
not(Bool -> Bool) -> (Individual -> Bool) -> Individual -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[Double] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null([Double] -> Bool)
-> (Individual -> [Double]) -> Individual -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Individual -> [Double]
_fit) Individual
sol = Individual
sol
  | Bool
otherwise                          = Individual
sol{ _chromo :: TIR
_chromo  = TIR
fitted
                                            , _fit :: [Double]
_fit     = [Double]
fitness
                                            , _weights :: [Vector Double]
_weights = [Vector Double]
ws
                                            , _constr :: Double
_constr  = Double
cnst
                                            , _len :: Int
_len     = Int
len
                                            , _penalty :: Double
_penalty = Double
pnlty 
                                            }
  where
    
    tir :: TIR
tir          = TIR -> Vector (Kaucher Double) -> TIR
selectValidTerms (Individual -> TIR
_chromo Individual
sol) Vector (Kaucher Double)
domains
    ws :: [Vector Double]
ws           = Task -> TIR -> Dataset Double -> Vector Double -> [Vector Double]
fitTask Task
task TIR
tir Dataset Double
xss_train Vector Double
ys_train
    
    
    fitted :: TIR
fitted         = TIR -> Vector Double -> TIR
replaceConsts TIR
tir (Vector Double -> TIR)
-> ([Vector Double] -> Vector Double) -> [Vector Double] -> TIR
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Double -> Vector Double
forall a. Vector a -> Vector a
V.tail (Vector Double -> Vector Double)
-> ([Vector Double] -> Vector Double)
-> [Vector Double]
-> Vector Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Double -> Vector Double
forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
VS.convert (Vector Double -> Vector Double)
-> ([Vector Double] -> Vector Double)
-> [Vector Double]
-> Vector Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Vector Double] -> Vector Double
forall a. [a] -> a
head
                   ([Vector Double] -> TIR) -> [Vector Double] -> TIR
forall a b. (a -> b) -> a -> b
$ [Vector Double]
ws               
    fitness :: [Double]
fitness        = (Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map Double -> Double
forall a. RealFloat a => a -> a
nan2inf ([Double] -> [Double])
-> (Individual -> [Double]) -> Individual -> [Double]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe [Double] -> [Double]
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe [Double] -> [Double])
-> (Individual -> Maybe [Double]) -> Individual -> [Double]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Task
-> [Measure]
-> Dataset Double
-> Vector Double
-> Individual
-> Maybe [Double]
evalTest Task
task [Measure]
measures Dataset Double
xss_val Vector Double
ys_val
                   (Individual -> [Double]) -> Individual -> [Double]
forall a b. (a -> b) -> a -> b
$ Individual
sol{ _chromo :: TIR
_chromo=TIR
fitted, _weights :: [Vector Double]
_weights=[Vector Double]
ws }
    
    tree :: SRTree Int Double
tree           = Double -> TIR -> SRTree Int Double
assembleTree (Vector Double -> Double
forall a. Vector a -> a
V.head (Vector Double -> Double) -> Vector Double -> Double
forall a b. (a -> b) -> a -> b
$ Vector Double -> Vector Double
forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
VS.convert (Vector Double -> Vector Double) -> Vector Double -> Vector Double
forall a b. (a -> b) -> a -> b
$ [Vector Double] -> Vector Double
forall a. [a] -> a
head [Vector Double]
ws) TIR
fitted
    len :: Int
len            = SRTree Int Double -> Int
forall ix val. SRTree ix val -> Int
countNodes SRTree Int Double
tree
    cnst :: Double
cnst           = Constraint
cnstrFun SRTree Int Double
tree
    pnlty :: Double
pnlty          = Penalty -> Int -> Double -> Double
evalPenalty Penalty
penalty Int
len Double
cnst
evalTest :: Task -> [Measure] -> Dataset Double -> Vector Double -> Individual -> Maybe [Double]
evalTest :: Task
-> [Measure]
-> Dataset Double
-> Vector Double
-> Individual
-> Maybe [Double]
evalTest Task
task [Measure]
measures Dataset Double
xss Vector Double
ys Individual
sol
  | [Vector Double] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Vector Double]
weights = Maybe [Double]
forall a. Maybe a
Nothing
  | Bool
otherwise    = [Double] -> Maybe [Double]
forall a. a -> Maybe a
Just
                 ([Double] -> Maybe [Double]) -> [Double] -> Maybe [Double]
forall a b. (a -> b) -> a -> b
$ [Measure] -> Vector Double -> Vector Double -> [Double]
applyMeasures [Measure]
measures Vector Double
ys
                 (Vector Double -> [Double]) -> Vector Double -> [Double]
forall a b. (a -> b) -> a -> b
$ Task -> [Vector Double] -> Vector Double
predictTask Task
task
                 ([Vector Double] -> Vector Double)
-> [Vector Double] -> Vector Double
forall a b. (a -> b) -> a -> b
$ (Vector Double -> Vector Double)
-> [Vector Double] -> [Vector Double]
forall a b. (a -> b) -> [a] -> [b]
map (Dataset Double -> Double -> TIR -> Vector Double
evalTIR Dataset Double
xss' Double
bias (TIR -> Vector Double)
-> (Vector Double -> TIR) -> Vector Double -> Vector Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TIR -> Vector Double -> TIR
replaceConsts TIR
tir (Vector Double -> TIR)
-> (Vector Double -> Vector Double) -> Vector Double -> TIR
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Double -> Vector Double
forall a. Vector a -> Vector a
V.tail (Vector Double -> Vector Double)
-> (Vector Double -> Vector Double)
-> Vector Double
-> Vector Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Double -> Vector Double
forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
VS.convert) [Vector Double]
weights
  where
    tir :: TIR
tir          = Individual -> TIR
_chromo Individual
sol
    weights :: [Vector Double]
weights      = Individual -> [Vector Double]
_weights Individual
sol
    bias :: Double
bias         = Vector Double -> Double
forall a. Vector a -> a
V.head (Vector Double -> Double) -> Vector Double -> Double
forall a b. (a -> b) -> a -> b
$ Vector Double -> Vector Double
forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
VS.convert (Vector Double -> Vector Double) -> Vector Double -> Vector Double
forall a b. (a -> b) -> a -> b
$ [Vector Double] -> Vector Double
forall a. [a] -> a
head [Vector Double]
weights 
    
    xss' :: Dataset Double
xss'         = Dataset Double -> Dataset Double
forall a. Vector a -> Vector a
V.tail Dataset Double
xss
    
evalTIR :: Dataset Double -> Double -> TIR -> LA.Vector Double
evalTIR :: Dataset Double -> Double -> TIR -> Vector Double
evalTIR Dataset Double
xss Double
bias (TIR Function
g Sigma
p Sigma
q) = Function -> Vector Double -> Vector Double
forall val. Floating val => Function -> val -> val
evalFun Function
g ((Double -> Vector Double
forall (c :: * -> *) e. Container c e => e -> c e
LA.scalar Double
bias Vector Double -> Vector Double -> Vector Double
forall a. Num a => a -> a -> a
+ Vector Double
p') Vector Double -> Vector Double -> Vector Double
forall a. Fractional a => a -> a -> a
/ (Vector Double
1 Vector Double -> Vector Double -> Vector Double
forall a. Num a => a -> a -> a
+ Vector Double
q'))
  where
    p' :: Vector Double
p'     = ((Double, Function, [(Int, Int)])
 -> Vector Double -> Vector Double)
-> Vector Double -> Sigma -> Vector Double
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(Double
w, Function
h, [(Int, Int)]
ks) Vector Double
acc -> Double -> Vector Double
forall (c :: * -> *) e. Container c e => e -> c e
LA.scalar Double
w Vector Double -> Vector Double -> Vector Double
forall a. Num a => a -> a -> a
* Function -> Vector Double -> Vector Double
forall val. Floating val => Function -> val -> val
evalFun Function
h ([(Int, Int)] -> Vector Double
evalPi [(Int, Int)]
ks) Vector Double -> Vector Double -> Vector Double
forall a. Num a => a -> a -> a
+ Vector Double
acc) Vector Double
0 Sigma
p
    q' :: Vector Double
q'     = ((Double, Function, [(Int, Int)])
 -> Vector Double -> Vector Double)
-> Vector Double -> Sigma -> Vector Double
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(Double
w, Function
h, [(Int, Int)]
ks) Vector Double
acc -> Double -> Vector Double
forall (c :: * -> *) e. Container c e => e -> c e
LA.scalar Double
w Vector Double -> Vector Double -> Vector Double
forall a. Num a => a -> a -> a
* Function -> Vector Double -> Vector Double
forall val. Floating val => Function -> val -> val
evalFun Function
h ([(Int, Int)] -> Vector Double
evalPi [(Int, Int)]
ks) Vector Double -> Vector Double -> Vector Double
forall a. Num a => a -> a -> a
+ Vector Double
acc) Vector Double
0 Sigma
q
    evalPi :: [(Int, Int)] -> Vector Double
evalPi = ((Int, Int) -> Vector Double -> Vector Double)
-> Vector Double -> [(Int, Int)] -> Vector Double
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(Int
ix,Int
k) Vector Double
acc -> Vector Double
acc Vector Double -> Vector Double -> Vector Double
forall a. Num a => a -> a -> a
* (Dataset Double
xss Dataset Double -> Int -> Vector Double
forall a. Vector a -> Int -> a
! Int
ix)Vector Double -> Int -> Vector Double
forall a b. (Fractional a, Integral b) => a -> b -> a
^^Int
k) Vector Double
1
{-# INLINE evalTIR #-}
    
nan2inf :: RealFloat a => a -> a
nan2inf :: forall a. RealFloat a => a -> a
nan2inf a
x | a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x = a
1a -> a -> a
forall a. Fractional a => a -> a -> a
/a
0
          |Bool
otherwise = a
x
{-# INLINE nan2inf #-}