HLearn-distributions-0.2.2: src/HLearn/Models/Distributions/Multivariate.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE RankNTypes #-}
-- {-# LANGUAGE DatatypeContexts #-}
-- |
module HLearn.Models.Distributions.Multivariate
{- ( MultivariateParams (..)
, Multivariate
, (:::) (..)
)-}
where
import HLearn.Algebra
import HLearn.Models.Distributions.Common
import HLearn.Models.Distributions.Categorical
import GHC.TypeLits
-- data Discrete
-- data Continuous
-- data Copula
-- data ParamsBox = forall (Model params dist) => params . ParamsBox params
-- data DistBox
-------------------------------------------------------------------------------
-- Crazy Tuple
-- data T a b c = (a c) ::: (b c)
-- deriving (Read,Show,Eq,Ord)
data a ::: b = a ::: b
deriving (Read,Show,Eq,Ord)
instance (Semigroup a, Semigroup b) => Semigroup (a ::: b) where
(a1 ::: b1) <> (a2 ::: b2) = (a1<>a2):::(b1<>b2)
instance (Monoid a, Monoid b) => Monoid (a ::: b) where
mempty = mempty ::: mempty
(a1 ::: b1) `mappend` (a2 ::: b2) = (a1 `mappend` a2):::(b1 `mappend` b2)
instance (RegularSemigroup a, RegularSemigroup b) => RegularSemigroup (a ::: b) where
inverse (a ::: b) = (inverse a):::(inverse b)
-------------------------------------------------------------------------------
-- Multivariate
data MultivariateParams distparams {-copulaparams-} = MultivariateParams
{ distparams :: distparams
-- , copulaparams :: copulaparams
}
deriving (Read,Show,Eq,Ord)
data Multivariate' distparams {-copulaparams-} distL {-copula-} = Multivariate'
{ params :: MultivariateParams distparams {-copulaparams-}
, distL :: distL
-- , copula :: copula
}
deriving (Read,Show,Eq,Ord)
-- data Multivariate' distparams {-copulaparams-} distL {-copula-} = Multivariate'
-- { params :: MultivariateParams distparams {-copulaparams-}
-- , distL :: distL
-- -- , copula :: copula
-- }
-- deriving (Read,Show,Eq,Ord)
data ParamsMask dist = forall params dist . (Model params dist) => ParamsMask dist
-- type Multivariate distL = forall distparams distL . (Model distparams distL) => RegSG2Group (Multivariate' distparams distL)
type Multivariate distparams distL = RegSG2Group (Multivariate' distparams distL)
-- Multivariate distL = forall (Model distparams distL) => RegSG2Group (Multivariate' distparams distL)
-- data Booger distL = forall distparams distL . (Model distparams distL) => Booger (Multivariate distparams distL)
-------------------------------------------------------------------------------
-- Algebra
instance (Semigroup distL, Eq distparams) => Semigroup (Multivariate' distparams distL) where
mv1 <> mv2 = if (params mv1)/=(params mv2)
then error "Multivariate.(<>): Adding distributions with different params"
else mv1 { distL = (distL mv1) <> (distL mv2) }
instance (RegularSemigroup distL, Eq distparams) => RegularSemigroup (Multivariate' distparams distL) where
inverse mv = mv { distL = inverse $ distL mv }
-------------------------------------------------------------------------------
-- Training
instance
( Model params1 model1
, Model params2 model2
) => Model (params1 ::: params2) (model1 ::: model2) where
getparams (model1 ::: model2) = (getparams model1 ::: getparams model2)
instance
( DefaultModel params1 model1
, DefaultModel params2 model2
, Model (params1 ::: params2) (model1 ::: model2)
) => DefaultModel (params1 ::: params2) (model1 ::: model2) where
defparams = (defparams ::: defparams)
instance (RegularSemigroup distL, Eq distparams) => Model (MultivariateParams distparams) (Multivariate distparams distL) where
getparams (SGJust mv) = params mv
instance
( DefaultModel params dist
, DefaultModel paramsT distT
, RegularSemigroup dist
, RegularSemigroup distT
, Eq params
, Eq paramsT
) => DefaultModel (MultivariateParams (params ::: paramsT)) (Multivariate (params ::: paramsT) (dist ::: distT))
where
defparams = MultivariateParams (defparams ::: defparams)
instance
( HomTrainer params1 dp1 model1
, HomTrainer params2 dp2 model2
) => HomTrainer (params1 ::: params2) (dp1 ::: dp2) (model1 ::: model2)
where
train1dp' (params1 ::: params2) (dp1 ::: dp2) = (train1dp' params1 dp1 ::: train1dp' params2 dp2)
instance
( HomTrainer params dp dist
, HomTrainer paramsT dpT distT
, RegularSemigroup dist
, RegularSemigroup distT
, Eq paramsT
, Eq params
) => HomTrainer (MultivariateParams (params ::: paramsT)) (dp ::: dpT) (Multivariate (params ::: paramsT) (dist ::: distT))
where
train1dp' (MultivariateParams (params ::: paramsT)) (dp ::: dpT) =
SGJust $ Multivariate' (MultivariateParams (params ::: paramsT)) (train1dp' params dp ::: train1dp' paramsT dpT)
-------------------------------------------------------------------------------
-- Distribution
instance
( Eq params
, RegularSemigroup dist
, Distribution dist dp prob
) => Distribution (Multivariate params dist) dp prob where
pdf (SGJust dist) = pdf (distL dist)
instance
( Num prob
, Distribution dist dp prob
, Distribution distT dpT prob
) => Distribution (dist:::distT) (dp:::dpT) prob where
pdf (dist:::distT) (dp:::dpT) = (pdf dist dp)*(pdf distT dpT)
-- instance
-- ( Eq params
-- , Eq paramsT
-- , RegularSemigroup dist
-- , RegularSemigroup distT
-- , Distribution dist dp prob
-- ) => Distribution (Multivariate (params ::: paramsT) (dist:::distT)) (dp:::dpT) prob where
-- pdf (SGJust (Multivariate' params (dist:::distT))) (dp ::: dpT) = (pdf dist dp)*(pdf () dpT)
-------------------------------------------------------------------------------
-- Testing
test = train1dp ("food":::6:::4)
:: Multivariate (CategoricalParams ::: CategoricalParams ::: CategoricalParams)
(Categorical String Double ::: Categorical Int Double ::: Categorical Int Double)
test2 = train [("food" ::: "dog")
,("food" ::: "cat")
,("drink" ::: "water")
,("drink" ::: "piss")
]
:: Multivariate (CategoricalParams ::: CategoricalParams) (Categorical String Double ::: Categorical String Double)