module MachineLearning.TIR where
import Control.Evolution
import Control.Monad.State.Strict
import Data.List.Split
import Data.SRTree
import System.Random
import Control.DeepSeq (NFData, rnf)
import Data.List (delete)
import Data.SRTree.Print (showDefault)
import Data.Vector (Vector)
import qualified Data.Vector as V
import qualified Data.Vector.Storable as VS
import qualified Numeric.LinearAlgebra as LA
import MachineLearning.Utils.Config
data TIR = TIR { TIR -> Function
_funY :: Function
, TIR -> Sigma
_p :: Sigma
, TIR -> Sigma
_q :: Sigma
} deriving Int -> TIR -> ShowS
[TIR] -> ShowS
TIR -> String
(Int -> TIR -> ShowS)
-> (TIR -> String) -> ([TIR] -> ShowS) -> Show TIR
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TIR] -> ShowS
$cshowList :: [TIR] -> ShowS
show :: TIR -> String
$cshow :: TIR -> String
showsPrec :: Int -> TIR -> ShowS
$cshowsPrec :: Int -> TIR -> ShowS
Show
instance NFData TIR where
rnf :: TIR -> ()
rnf TIR
_ = ()
type Sigma = [Pi]
type Pi = (Double, Function, [(Int, Int)])
randomRng :: (Int, Int) -> Rnd Int
randomRng :: (Int, Int) -> Rnd Int
randomRng (Int, Int)
rng = (StdGen -> (Int, StdGen)) -> Rnd Int
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state ((StdGen -> (Int, StdGen)) -> Rnd Int)
-> (StdGen -> (Int, StdGen)) -> Rnd Int
forall a b. (a -> b) -> a -> b
$ (Int, Int) -> StdGen -> (Int, StdGen)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Int, Int)
rng
{-# INLINE randomRng #-}
randomRngNZ :: (Int, Int) -> Rnd Int
randomRngNZ :: (Int, Int) -> Rnd Int
randomRngNZ (Int, Int)
rng = do
Int
x <- (Int, Int) -> Rnd Int
randomRng (Int, Int)
rng
if Int
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
then (Int, Int) -> Rnd Int
randomRngNZ (Int, Int)
rng
else Int -> Rnd Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
x
{-# INLINE randomRngNZ #-}
randomFrom :: [a] -> Rnd a
randomFrom :: forall a. [a] -> Rnd a
randomFrom [a]
xs = do
Int
ix <- (Int, Int) -> Rnd Int
randomRng (Int
0, [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
a -> Rnd a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([a]
xs [a] -> Int -> a
forall a. [a] -> Int -> a
!! Int
ix)
{-# INLINE randomFrom #-}
randomVar :: MutationCfg -> Rnd (Maybe Int, MutationCfg)
randomVar :: MutationCfg -> Rnd (Maybe Int, MutationCfg)
randomVar MutationCfg
params = do
let vars :: [Int]
vars = MutationCfg -> [Int]
_vars MutationCfg
params
n :: Int
n = [Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
vars
Int
ix <- (Int, Int) -> Rnd Int
randomRng (Int
0, Int
n)
if Int
ix Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n
then (Maybe Int, MutationCfg) -> Rnd (Maybe Int, MutationCfg)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Int
forall a. Maybe a
Nothing, MutationCfg
params)
else do let x :: Int
x = [Int]
vars [Int] -> Int -> Int
forall a. [a] -> Int -> a
!! Int
ix
(Maybe Int, MutationCfg) -> Rnd (Maybe Int, MutationCfg)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
x, MutationCfg
params{ _vars :: [Int]
_vars=Int -> [Int] -> [Int]
forall a. Eq a => a -> [a] -> [a]
delete Int
x [Int]
vars })
randomVars :: MutationCfg -> Rnd [(Int, Int)]
randomVars :: MutationCfg -> Rnd [(Int, Int)]
randomVars MutationCfg
params = do
(Maybe Int
v, MutationCfg
params') <- MutationCfg -> Rnd (Maybe Int, MutationCfg)
randomVar MutationCfg
params
Int
k <- (Int, Int) -> Rnd Int
randomRngNZ ((Int, Int) -> Rnd Int) -> (Int, Int) -> Rnd Int
forall a b. (a -> b) -> a -> b
$ MutationCfg -> (Int, Int)
_kRange MutationCfg
params
case Maybe Int
v of
Maybe Int
Nothing -> [(Int, Int)] -> Rnd [(Int, Int)]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
Just Int
var -> do [(Int, Int)]
vs <- MutationCfg -> Rnd [(Int, Int)]
randomVars MutationCfg
params'
[(Int, Int)] -> Rnd [(Int, Int)]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(Int, Int)] -> Rnd [(Int, Int)])
-> [(Int, Int)] -> Rnd [(Int, Int)]
forall a b. (a -> b) -> a -> b
$ (Int
var, Int
k) (Int, Int) -> [(Int, Int)] -> [(Int, Int)]
forall a. a -> [a] -> [a]
: [(Int, Int)]
vs
randomPi :: MutationCfg -> Rnd (Maybe Pi)
randomPi :: MutationCfg -> Rnd (Maybe (Double, Function, [(Int, Int)]))
randomPi MutationCfg
params = do
[(Int, Int)]
pis <- MutationCfg -> Rnd [(Int, Int)]
randomVars MutationCfg
params
Function
f <- [Function] -> Rnd Function
forall a. [a] -> Rnd a
randomFrom ([Function] -> Rnd Function) -> [Function] -> Rnd Function
forall a b. (a -> b) -> a -> b
$ MutationCfg -> [Function]
_funs MutationCfg
params
if [(Int, Int)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Int, Int)]
pis
then Maybe (Double, Function, [(Int, Int)])
-> Rnd (Maybe (Double, Function, [(Int, Int)]))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Double, Function, [(Int, Int)])
forall a. Maybe a
Nothing
else Maybe (Double, Function, [(Int, Int)])
-> Rnd (Maybe (Double, Function, [(Int, Int)]))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (Double, Function, [(Int, Int)])
-> Rnd (Maybe (Double, Function, [(Int, Int)])))
-> Maybe (Double, Function, [(Int, Int)])
-> Rnd (Maybe (Double, Function, [(Int, Int)]))
forall a b. (a -> b) -> a -> b
$ (Double, Function, [(Int, Int)])
-> Maybe (Double, Function, [(Int, Int)])
forall a. a -> Maybe a
Just (Double
1.0, Function
f, [(Int, Int)]
pis)
randomSigma :: MutationCfg -> Int -> Rnd (Sigma, Int)
randomSigma :: MutationCfg -> Int -> Rnd (Sigma, Int)
randomSigma MutationCfg
params Int
budget | Int
budget Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = (Sigma, Int) -> Rnd (Sigma, Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([], Int
budget)
randomSigma MutationCfg
params Int
budget = do
Int
n <- (Int, Int) -> Rnd Int
randomRng (Int
0, Int
budget)
if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
budget
then (Sigma, Int) -> Rnd (Sigma, Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([], Int
budget)
else do Maybe (Double, Function, [(Int, Int)])
term <- MutationCfg -> Rnd (Maybe (Double, Function, [(Int, Int)]))
randomPi MutationCfg
params
(Sigma
terms, Int
budget') <- MutationCfg -> Int -> Rnd (Sigma, Int)
randomSigma MutationCfg
params (Int
budget Int -> Int -> Int
forall a. Num a => a -> a -> a
- Maybe (Double, Function, [(Int, Int)]) -> Int
forall {p} {a} {b} {c}. Num p => Maybe (a, b, c) -> p
spentBudget Maybe (Double, Function, [(Int, Int)])
term)
case Maybe (Double, Function, [(Int, Int)])
term of
Maybe (Double, Function, [(Int, Int)])
Nothing -> (Sigma, Int) -> Rnd (Sigma, Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Sigma
terms, Int
budget')
Just (Double, Function, [(Int, Int)])
t -> (Sigma, Int) -> Rnd (Sigma, Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Double, Function, [(Int, Int)])
t(Double, Function, [(Int, Int)]) -> Sigma -> Sigma
forall a. a -> [a] -> [a]
:Sigma
terms, Int
budget')
where
spentBudget :: Maybe (a, b, c) -> p
spentBudget Maybe (a, b, c)
Nothing = p
0
spentBudget (Just (a
_, b
_, c
ps)) = p
1
randomTIR :: MutationCfg -> Rnd TIR
randomTIR :: MutationCfg -> Rnd TIR
randomTIR MutationCfg
params = do
Function
yf <- [Function] -> Rnd Function
forall a. [a] -> Rnd a
randomFrom ([Function] -> Rnd Function) -> [Function] -> Rnd Function
forall a b. (a -> b) -> a -> b
$ MutationCfg -> [Function]
_yfuns MutationCfg
params
(Sigma
p, Int
budget') <- MutationCfg -> Int -> Rnd (Sigma, Int)
randomSigma MutationCfg
params (Int -> Rnd (Sigma, Int)) -> Int -> Rnd (Sigma, Int)
forall a b. (a -> b) -> a -> b
$ MutationCfg -> Int
_budget MutationCfg
params
(Sigma
q, Int
_) <- MutationCfg -> Int -> Rnd (Sigma, Int)
randomSigma MutationCfg
params Int
budget'
if Sigma -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Sigma
p
then MutationCfg -> Rnd TIR
randomTIR MutationCfg
params
else TIR -> Rnd TIR
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Function -> Sigma -> Sigma -> TIR
TIR Function
yf Sigma
p Sigma
q)
type Column a = LA.Vector a
type Dataset a = Vector (Column a)
type Constraint = SRTree Int Double -> Double
data Individual = Individual { Individual -> TIR
_chromo :: TIR
, Individual -> [Double]
_fit :: [Double]
, Individual -> [Vector Double]
_weights :: [LA.Vector Double]
, Individual -> Double
_constr :: Double
, Individual -> Int
_len :: Int
, Individual -> Double
_penalty :: Double
}
createIndividual :: TIR -> Individual
createIndividual :: TIR -> Individual
createIndividual TIR
tir = TIR
-> [Double]
-> [Vector Double]
-> Double
-> Int
-> Double
-> Individual
Individual TIR
tir [] [] Double
0.0 Int
0 Double
0.0
penalizedFit :: Individual -> Double
penalizedFit :: Individual -> Double
penalizedFit Individual
t = ([Double] -> Double
forall a. [a] -> a
head ([Double] -> Double)
-> (Individual -> [Double]) -> Individual -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Individual -> [Double]
_fit) Individual
t Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Individual -> Double
_penalty Individual
t
{-# INLINE penalizedFit #-}
replaceConsts :: TIR -> V.Vector Double -> TIR
replaceConsts :: TIR -> Vector Double -> TIR
replaceConsts (TIR Function
g Sigma
p Sigma
q) Vector Double
ws = Function -> Sigma -> Sigma -> TIR
TIR Function
g Sigma
p' Sigma
q'
where
(Sigma
p', [Double]
ws1) = State [Double] Sigma -> [Double] -> (Sigma, [Double])
forall s a. State s a -> s -> (a, s)
runState (((Double, Function, [(Int, Int)])
-> StateT [Double] Identity (Double, Function, [(Int, Int)]))
-> Sigma -> State [Double] Sigma
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Double, Function, [(Int, Int)])
-> StateT [Double] Identity (Double, Function, [(Int, Int)])
replaceWeight Sigma
p) (Vector Double -> [Double]
forall a. Vector a -> [a]
V.toList Vector Double
ws)
(Sigma
q', [Double]
ws2) = State [Double] Sigma -> [Double] -> (Sigma, [Double])
forall s a. State s a -> s -> (a, s)
runState (((Double, Function, [(Int, Int)])
-> StateT [Double] Identity (Double, Function, [(Int, Int)]))
-> Sigma -> State [Double] Sigma
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Double, Function, [(Int, Int)])
-> StateT [Double] Identity (Double, Function, [(Int, Int)])
replaceWeight Sigma
q) [Double]
ws1
replaceWeight :: Pi -> State [Double] Pi
replaceWeight :: (Double, Function, [(Int, Int)])
-> StateT [Double] Identity (Double, Function, [(Int, Int)])
replaceWeight (Double
w, Function
g, [(Int, Int)]
h) = ([Double] -> ((Double, Function, [(Int, Int)]), [Double]))
-> StateT [Double] Identity (Double, Function, [(Int, Int)])
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state (([Double] -> ((Double, Function, [(Int, Int)]), [Double]))
-> StateT [Double] Identity (Double, Function, [(Int, Int)]))
-> ([Double] -> ((Double, Function, [(Int, Int)]), [Double]))
-> StateT [Double] Identity (Double, Function, [(Int, Int)])
forall a b. (a -> b) -> a -> b
$ \[Double]
ws -> case [Double]
ws of
(Double
wi:[Double]
ws') -> ((Double
wi, Function
g, [(Int, Int)]
h), [Double]
ws')
[] -> String -> ((Double, Function, [(Int, Int)]), [Double])
forall a. HasCallStack => String -> a
error (String -> ((Double, Function, [(Int, Int)]), [Double]))
-> String -> ((Double, Function, [(Int, Int)]), [Double])
forall a b. (a -> b) -> a -> b
$ [(Int, Int)] -> String
forall a. Show a => a -> String
show [(Int, Int)]
h
instance Eq Individual where
Individual
t1 == :: Individual -> Individual -> Bool
== Individual
t2 = Individual -> Double
penalizedFit Individual
t1 Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Individual -> Double
penalizedFit Individual
t2
instance Ord Individual where
Individual
t1 <= :: Individual -> Individual -> Bool
<= Individual
t2 = Individual -> Double
penalizedFit Individual
t1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Individual -> Double
penalizedFit Individual
t2
instance NFData Individual where
rnf :: Individual -> ()
rnf Individual
_ = ()
instance Solution Individual where
_getFitness :: Individual -> Double
_getFitness = [Double] -> Double
forall a. [a] -> a
head ([Double] -> Double)
-> (Individual -> [Double]) -> Individual -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Individual -> [Double]
_fit
_isFeasible :: Individual -> Bool
_isFeasible = (Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<Double
1e-12) (Double -> Bool) -> (Individual -> Double) -> Individual -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Individual -> Double
_constr
assembleTree :: Double -> TIR -> SRTree Int Double
assembleTree :: Double -> TIR -> SRTree Int Double
assembleTree Double
bias (TIR Function
f Sigma
p Sigma
q) = Function -> SRTree Int Double -> SRTree Int Double
forall ix val. Function -> SRTree ix val -> SRTree ix val
Fun Function
f ((Double -> SRTree Int Double
forall ix val. val -> SRTree ix val
Const Double
bias SRTree Int Double -> SRTree Int Double -> SRTree Int Double
forall a. Num a => a -> a -> a
+ Sigma -> SRTree Int Double
forall {ix} {val} {t :: * -> *}.
(Eq ix, Eq val, Num val, Foldable t) =>
[(val, Function, t (ix, Int))] -> SRTree ix val
assemble Sigma
p) SRTree Int Double -> SRTree Int Double -> SRTree Int Double
forall a. Fractional a => a -> a -> a
/ (SRTree Int Double
1 SRTree Int Double -> SRTree Int Double -> SRTree Int Double
forall a. Num a => a -> a -> a
+ Sigma -> SRTree Int Double
forall {ix} {val} {t :: * -> *}.
(Eq ix, Eq val, Num val, Foldable t) =>
[(val, Function, t (ix, Int))] -> SRTree ix val
assemble Sigma
q))
where
assemble :: [(val, Function, t (ix, Int))] -> SRTree ix val
assemble [] = SRTree ix val
0
assemble [(val, Function, t (ix, Int))
p'] = (val, Function, t (ix, Int)) -> SRTree ix val
forall {ix} {val} {t :: * -> *}.
(Eq ix, Eq val, Num val, Foldable t) =>
(val, Function, t (ix, Int)) -> SRTree ix val
mk (val, Function, t (ix, Int))
p'
assemble ((val, Function, t (ix, Int))
p':[(val, Function, t (ix, Int))]
ps) = (val, Function, t (ix, Int)) -> SRTree ix val
forall {ix} {val} {t :: * -> *}.
(Eq ix, Eq val, Num val, Foldable t) =>
(val, Function, t (ix, Int)) -> SRTree ix val
mk (val, Function, t (ix, Int))
p' SRTree ix val -> SRTree ix val -> SRTree ix val
forall a. Num a => a -> a -> a
+ [(val, Function, t (ix, Int))] -> SRTree ix val
assemble [(val, Function, t (ix, Int))]
ps
mk :: (val, Function, t (ix, Int)) -> SRTree ix val
mk (val
v, Function
g, t (ix, Int)
ts) = val -> SRTree ix val
forall ix val. val -> SRTree ix val
Const val
v SRTree ix val -> SRTree ix val -> SRTree ix val
forall a. Num a => a -> a -> a
* Function -> SRTree ix val -> SRTree ix val
forall ix val. Function -> SRTree ix val -> SRTree ix val
Fun Function
g (((ix, Int) -> SRTree ix val -> SRTree ix val)
-> SRTree ix val -> t (ix, Int) -> SRTree ix val
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(ix
ix, Int
k) SRTree ix val
acc -> SRTree ix val
acc SRTree ix val -> SRTree ix val -> SRTree ix val
forall a. Num a => a -> a -> a
* SRTree ix val -> Int -> SRTree ix val
forall ix val. SRTree ix val -> Int -> SRTree ix val
Pow (ix -> SRTree ix val
forall ix val. ix -> SRTree ix val
Var ix
ix) Int
k) SRTree ix val
1 t (ix, Int)
ts)
prettyPrintsolution :: Individual -> String
prettyPrintsolution :: Individual -> String
prettyPrintsolution Individual
sol | [Double] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
Prelude.null (Individual -> [Double]
_fit Individual
sol) = ShowS
forall a. HasCallStack => String -> a
error String
"unevaluated solution"
prettyPrintsolution Individual
sol = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"Expression:\n", (SRTree Int Double -> String
forall {ix} {val}. (Show ix, Show val) => SRTree ix val -> String
showDefault (SRTree Int Double -> String)
-> (Individual -> SRTree Int Double) -> Individual -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> TIR -> SRTree Int Double
assembleTree Double
bias (TIR -> SRTree Int Double)
-> (Individual -> TIR) -> Individual -> SRTree Int Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Individual -> TIR
_chromo) Individual
sol, String
"\n"
, String
"Fitness: ", (Double -> String
forall a. Show a => a -> String
show (Double -> String)
-> (Individual -> Double) -> Individual -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Double] -> Double
forall a. [a] -> a
head ([Double] -> Double)
-> (Individual -> [Double]) -> Individual -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Individual -> [Double]
_fit) Individual
sol, String
"\n"
, String
"Constraints: ", (Double -> String
forall a. Show a => a -> String
show (Double -> String)
-> (Individual -> Double) -> Individual -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Individual -> Double
_constr) Individual
sol, String
"\n"
, String
"Length: ", (Int -> String
forall a. Show a => a -> String
show (Int -> String) -> (Individual -> Int) -> Individual -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Individual -> Int
_len) Individual
sol, String
"\n"
, String
"Penalty: ", (Double -> String
forall a. Show a => a -> String
show (Double -> String)
-> (Individual -> Double) -> Individual -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Individual -> Double
_penalty) Individual
sol, String
"\n"
]
where 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] -> Vector Double)
-> [Vector Double] -> Vector Double
forall a b. (a -> b) -> a -> b
$ Individual -> [Vector Double]
_weights Individual
sol