hmm-lapack 0.3.0.3 → 0.4
raw patch · 13 files changed
+595/−564 lines, 13 filesdep −boxesdep ~comfort-arraydep ~lapackdep ~non-emptyPVP ok
version bump matches the API change (PVP)
Dependencies removed: boxes
Dependency ranges changed: comfort-array, lapack, non-empty, random, semigroups
API changes (from Hackage documentation)
- Math.HiddenMarkovModel: distribution :: T distr sh prob -> distr
- Math.HiddenMarkovModel: initial :: T distr sh prob -> Vector sh prob
- Math.HiddenMarkovModel: trainedDistribution :: Trained distr sh prob -> distr
- Math.HiddenMarkovModel: trainedInitial :: Trained distr sh prob -> Vector sh prob
- Math.HiddenMarkovModel: trainedTransition :: Trained distr sh prob -> SquareMatrix sh prob
- Math.HiddenMarkovModel: transition :: T distr sh prob -> SquareMatrix sh prob
- Math.HiddenMarkovModel.Distribution: Discrete :: (Map symbol (Vector sh prob)) -> Discrete symbol sh prob
- Math.HiddenMarkovModel.Distribution: DiscreteTrained :: (Map symbol (Vector sh prob)) -> DiscreteTrained symbol sh prob
- Math.HiddenMarkovModel.Distribution: Gaussian :: (Array stateSh (Vector emiSh a, UpperTriangular emiSh a, a)) -> Gaussian emiSh stateSh a
- Math.HiddenMarkovModel.Distribution: GaussianTrained :: (Array stateSh (Maybe (Vector emiSh a, HermitianMatrix emiSh a, a))) -> GaussianTrained emiSh stateSh a
- Math.HiddenMarkovModel.Distribution: instance (C emiSh, Eq emiSh, Indexed stateSh, Eq stateSh, Real a) => EmissionProb (Gaussian emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (C emiSh, Eq emiSh, Indexed stateSh, Eq stateSh, Real a) => Estimate (GaussianTrained emiSh stateSh a) (Gaussian emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (C emiSh, Eq emiSh, Indexed stateSh, Eq stateSh, Real a) => Generate (Gaussian emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (C sh, Real prob, Ord symbol) => Info (Discrete symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (C sh, Real prob, Show prob, Read prob, CSVSymbol symbol) => FromCSV (Discrete symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (C sh, Real prob, Show prob, Read prob, CSVSymbol symbol) => ToCSV (Discrete symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (FormatArray emiSh, C stateSh, Real a) => Format (Gaussian emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (FormatArray sh, Real prob, Format symbol) => Format (Discrete symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (Indexed emiSh, Indexed stateSh, Real a, Eq a, Show a, Read a) => ToCSV (Gaussian emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (Indexed sh, Eq sh, Real prob, Ord symbol) => Estimate (DiscreteTrained symbol sh prob) (Discrete symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (Indexed sh, Real prob, Ord symbol) => EmissionProb (Discrete symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (Indexed sh, Real prob, Ord symbol, Ord prob, Random prob) => Generate (Discrete symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (Indexed stateSh, Eq stateSh, Real a) => Info (Gaussian emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (NFData emiSh, NFData stateSh, C stateSh, NFData a, Storable a) => NFData (Gaussian emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (NFData emiSh, NFData stateSh, C stateSh, NFData a, Storable a) => NFData (GaussianTrained emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (NFData sh, NFData prob, NFData symbol) => NFData (Discrete symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (NFData sh, NFData prob, NFData symbol) => NFData (DiscreteTrained symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (Show emiSh, Show stateSh, Show a, Storable a, C emiSh, C stateSh) => Show (Gaussian emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (Show emiSh, Show stateSh, Show a, Storable a, C emiSh, C stateSh) => Show (GaussianTrained emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance (Show symbol, Show sh, Show prob, Storable prob, C sh) => Show (Discrete symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (Show symbol, Show sh, Show prob, Storable prob, C sh) => Show (DiscreteTrained symbol sh prob)
- Math.HiddenMarkovModel.Distribution: instance (emiSh ~ ZeroInt, Indexed stateSh, Real a, Eq a, Show a, Read a) => FromCSV (Gaussian emiSh stateSh a)
- Math.HiddenMarkovModel.Distribution: instance CSVSymbol Char
- Math.HiddenMarkovModel.Distribution: instance CSVSymbol Int
- Math.HiddenMarkovModel.Distribution: newtype Discrete symbol sh prob
- Math.HiddenMarkovModel.Distribution: newtype DiscreteTrained symbol sh prob
- Math.HiddenMarkovModel.Distribution: newtype Gaussian emiSh stateSh a
- Math.HiddenMarkovModel.Distribution: newtype GaussianTrained emiSh stateSh a
- Math.HiddenMarkovModel.Example.SineWave: instance Bounded State
- Math.HiddenMarkovModel.Example.SineWave: instance Enum State
- Math.HiddenMarkovModel.Example.SineWave: instance Eq State
- Math.HiddenMarkovModel.Example.SineWave: instance Ord State
- Math.HiddenMarkovModel.Named: instance (NFData distr, NFData sh, NFData ix, NFData prob, C sh, Storable prob) => NFData (T distr sh ix prob)
- Math.HiddenMarkovModel.Named: instance (Show distr, Show sh, Show ix, Show prob, Storable prob, C sh) => Show (T distr sh ix prob)
- Math.HiddenMarkovModel.Named: model :: T distr sh ix prob -> T distr sh prob
- Math.HiddenMarkovModel.Named: nameFromStateMap :: T distr sh ix prob -> Array sh String
- Math.HiddenMarkovModel.Named: stateFromNameMap :: T distr sh ix prob -> Map String ix
- Math.HiddenMarkovModel.Pattern: instance (Indexed sh, Eq sh, Real prob) => Semigroup (T sh prob)
+ Math.HiddenMarkovModel: [distribution] :: T typ sh prob -> T typ sh prob
+ Math.HiddenMarkovModel: [initial] :: T typ sh prob -> Vector sh prob
+ Math.HiddenMarkovModel: [trainedDistribution] :: Trained typ sh prob -> Trained typ sh prob
+ Math.HiddenMarkovModel: [trainedInitial] :: Trained typ sh prob -> Vector sh prob
+ Math.HiddenMarkovModel: [trainedTransition] :: Trained typ sh prob -> Square sh prob
+ Math.HiddenMarkovModel: [transition] :: T typ sh prob -> Square sh prob
+ Math.HiddenMarkovModel.Distribution: accumulateEmissionVectors :: (Estimate typ, C sh, Eq sh, Real prob) => T [] (Emission typ prob, Vector sh prob) -> Trained typ sh prob
+ Math.HiddenMarkovModel.Distribution: class Format typ
+ Math.HiddenMarkovModel.Distribution: class NFData typ
+ Math.HiddenMarkovModel.Distribution: class Show typ
+ Math.HiddenMarkovModel.Distribution: data Discrete symbol
+ Math.HiddenMarkovModel.Distribution: data Gaussian emiSh
+ Math.HiddenMarkovModel.Distribution: data family Trained typ sh prob
+ Math.HiddenMarkovModel.Distribution: discreteFromList :: (Ord symbol, C sh, Eq sh, Real prob) => T [] (symbol, Vector sh prob) -> T (Discrete symbol) sh prob
+ Math.HiddenMarkovModel.Distribution: format :: (Format typ, C sh, Output out, Real prob) => String -> T typ sh prob -> out
+ Math.HiddenMarkovModel.Distribution: gaussianTrained :: (C emiSh, Eq emiSh, C stateSh, Real prob) => Array stateSh (prob, Vector emiSh prob, Hermitian emiSh prob) -> Trained (Gaussian emiSh) stateSh prob
+ Math.HiddenMarkovModel.Distribution: instance (Data.Array.Comfort.Shape.C emiSh, GHC.Classes.Eq emiSh) => Math.HiddenMarkovModel.Distribution.EmissionProb (Math.HiddenMarkovModel.Distribution.Gaussian emiSh)
+ Math.HiddenMarkovModel.Distribution: instance (Data.Array.Comfort.Shape.C emiSh, GHC.Classes.Eq emiSh) => Math.HiddenMarkovModel.Distribution.Estimate (Math.HiddenMarkovModel.Distribution.Gaussian emiSh)
+ Math.HiddenMarkovModel.Distribution: instance (Data.Array.Comfort.Shape.C emiSh, GHC.Classes.Eq emiSh) => Math.HiddenMarkovModel.Distribution.Generate (Math.HiddenMarkovModel.Distribution.Gaussian emiSh)
+ Math.HiddenMarkovModel.Distribution: instance (Data.Array.Comfort.Shape.C emiSh, GHC.Show.Show emiSh) => Math.HiddenMarkovModel.Distribution.Show (Math.HiddenMarkovModel.Distribution.Gaussian emiSh)
+ Math.HiddenMarkovModel.Distribution: instance (GHC.Show.Show symbol, GHC.Classes.Ord symbol) => Math.HiddenMarkovModel.Distribution.Format (Math.HiddenMarkovModel.Distribution.Discrete symbol)
+ Math.HiddenMarkovModel.Distribution: instance (GHC.Show.Show symbol, GHC.Classes.Ord symbol) => Math.HiddenMarkovModel.Distribution.Show (Math.HiddenMarkovModel.Distribution.Discrete symbol)
+ Math.HiddenMarkovModel.Distribution: instance (Math.HiddenMarkovModel.Distribution.Estimate typ, Data.Array.Comfort.Shape.C sh, GHC.Classes.Eq sh, Numeric.Netlib.Class.Real prob) => GHC.Base.Semigroup (Math.HiddenMarkovModel.Distribution.Trained typ sh prob)
+ Math.HiddenMarkovModel.Distribution: instance (Math.HiddenMarkovModel.Distribution.Format typ, Data.Array.Comfort.Shape.C sh, Numeric.Netlib.Class.Real prob) => Numeric.LAPACK.Format.Format (Math.HiddenMarkovModel.Distribution.T typ sh prob)
+ Math.HiddenMarkovModel.Distribution: instance (Math.HiddenMarkovModel.Distribution.NFData typ, Control.DeepSeq.NFData sh, Control.DeepSeq.NFData prob, Data.Array.Comfort.Shape.C sh) => Control.DeepSeq.NFData (Math.HiddenMarkovModel.Distribution.T typ sh prob)
+ Math.HiddenMarkovModel.Distribution: instance (Math.HiddenMarkovModel.Distribution.NFData typ, Control.DeepSeq.NFData sh, Control.DeepSeq.NFData prob, Data.Array.Comfort.Shape.C sh) => Control.DeepSeq.NFData (Math.HiddenMarkovModel.Distribution.Trained typ sh prob)
+ Math.HiddenMarkovModel.Distribution: instance (Math.HiddenMarkovModel.Distribution.Show typ, Data.Array.Comfort.Shape.C sh, GHC.Show.Show sh, GHC.Show.Show prob, Foreign.Storable.Storable prob) => GHC.Show.Show (Math.HiddenMarkovModel.Distribution.T typ sh prob)
+ Math.HiddenMarkovModel.Distribution: instance (Math.HiddenMarkovModel.Distribution.Show typ, Data.Array.Comfort.Shape.C sh, GHC.Show.Show sh, GHC.Show.Show prob, Foreign.Storable.Storable prob) => GHC.Show.Show (Math.HiddenMarkovModel.Distribution.Trained typ sh prob)
+ Math.HiddenMarkovModel.Distribution: instance (emiSh Data.Type.Equality.~ Numeric.LAPACK.Matrix.Private.ShapeInt) => Math.HiddenMarkovModel.Distribution.FromCSV (Math.HiddenMarkovModel.Distribution.Gaussian emiSh)
+ Math.HiddenMarkovModel.Distribution: instance Control.DeepSeq.NFData emiSh => Math.HiddenMarkovModel.Distribution.NFData (Math.HiddenMarkovModel.Distribution.Gaussian emiSh)
+ Math.HiddenMarkovModel.Distribution: instance Control.DeepSeq.NFData symbol => Math.HiddenMarkovModel.Distribution.NFData (Math.HiddenMarkovModel.Distribution.Discrete symbol)
+ Math.HiddenMarkovModel.Distribution: instance Data.Array.Comfort.Shape.Indexed emiSh => Math.HiddenMarkovModel.Distribution.ToCSV (Math.HiddenMarkovModel.Distribution.Gaussian emiSh)
+ Math.HiddenMarkovModel.Distribution: instance GHC.Classes.Ord symbol => Math.HiddenMarkovModel.Distribution.EmissionProb (Math.HiddenMarkovModel.Distribution.Discrete symbol)
+ Math.HiddenMarkovModel.Distribution: instance GHC.Classes.Ord symbol => Math.HiddenMarkovModel.Distribution.Estimate (Math.HiddenMarkovModel.Distribution.Discrete symbol)
+ Math.HiddenMarkovModel.Distribution: instance GHC.Classes.Ord symbol => Math.HiddenMarkovModel.Distribution.Generate (Math.HiddenMarkovModel.Distribution.Discrete symbol)
+ Math.HiddenMarkovModel.Distribution: instance GHC.Classes.Ord symbol => Math.HiddenMarkovModel.Distribution.Info (Math.HiddenMarkovModel.Distribution.Discrete symbol)
+ Math.HiddenMarkovModel.Distribution: instance Math.HiddenMarkovModel.Distribution.CSVSymbol GHC.Types.Char
+ Math.HiddenMarkovModel.Distribution: instance Math.HiddenMarkovModel.Distribution.CSVSymbol GHC.Types.Int
+ Math.HiddenMarkovModel.Distribution: instance Math.HiddenMarkovModel.Distribution.CSVSymbol symbol => Math.HiddenMarkovModel.Distribution.FromCSV (Math.HiddenMarkovModel.Distribution.Discrete symbol)
+ Math.HiddenMarkovModel.Distribution: instance Math.HiddenMarkovModel.Distribution.CSVSymbol symbol => Math.HiddenMarkovModel.Distribution.ToCSV (Math.HiddenMarkovModel.Distribution.Discrete symbol)
+ Math.HiddenMarkovModel.Distribution: instance Math.HiddenMarkovModel.Distribution.Info (Math.HiddenMarkovModel.Distribution.Gaussian emiSh)
+ Math.HiddenMarkovModel.Distribution: instance Numeric.LAPACK.Matrix.Plain.Format.FormatArray emiSh => Math.HiddenMarkovModel.Distribution.Format (Math.HiddenMarkovModel.Distribution.Gaussian emiSh)
+ Math.HiddenMarkovModel.Distribution: mapStatesShape :: (EmissionProb typ, C sh0, C sh1) => (sh0 -> sh1) -> T typ sh0 prob -> T typ sh1 prob
+ Math.HiddenMarkovModel.Distribution: rnf :: (NFData typ, NFData sh, NFData prob, C sh) => T typ sh prob -> ()
+ Math.HiddenMarkovModel.Distribution: rnfTrained :: (NFData typ, NFData sh, NFData prob, C sh) => Trained typ sh prob -> ()
+ Math.HiddenMarkovModel.Distribution: showsPrec :: (Show typ, C sh, Show sh, Show prob, Storable prob) => Int -> T typ sh prob -> ShowS
+ Math.HiddenMarkovModel.Distribution: showsPrecTrained :: (Show typ, C sh, Show sh, Show prob, Storable prob) => Int -> Trained typ sh prob -> ShowS
+ Math.HiddenMarkovModel.Distribution: statesShapeTrained :: (Info typ, C sh) => Trained typ sh prob -> sh
+ Math.HiddenMarkovModel.Distribution: trainVector :: (Estimate typ, C sh, Eq sh, Real prob) => Emission typ prob -> Vector sh prob -> Trained typ sh prob
+ Math.HiddenMarkovModel.Distribution: type family Emission typ prob
+ Math.HiddenMarkovModel.Example.SineWave: instance GHC.Classes.Eq Math.HiddenMarkovModel.Example.SineWave.State
+ Math.HiddenMarkovModel.Example.SineWave: instance GHC.Classes.Ord Math.HiddenMarkovModel.Example.SineWave.State
+ Math.HiddenMarkovModel.Example.SineWave: instance GHC.Enum.Bounded Math.HiddenMarkovModel.Example.SineWave.State
+ Math.HiddenMarkovModel.Example.SineWave: instance GHC.Enum.Enum Math.HiddenMarkovModel.Example.SineWave.State
+ Math.HiddenMarkovModel.Named: [model] :: T typ sh ix prob -> T typ sh prob
+ Math.HiddenMarkovModel.Named: [nameFromStateMap] :: T typ sh ix prob -> Array sh String
+ Math.HiddenMarkovModel.Named: [stateFromNameMap] :: T typ sh ix prob -> Map String ix
+ Math.HiddenMarkovModel.Named: instance (Data.Array.Comfort.Shape.C sh, Foreign.Storable.Storable prob, Math.HiddenMarkovModel.Distribution.Show typ, GHC.Show.Show sh, GHC.Show.Show prob, GHC.Show.Show ix) => GHC.Show.Show (Math.HiddenMarkovModel.Named.T typ sh ix prob)
+ Math.HiddenMarkovModel.Named: instance (Math.HiddenMarkovModel.Distribution.NFData typ, Control.DeepSeq.NFData sh, Control.DeepSeq.NFData ix, Control.DeepSeq.NFData prob, Data.Array.Comfort.Shape.C sh, Foreign.Storable.Storable prob) => Control.DeepSeq.NFData (Math.HiddenMarkovModel.Named.T typ sh ix prob)
+ Math.HiddenMarkovModel.Pattern: infixl 5 `append`
+ Math.HiddenMarkovModel.Pattern: instance (Data.Array.Comfort.Shape.Indexed sh, GHC.Classes.Eq sh, Numeric.Netlib.Class.Real prob) => GHC.Base.Semigroup (Math.HiddenMarkovModel.Pattern.T sh prob)
- Math.HiddenMarkovModel: Cons :: Vector sh prob -> SquareMatrix sh prob -> distr -> T distr sh prob
+ Math.HiddenMarkovModel: Cons :: Vector sh prob -> Square sh prob -> T typ sh prob -> T typ sh prob
- Math.HiddenMarkovModel: Trained :: Vector sh prob -> SquareMatrix sh prob -> distr -> Trained distr sh prob
+ Math.HiddenMarkovModel: Trained :: Vector sh prob -> Square sh prob -> Trained typ sh prob -> Trained typ sh prob
- Math.HiddenMarkovModel: data T distr sh prob
+ Math.HiddenMarkovModel: data T typ sh prob
- Math.HiddenMarkovModel: data Trained distr sh prob
+ Math.HiddenMarkovModel: data Trained typ sh prob
- Math.HiddenMarkovModel: deviation :: (C sh, Eq sh, Real prob, Ord prob) => T distr sh prob -> T distr sh prob -> prob
+ Math.HiddenMarkovModel: deviation :: (C sh, Eq sh, Real prob) => T typ sh prob -> T typ sh prob -> prob
- Math.HiddenMarkovModel: finishTraining :: (C sh, Eq sh, Estimate tdistr distr, Probability distr ~ prob) => Trained tdistr sh prob -> T distr sh prob
+ Math.HiddenMarkovModel: finishTraining :: (Estimate typ, C sh, Eq sh, Real prob) => Trained typ sh prob -> T typ sh prob
- Math.HiddenMarkovModel: fromCSV :: (FromCSV distr, StateShape distr ~ stateSh, Indexed stateSh, Index stateSh ~ state, Real prob, Read prob) => (Int -> stateSh) -> String -> Exceptional String (T distr stateSh prob)
+ Math.HiddenMarkovModel: fromCSV :: (FromCSV typ, Indexed sh, Eq sh, Real prob, Read prob) => (Int -> sh) -> String -> Exceptional String (T typ sh prob)
- Math.HiddenMarkovModel: generate :: (RandomGen g, Ord prob, Random prob, Generate distr, StateShape distr ~ sh, Indexed sh, Index sh ~ state, Probability distr ~ prob, Emission distr ~ emission) => T distr sh prob -> g -> [emission]
+ Math.HiddenMarkovModel: generate :: (Generate typ, Indexed sh, Real prob, RandomGen g, Random prob, Emission typ prob ~ emission) => T typ sh prob -> g -> [emission]
- Math.HiddenMarkovModel: generateLabeled :: (RandomGen g, Ord prob, Random prob, Generate distr, StateShape distr ~ sh, Indexed sh, Index sh ~ state, Probability distr ~ prob, Emission distr ~ emission) => T distr sh prob -> g -> [(state, emission)]
+ Math.HiddenMarkovModel: generateLabeled :: (Generate typ, Indexed sh, Index sh ~ state, RandomGen g, Random prob, Real prob, Emission typ prob ~ emission) => T typ sh prob -> g -> [(state, emission)]
- Math.HiddenMarkovModel: logLikelihood :: (EmissionProb distr, StateShape distr ~ sh, Eq sh, Floating prob, Probability distr ~ prob, Emission distr ~ emission, Traversable f) => T distr sh prob -> T f emission -> prob
+ Math.HiddenMarkovModel: logLikelihood :: (EmissionProb typ, C sh, Eq sh, Floating prob, Real prob, Emission typ prob ~ emission, Traversable f) => T typ sh prob -> T f emission -> prob
- Math.HiddenMarkovModel: mergeTrained :: (C sh, Eq sh, Estimate tdistr distr, Probability distr ~ prob) => Trained tdistr sh prob -> Trained tdistr sh prob -> Trained tdistr sh prob
+ Math.HiddenMarkovModel: mergeTrained :: (Estimate typ, C sh, Eq sh, Real prob) => Trained typ sh prob -> Trained typ sh prob -> Trained typ sh prob
- Math.HiddenMarkovModel: probabilitySequence :: (Traversable f, EmissionProb distr, StateShape distr ~ sh, Indexed sh, Index sh ~ state, Probability distr ~ prob, Emission distr ~ emission) => T distr sh prob -> f (state, emission) -> f prob
+ Math.HiddenMarkovModel: probabilitySequence :: (EmissionProb typ, Indexed sh, Index sh ~ state, Real prob, Emission typ prob ~ emission, Traversable f) => T typ sh prob -> f (state, emission) -> f prob
- Math.HiddenMarkovModel: reveal :: (EmissionProb distr, StateShape distr ~ sh, InvIndexed sh, Eq sh, Index sh ~ state, Probability distr ~ prob, Emission distr ~ emission, Traversable f, Reverse f) => T distr sh prob -> T f emission -> T f state
+ Math.HiddenMarkovModel: reveal :: (EmissionProb typ, InvIndexed sh, Eq sh, Index sh ~ state, Emission typ prob ~ emission, Real prob, Traversable f) => T typ sh prob -> T f emission -> T f state
- Math.HiddenMarkovModel: toCSV :: (ToCSV distr, Indexed sh, Real prob, Show prob) => T distr sh prob -> String
+ Math.HiddenMarkovModel: toCSV :: (ToCSV typ, Indexed sh, Real prob, Show prob) => T typ sh prob -> String
- Math.HiddenMarkovModel: trainMany :: (C sh, Eq sh, Estimate tdistr distr, Probability distr ~ prob, Foldable f) => (trainingData -> Trained tdistr sh prob) -> T f trainingData -> T distr sh prob
+ Math.HiddenMarkovModel: trainMany :: (Estimate typ, C sh, Eq sh, Real prob, Foldable f) => (trainingData -> Trained typ sh prob) -> T f trainingData -> T typ sh prob
- Math.HiddenMarkovModel: trainSupervised :: (StateShape distr ~ sh, Index sh ~ state, Estimate tdistr distr, Probability distr ~ prob, Emission distr ~ emission) => sh -> T [] (state, emission) -> Trained tdistr sh prob
+ Math.HiddenMarkovModel: trainSupervised :: (Estimate typ, Indexed sh, Index sh ~ state, Real prob, Emission typ prob ~ emission) => sh -> T [] (state, emission) -> Trained typ sh prob
- Math.HiddenMarkovModel: trainUnsupervised :: (Estimate tdistr distr, StateShape distr ~ sh, Eq sh, Probability distr ~ prob, Emission distr ~ emission) => T distr sh prob -> T [] emission -> Trained tdistr sh prob
+ Math.HiddenMarkovModel: trainUnsupervised :: (Estimate typ, C sh, Eq sh, Real prob, Emission typ prob ~ emission) => T typ sh prob -> T [] emission -> Trained typ sh prob
- Math.HiddenMarkovModel: type Discrete symbol sh prob = T (Discrete symbol sh prob) sh prob
+ Math.HiddenMarkovModel: type Discrete symbol sh prob = T (Discrete symbol) sh prob
- Math.HiddenMarkovModel: type DiscreteTrained symbol sh prob = Trained (DiscreteTrained symbol sh prob) sh prob
+ Math.HiddenMarkovModel: type DiscreteTrained symbol sh prob = Trained (Discrete symbol) sh prob
- Math.HiddenMarkovModel: type Gaussian emiSh stateSh a = T (Gaussian emiSh stateSh a) stateSh a
+ Math.HiddenMarkovModel: type Gaussian emiSh stateSh a = T (Gaussian emiSh) stateSh a
- Math.HiddenMarkovModel: type GaussianTrained emiSh stateSh a = Trained (GaussianTrained emiSh stateSh a) stateSh a
+ Math.HiddenMarkovModel: type GaussianTrained emiSh stateSh a = Trained (Gaussian emiSh) stateSh a
- Math.HiddenMarkovModel: uniform :: (Info distr, StateShape distr ~ sh, C sh, Probability distr ~ prob) => distr -> T distr sh prob
+ Math.HiddenMarkovModel: uniform :: (Info typ, C sh, Real prob) => T typ sh prob -> T typ sh prob
- Math.HiddenMarkovModel.Distribution: accumulateEmissions :: (Estimate tdistr distr, Probability distr ~ prob, StateShape distr ~ sh) => Array sh [(Emission distr, prob)] -> tdistr
+ Math.HiddenMarkovModel.Distribution: accumulateEmissions :: (Estimate typ, Indexed sh, Real prob, Index sh ~ state) => sh -> T [] (state, Emission typ prob) -> Trained typ sh prob
- Math.HiddenMarkovModel.Distribution: class Ord symbol => CSVSymbol symbol
+ Math.HiddenMarkovModel.Distribution: class (Ord symbol) => CSVSymbol symbol
- Math.HiddenMarkovModel.Distribution: class (Indexed (StateShape distr), Real (Probability distr)) => EmissionProb distr where emissionStateProb distr e s = emissionProb distr e ! s
+ Math.HiddenMarkovModel.Distribution: class EmissionProb typ
- Math.HiddenMarkovModel.Distribution: class (Distribution tdistr ~ distr, Trained distr ~ tdistr, EmissionProb distr) => Estimate tdistr distr where type family Distribution tdistr type family Trained distr
+ Math.HiddenMarkovModel.Distribution: class (EmissionProb typ) => Estimate typ
- Math.HiddenMarkovModel.Distribution: class FromCSV distr
+ Math.HiddenMarkovModel.Distribution: class FromCSV typ
- Math.HiddenMarkovModel.Distribution: class Real (Probability distr) => Generate distr
+ Math.HiddenMarkovModel.Distribution: class Generate typ
- Math.HiddenMarkovModel.Distribution: class Real (Probability distr) => Info distr
+ Math.HiddenMarkovModel.Distribution: class Info typ
- Math.HiddenMarkovModel.Distribution: class ToCSV distr
+ Math.HiddenMarkovModel.Distribution: class ToCSV typ
- Math.HiddenMarkovModel.Distribution: combine :: Estimate tdistr distr => tdistr -> tdistr -> tdistr
+ Math.HiddenMarkovModel.Distribution: combine :: (Estimate typ, C sh, Eq sh, Real prob) => Trained typ sh prob -> Trained typ sh prob -> Trained typ sh prob
- Math.HiddenMarkovModel.Distribution: emissionProb :: EmissionProb distr => distr -> Emission distr -> Vector (StateShape distr) (Probability distr)
+ Math.HiddenMarkovModel.Distribution: emissionProb :: (EmissionProb typ, C sh, Real prob) => T typ sh prob -> Emission typ prob -> Vector sh prob
- Math.HiddenMarkovModel.Distribution: emissionStateProb :: EmissionProb distr => distr -> Emission distr -> Index (StateShape distr) -> Probability distr
+ Math.HiddenMarkovModel.Distribution: emissionStateProb :: (EmissionProb typ, Indexed sh, Real prob) => T typ sh prob -> Emission typ prob -> Index sh -> prob
- Math.HiddenMarkovModel.Distribution: gaussian :: (C emiSh, C stateSh, Real prob) => Array stateSh (Vector emiSh prob, HermitianMatrix emiSh prob) -> Gaussian emiSh stateSh prob
+ Math.HiddenMarkovModel.Distribution: gaussian :: (C emiSh, C stateSh, Real prob) => Array stateSh (Vector emiSh prob, Hermitian emiSh prob) -> T (Gaussian emiSh) stateSh prob
- Math.HiddenMarkovModel.Distribution: generate :: (Generate distr, RandomGen g, Emission distr ~ emission, StateShape distr ~ sh) => distr -> Index sh -> State g emission
+ Math.HiddenMarkovModel.Distribution: generate :: (Generate typ, Indexed sh, Real prob, Random prob, RandomGen g) => T typ sh prob -> Index sh -> State g (Emission typ prob)
- Math.HiddenMarkovModel.Distribution: normalize :: Estimate tdistr distr => tdistr -> distr
+ Math.HiddenMarkovModel.Distribution: normalize :: (Estimate typ, C sh, Eq sh, Real prob) => Trained typ sh prob -> T typ sh prob
- Math.HiddenMarkovModel.Distribution: parseCells :: FromCSV distr => StateShape distr -> CSVParser distr
+ Math.HiddenMarkovModel.Distribution: parseCells :: (FromCSV typ, C sh, Eq sh, Real prob, Read prob) => sh -> CSVParser (T typ sh prob)
- Math.HiddenMarkovModel.Distribution: statesShape :: Info distr => distr -> StateShape distr
+ Math.HiddenMarkovModel.Distribution: statesShape :: (Info typ, C sh) => T typ sh prob -> sh
- Math.HiddenMarkovModel.Distribution: toCells :: ToCSV distr => distr -> [[String]]
+ Math.HiddenMarkovModel.Distribution: toCells :: (ToCSV typ, C sh, Real prob, Show prob) => T typ sh prob -> [[String]]
- Math.HiddenMarkovModel.Named: Cons :: T distr sh prob -> Array sh String -> Map String ix -> T distr sh ix prob
+ Math.HiddenMarkovModel.Named: Cons :: T typ sh prob -> Array sh String -> Map String ix -> T typ sh ix prob
- Math.HiddenMarkovModel.Named: data T distr sh ix prob
+ Math.HiddenMarkovModel.Named: data T typ sh ix prob
- Math.HiddenMarkovModel.Named: fromCSV :: (FromCSV distr, StateShape distr ~ stateSh, Indexed stateSh, Index stateSh ~ state, Real prob, Read prob) => (Int -> stateSh) -> String -> Exceptional String (T distr stateSh state prob)
+ Math.HiddenMarkovModel.Named: fromCSV :: (FromCSV typ, Indexed stateSh, Eq stateSh, Real prob, Read prob) => (Int -> stateSh) -> String -> Exceptional String (Simple typ stateSh prob)
- Math.HiddenMarkovModel.Named: fromModelAndNames :: (Indexed sh, Index sh ~ state) => T distr sh prob -> [String] -> T distr sh state prob
+ Math.HiddenMarkovModel.Named: fromModelAndNames :: Indexed sh => T typ sh prob -> [String] -> Simple typ sh prob
- Math.HiddenMarkovModel.Named: toCSV :: (ToCSV distr, Indexed sh, Real prob, Show prob) => T distr sh ix prob -> String
+ Math.HiddenMarkovModel.Named: toCSV :: (ToCSV typ, Indexed sh, Real prob, Show prob) => Simple typ sh prob -> String
- Math.HiddenMarkovModel.Named: type Discrete symbol stateSh prob = T (Discrete symbol stateSh prob) stateSh (Index stateSh) prob
+ Math.HiddenMarkovModel.Named: type Discrete symbol stateSh prob = Simple (Discrete symbol) stateSh prob
- Math.HiddenMarkovModel.Named: type Gaussian emiSh stateSh a = T (Gaussian emiSh stateSh a) stateSh (Index stateSh) a
+ Math.HiddenMarkovModel.Named: type Gaussian emiSh stateSh a = Simple (Gaussian emiSh) stateSh a
- Math.HiddenMarkovModel.Pattern: finish :: (Indexed sh, Real prob) => sh -> tdistr -> T sh prob -> Trained tdistr sh prob
+ Math.HiddenMarkovModel.Pattern: finish :: (Info typ, Indexed sh, Real prob) => Trained typ sh prob -> T sh prob -> Trained typ sh prob
Files
- hmm-lapack.cabal +6/−7
- src/Math/HiddenMarkovModel.hs +43/−58
- src/Math/HiddenMarkovModel/CSV.hs +9/−9
- src/Math/HiddenMarkovModel/Distribution.hs +320/−258
- src/Math/HiddenMarkovModel/Example/CirclePrivate.hs +1/−1
- src/Math/HiddenMarkovModel/Example/SineWave.hs +1/−1
- src/Math/HiddenMarkovModel/Example/TrafficLightPrivate.hs +5/−11
- src/Math/HiddenMarkovModel/Named.hs +15/−18
- src/Math/HiddenMarkovModel/Normalized.hs +33/−51
- src/Math/HiddenMarkovModel/Pattern.hs +24/−22
- src/Math/HiddenMarkovModel/Private.hs +107/−111
- src/Math/HiddenMarkovModel/Test.hs +17/−10
- src/Math/HiddenMarkovModel/Utility.hs +14/−7
hmm-lapack.cabal view
@@ -1,5 +1,5 @@ Name: hmm-lapack-Version: 0.3.0.3+Version: 0.4 Synopsis: Hidden Markov Models using LAPACK primitives Description: Hidden Markov Models implemented using LAPACK data types and operations.@@ -41,7 +41,7 @@ Changes.md Source-Repository this- Tag: 0.3.0.3+ Tag: 0.4 Type: darcs Location: http://hub.darcs.net/thielema/hmm-lapack @@ -67,19 +67,18 @@ Math.HiddenMarkovModel.Utility Math.HiddenMarkovModel.CSV Build-Depends:- lapack >=0.2.2 && <0.3,+ lapack >=0.3 && <0.4, fixed-length >=0.2.1 && <0.3, tfp >=1.0 && <1.1, netlib-ffi >=0.1.1 && <0.2,- comfort-array >=0.2 && <0.4,+ comfort-array >=0.4 && <0.5, QuickCheck >=2.5 && <3, explicit-exception >=0.1.7 && <0.2,- boxes >=0.1.5 && <0.2, lazy-csv >=0.5 && <0.6, random >=1.0 && <1.2, transformers >= 0.2 && <0.6,- non-empty >=0.2.1 && <0.4,- semigroups >=0.17 && <0.19,+ non-empty >=0.3.2 && <0.4,+ semigroups >=0.17 && <1.0, containers >=0.4.2 && <0.7, utility-ht >=0.0.12 && <0.1, deepseq >=1.3 && <1.5,
src/Math/HiddenMarkovModel.hs view
@@ -26,17 +26,18 @@ import Math.HiddenMarkovModel.Private (T(..), Trained(..), mergeTrained, toCells, parseCSV) import Math.HiddenMarkovModel.Utility- (SquareMatrix, squareConstant, distance,+ (squareConstant, distance, matrixDistance, randomItemProp, normalizeProb, attachOnes) +import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix import qualified Numeric.LAPACK.Matrix as Matrix import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix ((#!)) import qualified Numeric.Netlib.Class as Class import qualified Data.Array.Comfort.Storable as StorableArray import qualified Data.Array.Comfort.Shape as Shape-import qualified Data.Array.Comfort.Boxed as Array import qualified Text.CSV.Lazy.String as CSV @@ -53,12 +54,12 @@ type DiscreteTrained symbol sh prob =- Trained (Distr.DiscreteTrained symbol sh prob) sh prob-type Discrete symbol sh prob = T (Distr.Discrete symbol sh prob) sh prob+ Trained (Distr.Discrete symbol) sh prob+type Discrete symbol sh prob = T (Distr.Discrete symbol) sh prob type GaussianTrained emiSh stateSh a =- Trained (Distr.GaussianTrained emiSh stateSh a) stateSh a-type Gaussian emiSh stateSh a = T (Distr.Gaussian emiSh stateSh a) stateSh a+ Trained (Distr.Gaussian emiSh) stateSh a+type Gaussian emiSh stateSh a = T (Distr.Gaussian emiSh) stateSh a {- |@@ -68,9 +69,8 @@ You can use this as a starting point for 'Normalized.trainUnsupervised'. -} uniform ::- (Distr.Info distr, Distr.StateShape distr ~ sh, Shape.C sh,- Distr.Probability distr ~ prob) =>- distr -> T distr sh prob+ (Distr.Info typ, Shape.C sh, Class.Real prob) =>+ Distr.T typ sh prob -> T typ sh prob uniform distr = let sh = Distr.statesShape distr c = recip $ fromIntegral $ Shape.size sh@@ -82,31 +82,29 @@ probabilitySequence ::- (Traversable f, Distr.EmissionProb distr,- Distr.StateShape distr ~ sh, Shape.Indexed sh, Shape.Index sh ~ state,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>- T distr sh prob -> f (state, emission) -> f prob+ (Distr.EmissionProb typ, Shape.Indexed sh, Shape.Index sh ~ state,+ Class.Real prob, Distr.Emission typ prob ~ emission, Traversable f) =>+ T typ sh prob -> f (state, emission) -> f prob probabilitySequence hmm = snd . mapAccumL (\index (s, e) ->- ((transition hmm StorableArray.!) . flip (,) s,+ ((transition hmm #!) . flip (,) s, index s * Distr.emissionStateProb (distribution hmm) e s)) (initial hmm StorableArray.!) generate ::- (Rnd.RandomGen g, Ord prob, Rnd.Random prob, Distr.Generate distr,- Distr.StateShape distr ~ sh, Shape.Indexed sh, Shape.Index sh ~ state,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>- T distr sh prob -> g -> [emission]+ (Distr.Generate typ, Shape.Indexed sh, Class.Real prob,+ Rnd.RandomGen g, Rnd.Random prob, Distr.Emission typ prob ~ emission) =>+ T typ sh prob -> g -> [emission] generate hmm = map snd . generateLabeled hmm generateLabeled ::- (Rnd.RandomGen g, Ord prob, Rnd.Random prob, Distr.Generate distr,- Distr.StateShape distr ~ sh, Shape.Indexed sh, Shape.Index sh ~ state,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>- T distr sh prob -> g -> [(state, emission)]+ (Distr.Generate typ, Shape.Indexed sh, Shape.Index sh ~ state,+ Rnd.RandomGen g, Rnd.Random prob,+ Class.Real prob, Distr.Emission typ prob ~ emission) =>+ T typ sh prob -> g -> [(state, emission)] generateLabeled hmm = MS.evalState $ flip MS.evalStateT (initial hmm) $@@ -123,31 +121,24 @@ Contribute a manually labeled emission sequence to a HMM training. -} trainSupervised ::- (Distr.StateShape distr ~ sh, Shape.Index sh ~ state,- Distr.Estimate tdistr distr,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>- sh -> NonEmpty.T [] (state, emission) -> Trained tdistr sh prob+ (Distr.Estimate typ, Shape.Indexed sh, Shape.Index sh ~ state,+ Class.Real prob, Distr.Emission typ prob ~ emission) =>+ sh -> NonEmpty.T [] (state, emission) -> Trained typ sh prob trainSupervised sh xs = let getState (s, _x) = s in Trained {- trainedInitial =- StorableArray.fromAssociations sh 0- [(getState (NonEmpty.head xs), 1)],+ trainedInitial = Vector.unit sh $ getState $ NonEmpty.head xs, trainedTransition =- Matrix.transpose $- StorableArray.accumulate (+) (squareConstant sh 0) $+ Matrix.transpose $ ArrMatrix.fromVector $+ StorableArray.accumulate (+)+ (ArrMatrix.toVector $ squareConstant sh 0) $ attachOnes $ NonEmpty.mapAdjacent (,) $ fmap getState xs,- trainedDistribution =- Distr.accumulateEmissions $ Array.map attachOnes $- Array.accumulate (flip (:))- (Array.fromList sh $ replicate (Shape.size sh) [])- (NonEmpty.flatten xs)+ trainedDistribution = Distr.accumulateEmissions sh xs } finishTraining ::- (Shape.C sh, Eq sh,- Distr.Estimate tdistr distr, Distr.Probability distr ~ prob) =>- Trained tdistr sh prob -> T distr sh prob+ (Distr.Estimate typ, Shape.C sh, Eq sh, Class.Real prob) =>+ Trained typ sh prob -> T typ sh prob finishTraining hmm = Cons { initial = normalizeProb $ trainedInitial hmm,@@ -156,18 +147,15 @@ } normalizeProbColumns ::- (Shape.C sh, Eq sh, Class.Real a) => SquareMatrix sh a -> SquareMatrix sh a+ (Shape.C sh, Eq sh, Class.Real a) => Matrix.Square sh a -> Matrix.Square sh a normalizeProbColumns m = Matrix.scaleColumns (StorableArray.map recip (Matrix.columnSums m)) m trainMany ::- (Shape.C sh, Eq sh,- Distr.Estimate tdistr distr, Distr.Probability distr ~ prob,- Foldable f) =>- (trainingData -> Trained tdistr sh prob) ->- NonEmpty.T f trainingData -> T distr sh prob-trainMany train =- finishTraining . NonEmpty.foldl1Map mergeTrained train+ (Distr.Estimate typ, Shape.C sh, Eq sh, Class.Real prob, Foldable f) =>+ (trainingData -> Trained typ sh prob) ->+ NonEmpty.T f trainingData -> T typ sh prob+trainMany train = finishTraining . NonEmpty.foldl1Map mergeTrained train @@ -181,25 +169,22 @@ should suffice for defining an abort criterion. -} deviation ::- (Shape.C sh, Eq sh, Class.Real prob, Ord prob) =>- T distr sh prob -> T distr sh prob -> prob+ (Shape.C sh, Eq sh, Class.Real prob) =>+ T typ sh prob -> T typ sh prob -> prob deviation hmm0 hmm1 = distance (initial hmm0) (initial hmm1) `max`- distance (transition hmm0) (transition hmm1)+ matrixDistance (transition hmm0) (transition hmm1) toCSV ::- (Distr.ToCSV distr, Shape.Indexed sh, Class.Real prob, Show prob) =>- T distr sh prob -> String+ (Distr.ToCSV typ, Shape.Indexed sh, Class.Real prob, Show prob) =>+ T typ sh prob -> String toCSV hmm =- CSV.ppCSVTable $ snd $ CSV.toCSVTable $ HMMCSV.padTable "" $- toCells hmm+ CSV.ppCSVTable $ snd $ CSV.toCSVTable $ HMMCSV.padTable "" $ toCells hmm fromCSV ::- (Distr.FromCSV distr, Distr.StateShape distr ~ stateSh,- Shape.Indexed stateSh, Shape.Index stateSh ~ state,- Class.Real prob, Read prob) =>- (Int -> stateSh) -> String -> ME.Exceptional String (T distr stateSh prob)+ (Distr.FromCSV typ, Shape.Indexed sh, Eq sh, Class.Real prob, Read prob) =>+ (Int -> sh) -> String -> ME.Exceptional String (T typ sh prob) fromCSV makeShape = MS.evalStateT (parseCSV makeShape) . map HMMCSV.fixShortRow . CSV.parseCSV
src/Math/HiddenMarkovModel/CSV.hs view
@@ -1,16 +1,15 @@ module Math.HiddenMarkovModel.CSV where -import Math.HiddenMarkovModel.Utility (SquareMatrix, vectorDim)+import Math.HiddenMarkovModel.Utility (vectorDim) import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape import qualified Numeric.LAPACK.Matrix as Matrix import qualified Numeric.LAPACK.Vector as Vector-import Numeric.LAPACK.Matrix (ZeroInt)+import Numeric.LAPACK.Matrix (ShapeInt) import Numeric.LAPACK.Vector (Vector) import qualified Numeric.Netlib.Class as Class -import qualified Data.Array.Comfort.Storable as ComfortArray import qualified Data.Array.Comfort.Shape as Shape import qualified Text.CSV.Lazy.String as CSV@@ -32,7 +31,7 @@ cellsFromVector = map show . Vector.toList cellsFromSquare ::- (Shape.Indexed sh, Show a, Class.Real a) => SquareMatrix sh a -> [[String]]+ (Shape.Indexed sh, Show a, Class.Real a) => Matrix.Square sh a -> [[String]] cellsFromSquare = map (map show . Vector.toList) . Matrix.toRows padTable :: a -> [[a]] -> [[a]]@@ -110,20 +109,21 @@ parseVectorCells :: (Read a, Class.Real a) =>- CSVParser (Vector ZeroInt a)+ CSVParser (Vector ShapeInt a) parseVectorCells = parseVectorFields =<< getRow +-- ToDo: Maybe check row consistency already here? parseVectorFields :: (Read a, Class.Real a) =>- CSV.CSVRow -> CSVParser (Vector ZeroInt a)+ CSV.CSVRow -> CSVParser (Vector ShapeInt a) parseVectorFields = MT.lift . fmap Vector.autoFromList . mapM parseNumberCell . Rev.dropWhile (null . CSV.csvFieldContent) parseNonEmptyVectorCells :: (Read a, Class.Real a) =>- CSVParser (Vector ZeroInt a)+ CSVParser (Vector ShapeInt a) parseNonEmptyVectorCells = do v <- parseVectorCells assert (vectorDim v > 0) "no data for vector"@@ -143,14 +143,14 @@ parseSquareMatrixCells :: (Shape.C sh, Read a, Class.Real a) =>- sh -> CSVParser (SquareMatrix sh a)+ sh -> CSVParser (Matrix.Square sh a) parseSquareMatrixCells sh = do let n = Shape.size sh rows <- replicateM n parseVectorCells assert (not $ null rows) "no rows" assert (all ((n==) . vectorDim) rows) "inconsistent matrix dimensions" return $- ComfortArray.reshape (MatrixShape.square MatrixShape.RowMajor sh) $+ Matrix.reshape (MatrixShape.square MatrixShape.RowMajor sh) $ Matrix.fromRows (Shape.ZeroBased n) rows parseStringList :: CSV.CSVRow -> CSVParser [String]
src/Math/HiddenMarkovModel/Distribution.hs view
@@ -1,28 +1,34 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE EmptyDataDecls #-} module Math.HiddenMarkovModel.Distribution (- Emission, Probability, StateShape,- Info(..), Generate(..), EmissionProb(..), Estimate(..),+ T(..), Trained(..), Emission,+ Show(..), NFData(..), Format(..),+ Info(..), Generate(..), EmissionProb(..),+ Estimate(..), accumulateEmissionVectors, - Discrete(..), DiscreteTrained(..),- Gaussian(..), GaussianTrained(..), gaussian,+ Discrete, discreteFromList,+ Gaussian, gaussian, gaussianTrained, ToCSV(..), FromCSV(..), HMMCSV.CSVParser, CSVSymbol(..), ) where import qualified Math.HiddenMarkovModel.CSV as HMMCSV-import Math.HiddenMarkovModel.Utility (SquareMatrix, randomItemProp, vectorDim)+import Math.HiddenMarkovModel.Utility (randomItemProp, vectorDim) import qualified Numeric.LAPACK.Matrix.HermitianPositiveDefinite as HermitianPD import qualified Numeric.LAPACK.Matrix.Hermitian as Hermitian import qualified Numeric.LAPACK.Matrix.Triangular as Triangular import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix import qualified Numeric.LAPACK.Matrix as Matrix import qualified Numeric.LAPACK.Vector as Vector-import Numeric.LAPACK.Matrix ((<#))+import qualified Numeric.LAPACK.Format as Format+import qualified Numeric.LAPACK.Output as Output+import Numeric.LAPACK.Matrix ((-*#), (-/#), (#/\), (|*-), (#!)) import Numeric.LAPACK.Vector (Vector)-import Numeric.LAPACK.Format (FormatArray, Format(format))+import Numeric.LAPACK.Format (FormatArray)+import Numeric.LAPACK.Output (Output) import qualified Numeric.Netlib.Class as Class import Foreign.Storable (Storable)@@ -31,334 +37,397 @@ import qualified Data.Array.Comfort.Shape as Shape import qualified Data.Array.Comfort.Boxed as Array import Data.Array.Comfort.Boxed (Array, (!))+import Data.Array.Comfort.Shape ((:+:)((:+:))) import qualified System.Random as Rnd import qualified Text.CSV.Lazy.String as CSV-import qualified Text.PrettyPrint.Boxes as TextBox-import Text.PrettyPrint.Boxes ((<>), (<+>)) import Text.Read.HT (maybeRead) import Text.Printf (printf) import qualified Control.Monad.Exception.Synchronous as ME import qualified Control.Monad.Trans.Class as MT import qualified Control.Monad.Trans.State as MS-import Control.DeepSeq (NFData, rnf)+import qualified Control.DeepSeq as DeepSeq import Control.Monad (liftM2)-import Control.Applicative (liftA2, (<|>))+import Control.Applicative (liftA2) +import qualified Data.NonEmpty.Map as NonEmptyMap import qualified Data.NonEmpty as NonEmpty-import qualified Data.Foldable as Fold+import qualified Data.Semigroup as Sg import qualified Data.Map as Map-import qualified Data.Set as Set import qualified Data.List.HT as ListHT import qualified Data.List as List import Data.Functor.Identity (Identity(Identity), runIdentity)-import Data.Foldable (Foldable, foldMap)-import Data.Tuple.HT (mapFst, fst3, swap)-import Data.Monoid (Endo(Endo, appEndo))-import Data.Map (Map)-import Data.Maybe (fromMaybe, listToMaybe)+import Data.Tuple.HT (snd3)+import Data.Set (Set)+import Data.Maybe (listToMaybe) -import Prelude ()-import Prelude2010+import qualified Prelude as P+import Prelude2010 hiding (Show, showsPrec) -type HermitianMatrix sh = Hermitian.Hermitian sh-type UpperTriangular sh = Triangular.Upper sh +data family T typ sh prob+data family Trained typ sh prob -type family Probability distr-type family Emission distr-type family StateShape distr+type family Emission typ prob -class (Class.Real (Probability distr)) => Info distr where- statesShape :: distr -> StateShape distr+class Show typ where+ showsPrec ::+ (Shape.C sh, P.Show sh, P.Show prob, Storable prob) =>+ Int -> T typ sh prob -> ShowS+ showsPrecTrained ::+ (Shape.C sh, P.Show sh, P.Show prob, Storable prob) =>+ Int -> Trained typ sh prob -> ShowS -class (Class.Real (Probability distr)) => Generate distr where+instance+ (Show typ, Shape.C sh, P.Show sh, P.Show prob, Storable prob) =>+ P.Show (T typ sh prob) where+ showsPrec = showsPrec++instance+ (Show typ, Shape.C sh, P.Show sh, P.Show prob, Storable prob) =>+ P.Show (Trained typ sh prob) where+ showsPrec = showsPrecTrained+++class NFData typ where+ rnf ::+ (DeepSeq.NFData sh, DeepSeq.NFData prob, Shape.C sh) =>+ T typ sh prob -> ()+ rnfTrained ::+ (DeepSeq.NFData sh, DeepSeq.NFData prob, Shape.C sh) =>+ Trained typ sh prob -> ()++instance+ (NFData typ, DeepSeq.NFData sh, DeepSeq.NFData prob, Shape.C sh) =>+ DeepSeq.NFData (T typ sh prob) where+ rnf = rnf++instance+ (NFData typ, DeepSeq.NFData sh, DeepSeq.NFData prob, Shape.C sh) =>+ DeepSeq.NFData (Trained typ sh prob) where+ rnf = rnfTrained+++class Format typ where+ format ::+ (Shape.C sh, Output out, Class.Real prob) =>+ String -> T typ sh prob -> out++instance+ (Format typ, Shape.C sh, Class.Real prob) =>+ Format.Format (T typ sh prob) where+ format = format++++class Info typ where+ statesShape :: (Shape.C sh) => T typ sh prob -> sh+ statesShapeTrained :: (Shape.C sh) => Trained typ sh prob -> sh++class Generate typ where generate ::- (Rnd.RandomGen g, Emission distr ~ emission, StateShape distr ~ sh) =>- distr -> Shape.Index sh -> MS.State g emission+ (Shape.Indexed sh, Class.Real prob, Rnd.Random prob, Rnd.RandomGen g) =>+ T typ sh prob -> Shape.Index sh -> MS.State g (Emission typ prob) -class- (Shape.Indexed (StateShape distr), Class.Real (Probability distr)) =>- EmissionProb distr where+class EmissionProb typ where+ mapStatesShape ::+ (Shape.C sh0, Shape.C sh1) =>+ (sh0 -> sh1) -> T typ sh0 prob -> T typ sh1 prob {- This function could be implemented generically in terms of emissionStateProb but that would require an Info constraint. -} emissionProb ::- distr -> Emission distr -> Vector (StateShape distr) (Probability distr)+ (Shape.C sh, Class.Real prob) =>+ T typ sh prob -> Emission typ prob -> Vector sh prob emissionStateProb ::- distr -> Emission distr -> Shape.Index (StateShape distr) -> Probability distr+ (Shape.Indexed sh, Class.Real prob) =>+ T typ sh prob -> Emission typ prob -> Shape.Index sh -> prob emissionStateProb distr e s = emissionProb distr e StorableArray.! s -class- (Distribution tdistr ~ distr, Trained distr ~ tdistr, EmissionProb distr) =>- Estimate tdistr distr where- type Distribution tdistr- type Trained distr+class (EmissionProb typ) => Estimate typ where accumulateEmissions ::- (Probability distr ~ prob, StateShape distr ~ sh) =>- Array sh [(Emission distr, prob)] -> tdistr- -- could as well be in Semigroup class- combine :: tdistr -> tdistr -> tdistr- normalize :: tdistr -> distr+ (Shape.Indexed sh, Class.Real prob, Shape.Index sh ~ state) =>+ sh -> NonEmpty.T [] (state, Emission typ prob) -> Trained typ sh prob+ trainVector ::+ (Shape.C sh, Eq sh, Class.Real prob) =>+ Emission typ prob -> Vector sh prob -> Trained typ sh prob+ combine ::+ (Shape.C sh, Eq sh, Class.Real prob) =>+ Trained typ sh prob -> Trained typ sh prob -> Trained typ sh prob+ normalize ::+ (Shape.C sh, Eq sh, Class.Real prob) =>+ Trained typ sh prob -> T typ sh prob +accumulateEmissionVectors ::+ (Estimate typ, Shape.C sh, Eq sh, Class.Real prob) =>+ NonEmpty.T [] (Emission typ prob, Vector sh prob) -> Trained typ sh prob+accumulateEmissionVectors = NonEmpty.foldl1Map combine (uncurry trainVector) -newtype Discrete symbol sh prob = Discrete (Map symbol (Vector sh prob))- deriving (Show)+instance+ (Estimate typ, Shape.C sh, Eq sh, Class.Real prob) =>+ Sg.Semigroup (Trained typ sh prob) where+ (<>) = combine -newtype- DiscreteTrained symbol sh prob =- DiscreteTrained (Map symbol (Vector sh prob))- deriving (Show) -type instance Probability (Discrete symbol sh prob) = prob-type instance Emission (Discrete symbol sh prob) = symbol-type instance StateShape (Discrete symbol sh prob) = sh+data Discrete symbol +newtype instance T (Discrete symbol) sh prob =+ Discrete (Matrix.General (Set symbol) sh prob) -instance- (NFData sh, NFData prob, NFData symbol) =>- NFData (Discrete symbol sh prob) where- rnf (Discrete m) = rnf m+newtype instance Trained (Discrete symbol) sh prob =+ DiscreteTrained (NonEmptyMap.T symbol (Vector sh prob)) -instance- (NFData sh, NFData prob, NFData symbol) =>- NFData (DiscreteTrained symbol sh prob) where- rnf (DiscreteTrained m) = rnf m+type instance Emission (Discrete symbol) prob = symbol -instance- (FormatArray sh, Class.Real prob, Format symbol) =>- Format (Discrete symbol sh prob) where++instance (P.Show symbol, Ord symbol) => Show (Discrete symbol) where+ showsPrec prec (Discrete m) = P.showsPrec prec m+ showsPrecTrained prec (DiscreteTrained m) = P.showsPrec prec m++instance (DeepSeq.NFData symbol) => NFData (Discrete symbol) where+ rnf (Discrete m) = DeepSeq.rnf m+ rnfTrained (DiscreteTrained m) = DeepSeq.rnf m++instance (P.Show symbol, Ord symbol) => Format (Discrete symbol) where format fmt (Discrete m) =- TextBox.vsep 1 TextBox.left $- map (\(sym,v) -> format fmt sym <> TextBox.char ':' <+> format fmt v) $- Map.toAscList m+ Output.formatAligned $+ map (\(sym,v) ->+ map (Identity . Output.text) $+ (show sym ++ ":") : map (printFmt fmt) (Vector.toList v)) $+ Array.toAssociations $ Matrix.toRowArray m -instance- (Shape.C sh, Class.Real prob, Ord symbol) =>- Info (Discrete symbol sh prob) where- statesShape (Discrete m) = StorableArray.shape $ snd $ Map.findMin m+-- cf. Data.Bifunctor.Flip+newtype Flip f b a = Flip {getFlip :: f a b} -instance- (Shape.Indexed sh, Class.Real prob, Ord symbol, Ord prob, Rnd.Random prob) =>- Generate (Discrete symbol sh prob) where- generate (Discrete m) state =- randomItemProp $ Map.toAscList $ fmap (StorableArray.! state) m+printFmt :: (Class.Real a) => String -> a -> String+printFmt fmt =+ getFlip $ Class.switchReal (Flip $ printf fmt) (Flip $ printf fmt) -instance- (Shape.Indexed sh, Class.Real prob, Ord symbol) =>- EmissionProb (Discrete symbol sh prob) where- emissionProb (Discrete m) =- mapLookup "emitDiscrete: unknown emission symbol" m+instance (Ord symbol) => Info (Discrete symbol) where+ statesShape (Discrete m) = Matrix.width m+ statesShapeTrained (DiscreteTrained m) = discreteStateShape m -instance- (Shape.Indexed sh, Eq sh, Class.Real prob, Ord symbol) =>- Estimate (DiscreteTrained symbol sh prob) (Discrete symbol sh prob) where- type Distribution (DiscreteTrained symbol sh prob) = Discrete symbol sh prob- type Trained (Discrete symbol sh prob) = DiscreteTrained symbol sh prob- accumulateEmissions grouped =- let set = Set.toAscList $ foldMap (Set.fromList . map fst) grouped- emi = Map.fromAscList $ zip set [0..]- in DiscreteTrained $ Map.fromAscList $ zip set $- transposeVectorList $- Array.map- (StorableArray.accumulate (+)- (Vector.constant (Shape.ZeroBased $ length set) 0) .- map (mapFst- (mapLookup "estimateDiscrete: unknown emission symbol" emi)))- grouped+instance (Ord symbol) => Generate (Discrete symbol) where+ generate (Discrete m) =+ randomItemProp . StorableArray.toAssociations . Matrix.takeColumn m++instance (Ord symbol) => EmissionProb (Discrete symbol) where+ mapStatesShape f (Discrete m) = Discrete $ Matrix.mapWidth f m+ emissionProb (Discrete m) = Matrix.takeRow m+ emissionStateProb (Discrete m) x s = m #! (x,s)++instance (Ord symbol) => Estimate (Discrete symbol) where+ accumulateEmissions sh =+ DiscreteTrained .+ NonEmptyMap.map+ (StorableArray.reshape sh .+ StorableArray.fromAssociations 0 (Shape.Deferred sh) .+ Map.toList) .+ NonEmptyMap.fromListWith (Map.unionWith (+)) .+ fmap (\(state,sym) -> (sym, Map.singleton (Shape.deferIndex sh state) 1))+ trainVector sym = DiscreteTrained . NonEmptyMap.singleton sym combine (DiscreteTrained distr0) (DiscreteTrained distr1) =- DiscreteTrained $ Map.unionWith Vector.add distr0 distr1+ DiscreteTrained $ NonEmptyMap.unionWith Vector.add distr0 distr1 normalize (DiscreteTrained distr) =- Discrete $ if Map.null distr then distr else normalizeProbVecs distr+ Discrete $ normalizeProbColumns $ discreteFromMap distr -transposeVectorList ::- (Shape.C sh, Eq sh, Class.Real a) =>- Array sh (Vector Matrix.ZeroInt a) -> [Vector sh a]-transposeVectorList xs =- case Array.toList xs of- [] -> []- x:_ -> Matrix.toRows $ Matrix.fromColumnArray (StorableArray.shape x) xs+normalizeProbColumns ::+ (Shape.C height, Shape.C width, Eq width, Class.Real a) =>+ Matrix.General height width a -> Matrix.General height width a+normalizeProbColumns m = m #/\ Matrix.columnSums m -normalizeProbVecs ::- (Shape.C sh, Eq sh, Foldable f, Functor f, Class.Real a) =>- f (Vector sh a) -> f (Vector sh a)-normalizeProbVecs vs =- let factors =- StorableArray.map recip $ List.foldl1' Vector.add $ Fold.toList vs- in fmap (Vector.mul factors) vs+discreteStateShape ::+ (Shape.C sh) => NonEmptyMap.T symbol (Vector sh prob) -> sh+discreteStateShape =+ StorableArray.shape . snd . fst . NonEmptyMap.minViewWithKey -mapLookup :: (Ord k) => String -> Map.Map k a -> k -> a-mapLookup msg dict x = Map.findWithDefault (error msg) x dict+discreteFromMap ::+ (Ord symbol, Shape.C sh, Eq sh, Class.Real prob) =>+ NonEmptyMap.T symbol (Vector sh prob) -> Matrix.General (Set symbol) sh prob+discreteFromMap m =+ Matrix.fromRowArray (discreteStateShape m) $+ Array.fromMap $ NonEmptyMap.flatten m +discreteFromList ::+ (Ord symbol, Shape.C sh, Eq sh, Class.Real prob) =>+ NonEmpty.T [] (symbol, Vector sh prob) -> T (Discrete symbol) sh prob+discreteFromList = Discrete . discreteFromMap . NonEmptyMap.fromList -newtype Gaussian emiSh stateSh a =- Gaussian (Array stateSh (Vector emiSh a, UpperTriangular emiSh a, a))- deriving (Show) -newtype GaussianTrained emiSh stateSh a =++data Gaussian emiSh++newtype instance T (Gaussian emiSh) stateSh a =+ Gaussian (Array stateSh (a, Vector emiSh a, Triangular.Upper emiSh a))++newtype instance Trained (Gaussian emiSh) stateSh a = GaussianTrained- (Array stateSh- (Maybe (Vector emiSh a, HermitianMatrix emiSh a, a)))- deriving (Show)+ (StorableArray.Array (stateSh, MatrixShape.Hermitian (():+:emiSh)) a) -type instance Probability (Gaussian emiSh stateSh a) = a-type instance Emission (Gaussian emiSh stateSh a) = Vector emiSh a-type instance StateShape (Gaussian emiSh stateSh a) = stateSh+type instance Emission (Gaussian emiSh) a = Vector emiSh a -instance- (NFData emiSh, NFData stateSh, Shape.C stateSh, NFData a, Storable a) =>- NFData (Gaussian emiSh stateSh a) where- rnf (Gaussian params) = rnf params+instance (Shape.C emiSh, P.Show emiSh) => Show (Gaussian emiSh) where+ showsPrec prec (Gaussian m) = P.showsPrec prec m+ showsPrecTrained prec (GaussianTrained m) = P.showsPrec prec m -instance- (NFData emiSh, NFData stateSh, Shape.C stateSh, NFData a, Storable a) =>- NFData (GaussianTrained emiSh stateSh a) where- rnf (GaussianTrained params) = rnf params+instance (DeepSeq.NFData emiSh) => NFData (Gaussian emiSh) where+ rnf (Gaussian params) = DeepSeq.rnf params+ rnfTrained (GaussianTrained params) = DeepSeq.rnf params -instance- (FormatArray emiSh, Shape.C stateSh, Class.Real a) =>- Format (Gaussian emiSh stateSh a) where+instance (FormatArray emiSh) => Format (Gaussian emiSh) where format = runFormatGaussian $ Class.switchReal formatGaussian formatGaussian -newtype FormatGaussian emiSh stateSh a =+newtype FormatGaussian out emiSh stateSh a = FormatGaussian- {runFormatGaussian :: String -> Gaussian emiSh stateSh a -> TextBox.Box}+ {runFormatGaussian :: String -> T (Gaussian emiSh) stateSh a -> out} formatGaussian ::- (FormatArray emiSh, Shape.C stateSh, Class.Real a, Format a) =>- FormatGaussian emiSh stateSh a+ (FormatArray emiSh, Shape.C stateSh,+ Class.Real a, Format.Format a, Output out) =>+ FormatGaussian out emiSh stateSh a formatGaussian =- FormatGaussian $ \fmt (Gaussian params) -> format fmt $ Array.toList params+ FormatGaussian $ \fmt (Gaussian params) ->+ Format.format fmt $ Array.toList params -instance- (Shape.Indexed stateSh, Eq stateSh, Class.Real a) =>- Info (Gaussian emiSh stateSh a) where+instance Info (Gaussian emiSh) where statesShape (Gaussian params) = Array.shape params+ statesShapeTrained (GaussianTrained params) =+ fst $ StorableArray.shape params -instance- (Shape.C emiSh, Eq emiSh, Shape.Indexed stateSh, Eq stateSh, Class.Real a) =>- Generate (Gaussian emiSh stateSh a) where+instance (Shape.C emiSh, Eq emiSh) => Generate (Gaussian emiSh) where generate (Gaussian allParams) state = do- let (center, covarianceChol, _c) = allParams ! state+ let (_c, center, covarianceChol) = allParams ! state seed <- MS.state Rnd.random return $ Vector.add center $ Vector.random Vector.Normal (StorableArray.shape center) seed- <# covarianceChol+ -*# covarianceChol -instance- (Shape.C emiSh, Eq emiSh, Shape.Indexed stateSh, Eq stateSh, Class.Real a) =>- EmissionProb (Gaussian emiSh stateSh a) where+instance (Shape.C emiSh, Eq emiSh) => EmissionProb (Gaussian emiSh) where+ mapStatesShape f (Gaussian m) = Gaussian $ Array.mapShape f m emissionProb (Gaussian allParams) x =- Vector.fromList (Array.shape allParams) $- map (emissionProbGen x) $ Array.toList allParams+ StorableArray.fromBoxed $ fmap (gaussianEmissionProb x) allParams emissionStateProb (Gaussian allParams) x s =- emissionProbGen x $ allParams ! s+ gaussianEmissionProb x $ allParams ! s -emissionProbGen ::+gaussianEmissionProb :: (Shape.C emiSh, Eq emiSh, Class.Real a) =>- Vector emiSh a -> (Vector emiSh a, UpperTriangular emiSh a, a) -> a-emissionProbGen x (center, covarianceChol, c) =- let x0 =- Matrix.solveVector (Triangular.transpose covarianceChol) $- Vector.sub x center- in c * cexp ((-1/2) * Vector.inner x0 x0)+ Vector emiSh a -> (a, Vector emiSh a, Triangular.Upper emiSh a) -> a+gaussianEmissionProb x (c, center, covarianceChol) =+ c * expSquared (Vector.sub x center -/# covarianceChol) +expSquared :: (Shape.C sh, Class.Real a) => Vector sh a -> a+expSquared =+ getNorm $ Class.switchReal (Norm expSquaredAux) (Norm expSquaredAux) -instance- (Shape.C emiSh, Eq emiSh, Shape.Indexed stateSh, Eq stateSh, Class.Real a) =>- Estimate- (GaussianTrained emiSh stateSh a)- (Gaussian emiSh stateSh a) where- type Distribution (GaussianTrained emiSh stateSh a) =- Gaussian emiSh stateSh a- type Trained (Gaussian emiSh stateSh a) = GaussianTrained emiSh stateSh a- accumulateEmissions =- let params xs =- (NonEmpty.foldl1Map Vector.add (uncurry $ flip Vector.scale) xs,- covarianceReal $ fmap swap xs,- Fold.sum $ fmap snd xs)- in GaussianTrained . fmap (fmap params . NonEmpty.fetch)- combine (GaussianTrained distr0) (GaussianTrained distr1) =- let comb (center0, covariance0, weight0)- (center1, covariance1, weight1) =- (Vector.add center0 center1,- Vector.add covariance0 covariance1,- weight0 + weight1)- in GaussianTrained $ Array.zipWith (maybePlus comb) distr0 distr1+newtype Norm f a = Norm {getNorm :: f a -> a}++expSquaredAux ::+ (Shape.C sh, Class.Floating a, Vector.RealOf a ~ ar, Class.Real ar) =>+ Vector sh a -> ar+expSquaredAux x = exp ((-1/2) * Vector.norm2Squared x)+++instance (Shape.C emiSh, Eq emiSh) => Estimate (Gaussian emiSh) where+ accumulateEmissions sh xs =+ let emiSh = StorableArray.shape $ snd $ NonEmpty.head xs+ hermSh = MatrixShape.hermitian MatrixShape.RowMajor (():+:emiSh)+ in GaussianTrained $+ Matrix.toRowMajor . Matrix.fromRowArray hermSh . Array.reshape sh .+ Array.accumulate Vector.add+ (Array.replicate (Shape.Deferred sh) (Vector.zero hermSh)) .+ map (\(state,v) -> (Shape.deferIndex sh state, extendedHermitian v)) .+ NonEmpty.flatten+ $ xs+ trainVector xs probs =+ GaussianTrained $ Matrix.toRowMajor $ probs |*- extendedHermitian xs+ combine (GaussianTrained m0) (GaussianTrained m1) =+ GaussianTrained $ Vector.add m0 m1 {- Sum_i (xi-m) * (xi-m)^T = Sum_i xi*xi^T + Sum_i m*m^T - Sum_i xi*m^T - Sum_i m*xi^T = Sum_i xi*xi^T - Sum_i m*m^T = Sum_i xi*xi^T - n * m*m^T -}- normalize (GaussianTrained distr) =- let params (centerSum, covarianceSum, weight) =- let c = recip weight- center = Vector.scale c centerSum+ normalize (GaussianTrained m) =+ let params (weight, centerSum, covarianceSum) =+ let c = recip (weight#!((),()))+ center = Vector.scale c $ Matrix.flattenRow centerSum in (center,- Vector.sub (Vector.scale c covarianceSum)+ Matrix.sub+ (Matrix.scaleRealReal c covarianceSum) (Hermitian.outer MatrixShape.RowMajor center))- in Gaussian $- fmap- (gaussianParameters . params .- fromMaybe- (error "Distribution.normalize: undefined array element")) $- distr--maybePlus :: (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a-maybePlus f mx my = liftA2 f mx my <|> mx <|> my+ in Gaussian $+ fmap (gaussianParameters . params .+ Hermitian.split . ArrMatrix.fromVector) $+ Matrix.toRowArray $ Matrix.fromRowMajor m +extendedHermitian ::+ (Shape.C emiSh, Class.Floating a) =>+ StorableArray.Array emiSh a ->+ StorableArray.Array (MatrixShape.Hermitian (():+:emiSh)) a+extendedHermitian =+ ArrMatrix.toVector .+ Hermitian.outer MatrixShape.RowMajor . Vector.append (Vector.one ()) -newtype CovarianceReal f emiSh a =- CovarianceReal- {getCovarianceReal :: f (a, Vector emiSh a) -> HermitianMatrix emiSh a}+{- |+input array must be non-empty+-}+gaussianTrained ::+ (Shape.C emiSh, Eq emiSh, Shape.C stateSh, Class.Real prob) =>+ Array stateSh (prob, Vector emiSh prob, Matrix.Hermitian emiSh prob) ->+ Trained (Gaussian emiSh) stateSh prob+gaussianTrained =+ GaussianTrained . Matrix.toRowMajor .+ matrixFromRowArray "HMM.Distribution.gaussianTrained" .+ fmap+ (\(weight, center, covariance) ->+ ArrMatrix.toVector $+ Hermitian.stack+ (Hermitian.fromList MatrixShape.RowMajor () [weight])+ (Matrix.singleRow MatrixShape.RowMajor center)+ covariance) -covarianceReal ::- (Shape.C emiSh, Eq emiSh, Class.Real a) =>- NonEmpty.T [] (a, Vector emiSh a) -> HermitianMatrix emiSh a-covarianceReal =- getCovarianceReal $- Class.switchReal- (CovarianceReal $ Hermitian.sumRank1NonEmpty MatrixShape.RowMajor)- (CovarianceReal $ Hermitian.sumRank1NonEmpty MatrixShape.RowMajor)+matrixFromRowArray ::+ (Shape.C width, Eq width, Shape.C height, Class.Real a) =>+ String ->+ Array height (StorableArray.Array width a) ->+ Matrix.General height width a+matrixFromRowArray name xs =+ case Array.toList xs of+ [] -> error $ name ++ ": empty array"+ x:_ -> Matrix.fromRowArray (StorableArray.shape x) xs gaussian :: (Shape.C emiSh, Shape.C stateSh, Class.Real prob) =>- Array stateSh (Vector emiSh prob, HermitianMatrix emiSh prob) ->- Gaussian emiSh stateSh prob-gaussian = consGaussian . fmap gaussianParameters+ Array stateSh (Vector emiSh prob, Matrix.Hermitian emiSh prob) ->+ T (Gaussian emiSh) stateSh prob+gaussian = Gaussian . fmap gaussianParameters gaussianParameters :: (Shape.C emiSh, Class.Real prob) =>- (Vector emiSh prob, HermitianMatrix emiSh prob) ->- (Vector emiSh prob, UpperTriangular emiSh prob, prob)+ (Vector emiSh prob, Matrix.Hermitian emiSh prob) ->+ (prob, Vector emiSh prob, Triangular.Upper emiSh prob) gaussianParameters (center, covariance) = gaussianFromCholesky center $ HermitianPD.decompose covariance -consGaussian ::- (Shape.C stateSh) =>- Array stateSh (Vector emiSh a, UpperTriangular emiSh a, a) ->- Gaussian emiSh stateSh a-consGaussian = Gaussian- gaussianFromCholesky :: (Shape.C emiSh, Class.Real prob) =>- Vector emiSh prob -> UpperTriangular emiSh prob ->- (Vector emiSh prob, UpperTriangular emiSh prob, prob)+ Vector emiSh prob -> Triangular.Upper emiSh prob ->+ (prob, Vector emiSh prob, Triangular.Upper emiSh prob) gaussianFromCholesky center covarianceChol = let covarianceSqrtDet = Vector.product $ Triangular.takeDiagonal covarianceChol- in (center, covarianceChol,- recip (sqrt2pi ^ vectorDim center * covarianceSqrtDet))+ in (recip (sqrt2pi ^ vectorDim center * covarianceSqrtDet),+ center, covarianceChol) sqrt2pi :: (Class.Real a) => a sqrt2pi = runIdentity $ Class.switchReal sqrt2piAux sqrt2piAux@@ -366,16 +435,16 @@ sqrt2piAux :: (Floating a) => Identity a sqrt2piAux = Identity $ sqrt (2*pi) -cexp :: (Class.Real a) => a -> a-cexp = appEndo $ Class.switchReal (Endo exp) (Endo exp) ---class ToCSV distr where- toCells :: distr -> [[String]]+class ToCSV typ where+ toCells ::+ (Shape.C sh, Class.Real prob, P.Show prob) =>+ T typ sh prob -> [[String]] -class FromCSV distr where- parseCells :: StateShape distr -> HMMCSV.CSVParser distr+class FromCSV typ where+ parseCells ::+ (Shape.C sh, Eq sh, Class.Real prob, Read prob) =>+ sh -> HMMCSV.CSVParser (T typ sh prob) class (Ord symbol) => CSVSymbol symbol where cellFromSymbol :: symbol -> String@@ -390,21 +459,18 @@ symbolFromCell = maybeRead -instance- (Shape.C sh, Class.Real prob, Show prob, Read prob, CSVSymbol symbol) =>- ToCSV (Discrete symbol sh prob) where+instance (CSVSymbol symbol) => ToCSV (Discrete symbol) where toCells (Discrete m) = map (\(symbol, probs) -> cellFromSymbol symbol : HMMCSV.cellsFromVector probs) $- Map.toAscList m+ Array.toAssociations $ Matrix.toRowArray m -instance- (Shape.C sh, Class.Real prob, Show prob, Read prob, CSVSymbol symbol) =>- FromCSV (Discrete symbol sh prob) where+instance (CSVSymbol symbol) => FromCSV (Discrete symbol) where parseCells n =- fmap (Discrete . Map.fromList) $- HMMCSV.manyRowsUntilEnd $ parseSymbolProb n+ let p = parseSymbolProb n+ in fmap discreteFromList $+ liftA2 NonEmpty.Cons (HMMCSV.getRow >>= p) (HMMCSV.manyRowsUntilEnd p) parseSymbolProb :: (Shape.C sh, Class.Real prob, Read prob, CSVSymbol symbol) =>@@ -426,36 +492,30 @@ return $ StorableArray.reshape sh v) -instance- (Shape.Indexed emiSh, Shape.Indexed stateSh,- Class.Real a, Eq a, Show a, Read a) =>- ToCSV (Gaussian emiSh stateSh a) where+instance (Shape.Indexed emiSh) => ToCSV (Gaussian emiSh) where toCells (Gaussian params) = List.intercalate [[]] $ map- (\(center, covarianceChol, _) ->+ (\(_, center, covarianceChol) -> HMMCSV.cellsFromVector center : HMMCSV.cellsFromSquare (Triangular.toSquare covarianceChol)) $ Array.toList params -instance- (emiSh ~ Matrix.ZeroInt, Shape.Indexed stateSh,- Class.Real a, Eq a, Show a, Read a) =>- FromCSV (Gaussian emiSh stateSh a) where+instance (emiSh ~ Matrix.ShapeInt) => FromCSV (Gaussian emiSh) where parseCells sh = do let n = Shape.size sh gs <- HMMCSV.manySepUntilEnd parseSingleGaussian HMMCSV.assert (length gs == n) $ printf "number of states (%d) and number of Gaussians (%d) mismatch" n (length gs)- let sizes = map (vectorDim . fst3) gs+ let sizes = map (vectorDim . snd3) gs HMMCSV.assert (ListHT.allEqual sizes) $ printf "dimensions of emissions mismatch: %s" (show sizes)- return $ consGaussian $ Array.fromList sh gs+ return $ Gaussian $ Array.fromList sh gs parseSingleGaussian ::- (emiSh ~ Matrix.ZeroInt, Class.Real prob, Eq prob, Read prob) =>- HMMCSV.CSVParser (Vector emiSh prob, UpperTriangular emiSh prob, prob)+ (emiSh ~ Matrix.ShapeInt, Class.Real prob, Eq prob, Read prob) =>+ HMMCSV.CSVParser (prob, Vector emiSh prob, Triangular.Upper emiSh prob) parseSingleGaussian = do center <- HMMCSV.parseNonEmptyVectorCells covarianceCholSquare <-@@ -475,6 +535,8 @@ -} isUpperTriang :: (Shape.C sh, Class.Real a, Eq a) =>- SquareMatrix sh a -> UpperTriangular sh a -> Bool+ Matrix.Square sh a -> Triangular.Upper sh a -> Bool isUpperTriang m mt =- Vector.toList m == Vector.toList (Triangular.toSquare mt)+ Vector.toList (ArrMatrix.toVector m)+ ==+ Vector.toList (ArrMatrix.toVector (Triangular.toSquare mt))
src/Math/HiddenMarkovModel/Example/CirclePrivate.hs view
@@ -46,7 +46,7 @@ hmm :: HMM hmm = HMM.Cons {- HMM.initial = normalizeProb $ Vector.constant stateSet 1,+ HMM.initial = normalizeProb $ Vector.one stateSet, HMM.transition = squareFromLists stateSet $ stateVector 0.9 0.0 0.0 0.1 :
src/Math/HiddenMarkovModel/Example/SineWave.hs view
@@ -40,7 +40,7 @@ hmm :: HMM hmm = HMM.Cons {- HMM.initial = normalizeProb $ Vector.constant stateSet 1,+ HMM.initial = normalizeProb $ Vector.one stateSet, HMM.transition = squareFromLists stateSet $ stateVector 0.9 0.0 0.0 0.1 :
src/Math/HiddenMarkovModel/Example/TrafficLightPrivate.hs view
@@ -7,17 +7,14 @@ import qualified Numeric.LAPACK.Vector as Vector import Numeric.LAPACK.Vector (Vector)-import Numeric.LAPACK.Format (Format(format)) import qualified Data.Array.Comfort.Shape as Shape -import qualified Text.PrettyPrint.Boxes as TextBox import Text.Read.HT (maybeRead) import Control.DeepSeq (NFData(rnf)) import Control.Monad (liftM2) -import qualified Data.Map as Map import qualified Data.NonEmpty as NonEmpty import qualified Data.List.HT as ListHT import Data.NonEmpty ((!:))@@ -31,9 +28,6 @@ rnf Red = () rnf _ = () -instance Format Color where- format _fmt = TextBox.text . show- {- | Using 'show' and 'read' is not always a good choice since they must format and parse Haskell expressions@@ -67,9 +61,9 @@ stateVector 0.0 0.0 0.2 0.8 : [], HMM.distribution =- Distr.Discrete $ Map.fromList $- (Red, stateVector 1 0 0 0) :- (Yellow, stateVector 0 1 0 1):+ Distr.discreteFromList $+ (Red, stateVector 1 0 0 0) !:+ (Yellow, stateVector 0 1 0 1) : (Green, stateVector 0 0 1 0) : [] }@@ -86,8 +80,8 @@ stateVector 0.2 0.2 0.3 0.3 : [], HMM.distribution =- Distr.Discrete $ Map.fromList $- (Red, stateVector 0.6 0.2 0.2 0.2) :+ Distr.discreteFromList $+ (Red, stateVector 0.6 0.2 0.2 0.2) !: (Yellow, stateVector 0.2 0.6 0.2 0.6) : (Green, stateVector 0.2 0.2 0.6 0.2) : []
src/Math/HiddenMarkovModel/Named.hs view
@@ -1,6 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-} module Math.HiddenMarkovModel.Named ( T(..), Discrete,@@ -42,30 +40,31 @@ Although 'nameFromStateMap' and 'stateFromNameMap' are exported you must be careful to keep them consistent when you alter them. -}-data T distr sh ix prob =+data T typ sh ix prob = Cons {- model :: HMM.T distr sh prob,+ model :: HMM.T typ sh prob, nameFromStateMap :: Array sh String, stateFromNameMap :: Map String ix } deriving (Show) +type Simple typ sh prob = T typ sh (Shape.Index sh) prob type Discrete symbol stateSh prob =- T (Distr.Discrete symbol stateSh prob) stateSh (Shape.Index stateSh) prob+ Simple (Distr.Discrete symbol) stateSh prob type Gaussian emiSh stateSh a =- T (Distr.Gaussian emiSh stateSh a) stateSh (Shape.Index stateSh) a+ Simple (Distr.Gaussian emiSh) stateSh a instance- (NFData distr, NFData sh, NFData ix, NFData prob,+ (Distr.NFData typ, NFData sh, NFData ix, NFData prob, Shape.C sh, Storable prob) =>- NFData (T distr sh ix prob) where+ NFData (T typ sh ix prob) where rnf hmm = rnf (model hmm, nameFromStateMap hmm, stateFromNameMap hmm) fromModelAndNames ::- (Shape.Indexed sh, Shape.Index sh ~ state) =>- HMM.T distr sh prob -> [String] -> T distr sh state prob+ (Shape.Indexed sh) =>+ HMM.T typ sh prob -> [String] -> Simple typ sh prob fromModelAndNames md names = let m = Array.fromList (StorableArray.shape $ HMM.initial md) names in Cons {@@ -82,26 +81,24 @@ toCSV ::- (Distr.ToCSV distr, Shape.Indexed sh, Class.Real prob, Show prob) =>- T distr sh ix prob -> String+ (Distr.ToCSV typ, Shape.Indexed sh, Class.Real prob, Show prob) =>+ Simple typ sh prob -> String toCSV hmm = CSV.ppCSVTable $ snd $ CSV.toCSVTable $ HMMCSV.padTable "" $ Array.toList (nameFromStateMap hmm) : HMM.toCells (model hmm) fromCSV ::- (Distr.FromCSV distr, Distr.StateShape distr ~ stateSh,- Shape.Indexed stateSh, Shape.Index stateSh ~ state,+ (Distr.FromCSV typ, Shape.Indexed stateSh, Eq stateSh, Class.Real prob, Read prob) => (Int -> stateSh) ->- String -> ME.Exceptional String (T distr stateSh state prob)+ String -> ME.Exceptional String (Simple typ stateSh prob) fromCSV makeShape = MS.evalStateT (parseCSV makeShape) . map HMMCSV.fixShortRow . CSV.parseCSV parseCSV ::- (Distr.FromCSV distr, Distr.StateShape distr ~ stateSh,- Shape.Indexed stateSh, Shape.Index stateSh ~ state,+ (Distr.FromCSV typ, Shape.Indexed stateSh, Eq stateSh, Class.Real prob, Read prob) =>- (Int -> stateSh) -> HMMCSV.CSVParser (T distr stateSh state prob)+ (Int -> stateSh) -> HMMCSV.CSVParser (Simple typ stateSh prob) parseCSV makeShape = do names <- HMMCSV.parseStringList =<< HMMCSV.getRow let duplicateNames =
src/Math/HiddenMarkovModel/Normalized.hs view
@@ -10,12 +10,12 @@ import qualified Math.HiddenMarkovModel.Distribution as Distr import Math.HiddenMarkovModel.Private (T(..), Trained(..), emission,- biscaleTransition, matrixMaxMul, sumTransitions)-import Math.HiddenMarkovModel.Utility- (SquareMatrix, normalizeFactor, normalizeProb)+ biscaleTransition, revealGen, sumTransitions)+import Math.HiddenMarkovModel.Utility (normalizeFactor, normalizeProb) +import qualified Numeric.LAPACK.Matrix as Matrix import qualified Numeric.LAPACK.Vector as Vector-import Numeric.LAPACK.Matrix ((<#), (#>))+import Numeric.LAPACK.Matrix ((-*#), (#*|)) import Numeric.LAPACK.Vector (Vector) import qualified Numeric.Netlib.Class as Class@@ -23,15 +23,12 @@ import qualified Control.Functor.HT as Functor import qualified Data.Array.Comfort.Storable as StorableArray-import qualified Data.Array.Comfort.Boxed as Array import qualified Data.Array.Comfort.Shape as Shape import qualified Data.NonEmpty.Class as NonEmptyC import qualified Data.NonEmpty as NonEmpty import qualified Data.Foldable as Fold-import qualified Data.List as List-import Data.Traversable (Traversable, mapAccumL)-import Data.Tuple.HT (mapFst, mapSnd, swap)+import Data.Traversable (Traversable) {- |@@ -40,43 +37,43 @@ that it may be rounded to zero in the choosen number type. -} logLikelihood ::- (Distr.EmissionProb distr, Distr.StateShape distr ~ sh, Eq sh, Floating prob,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,+ (Distr.EmissionProb typ, Shape.C sh, Eq sh, Floating prob,+ Class.Real prob, Distr.Emission typ prob ~ emission, Traversable f) =>- T distr sh prob -> NonEmpty.T f emission -> prob+ T typ sh prob -> NonEmpty.T f emission -> prob logLikelihood hmm = Fold.sum . fmap (log . fst) . alpha hmm alpha ::- (Distr.EmissionProb distr, Distr.StateShape distr ~ sh, Eq sh,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,+ (Distr.EmissionProb typ, Shape.C sh, Eq sh,+ Class.Real prob, Distr.Emission typ prob ~ emission, Traversable f) =>- T distr sh prob ->+ T typ sh prob -> NonEmpty.T f emission -> NonEmpty.T f (prob, Vector sh prob) alpha hmm (NonEmpty.Cons x xs) = let normMulEmiss y = normalizeFactor . Vector.mul (emission hmm y) in NonEmpty.scanl- (\(_,alphai) xi -> normMulEmiss xi (transition hmm #> alphai))+ (\(_,alphai) xi -> normMulEmiss xi (transition hmm #*| alphai)) (normMulEmiss x (initial hmm)) xs beta ::- (Distr.EmissionProb distr, Distr.StateShape distr ~ sh, Eq sh,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,+ (Distr.EmissionProb typ, Shape.C sh, Eq sh,+ Class.Real prob, Distr.Emission typ prob ~ emission, Traversable f, NonEmptyC.Reverse f) =>- T distr sh prob ->+ T typ sh prob -> f (prob, emission) -> NonEmpty.T f (Vector sh prob) beta hmm = nonEmptyScanr (\(ci,xi) betai -> Vector.scale (recip ci) $- Vector.mul (emission hmm xi) betai <# transition hmm)- (Vector.constant (StorableArray.shape $ initial hmm) 1)+ Vector.mul (emission hmm xi) betai -*# transition hmm)+ (Vector.one $ StorableArray.shape $ initial hmm) alphaBeta ::- (Distr.EmissionProb distr, Distr.StateShape distr ~ sh, Eq sh,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,+ (Distr.EmissionProb typ, Shape.C sh, Eq sh,+ Class.Real prob, Distr.Emission typ prob ~ emission, Traversable f, NonEmptyC.Zip f, NonEmptyC.Reverse f) =>- T distr sh prob ->+ T typ sh prob -> NonEmpty.T f emission -> (NonEmpty.T f (prob, Vector sh prob), NonEmpty.T f (Vector sh prob)) alphaBeta hmm xs =@@ -86,19 +83,19 @@ xiFromAlphaBeta ::- (Distr.EmissionProb distr, Distr.StateShape distr ~ sh, Eq sh,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,+ (Distr.EmissionProb typ, Shape.C sh, Eq sh,+ Class.Real prob, Distr.Emission typ prob ~ emission, Traversable f, NonEmptyC.Zip f) =>- T distr sh prob ->+ T typ sh prob -> NonEmpty.T f emission -> NonEmpty.T f (prob, Vector sh prob) -> NonEmpty.T f (Vector sh prob) ->- f (SquareMatrix sh prob)+ f (Matrix.Square sh prob) xiFromAlphaBeta hmm xs calphas betas = let (cs,alphas) = Functor.unzip calphas in NonEmptyC.zipWith4 (\x alpha0 c1 beta1 ->- Vector.scale (recip c1) $ biscaleTransition hmm x alpha0 beta1)+ Matrix.scale (recip c1) $ biscaleTransition hmm x alpha0 beta1) (NonEmpty.tail xs) (NonEmpty.init alphas) (NonEmpty.tail cs)@@ -119,22 +116,10 @@ It is found using the Viterbi algorithm. -} reveal ::- (Distr.EmissionProb distr, Distr.StateShape distr ~ sh,- Shape.InvIndexed sh, Eq sh, Shape.Index sh ~ state,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,- Traversable f, NonEmptyC.Reverse f) =>- T distr sh prob -> NonEmpty.T f emission -> NonEmpty.T f state-reveal hmm (NonEmpty.Cons x xs) =- fmap (Shape.revealIndex (StorableArray.shape $ initial hmm)) $- uncurry (NonEmpty.scanr (StorableArray.!)) $- mapFst- (fst . Vector.argAbsMaximum .- StorableArray.mapShape Shape.Deferred) $- mapAccumL- (\alphai xi ->- swap $ mapSnd (Vector.mul (emission hmm xi)) $- matrixMaxMul (transition hmm) $ normalizeProb alphai)- (Vector.mul (emission hmm x) (initial hmm)) xs+ (Distr.EmissionProb typ, Shape.InvIndexed sh, Eq sh, Shape.Index sh ~ state,+ Distr.Emission typ prob ~ emission, Class.Real prob, Traversable f) =>+ T typ sh prob -> NonEmpty.T f emission -> NonEmpty.T f state+reveal = revealGen normalizeProb {- |@@ -155,9 +140,9 @@ This is done by the Baum-Welch algorithm. -} trainUnsupervised ::- (Distr.Estimate tdistr distr, Distr.StateShape distr ~ sh, Eq sh,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>- T distr sh prob -> NonEmpty.T [] emission -> Trained tdistr sh prob+ (Distr.Estimate typ, Shape.C sh, Eq sh,+ Class.Real prob, Distr.Emission typ prob ~ emission) =>+ T typ sh prob -> NonEmpty.T [] emission -> Trained typ sh prob trainUnsupervised hmm xs = let (alphas, betas) = alphaBeta hmm xs zetas = zetaFromAlphaBeta alphas betas@@ -168,8 +153,5 @@ trainedTransition = sumTransitions hmm $ xiFromAlphaBeta hmm xs alphas betas, trainedDistribution =- Distr.accumulateEmissions $- Array.fromList (StorableArray.shape zeta0) $- map (zip (NonEmpty.flatten xs)) $- List.transpose $ map Vector.toList $ NonEmpty.flatten zetas+ Distr.accumulateEmissionVectors $ NonEmptyC.zip xs zetas }
src/Math/HiddenMarkovModel/Pattern.hs view
@@ -30,8 +30,10 @@ import qualified Math.HiddenMarkovModel.Distribution as Distr import qualified Math.HiddenMarkovModel as HMM import Math.HiddenMarkovModel.Private (Trained(..))-import Math.HiddenMarkovModel.Utility (SquareMatrix, squareConstant)+import Math.HiddenMarkovModel.Utility (squareConstant) +import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix+import qualified Numeric.LAPACK.Matrix as Matrix import qualified Numeric.LAPACK.Vector as Vector import qualified Numeric.LAPACK.ShapeStatic as ShapeStatic @@ -44,16 +46,16 @@ import Data.FixedLength ((!:)) import qualified Type.Data.Num.Unary.Literal as TypeNum-import Type.Base.Proxy (Proxy(Proxy)) -import qualified Data.Map as Map+import qualified Data.NonEmpty.Map as NonEmptyMap+import qualified Data.NonEmpty as NonEmpty import Data.Semigroup (Semigroup, (<>), stimes) import Prelude hiding (replicate) newtype T sh prob =- Cons (sh -> (Shape.Index sh, SquareMatrix sh prob, Shape.Index sh))+ Cons (sh -> (Shape.Index sh, Matrix.Square sh prob, Shape.Index sh)) atom :: (Shape.Indexed sh, Shape.Index sh ~ state, Class.Real prob) =>@@ -77,7 +79,7 @@ Cons $ \n -> case (f n, g n) of ((sai, ma, sao), (sbi, mb, sbo)) ->- (sai, increment (sbi,sao) 1 $ Vector.add ma mb, sbo)+ (sai, increment (sbi,sao) 1 $ Matrix.add ma mb, sbo) replicate :: (Shape.Indexed sh, Class.Real prob) => Int -> T sh prob -> T sh prob@@ -86,25 +88,26 @@ case f sh of (si, m, so) -> let k = fromIntegral ki- in (si, increment (si,so) (k-1) $ Vector.scale k m, so)+ in (si, increment (si,so) (k-1) $ Matrix.scale k m, so) increment :: (Shape.Indexed sh, Shape.Index sh ~ state, Class.Real a) =>- (state, state) -> a -> SquareMatrix sh a -> SquareMatrix sh a-increment (i,j) x m = StorableArray.accumulate (+) m [((i,j), x)]+ (state, state) -> a -> Matrix.Square sh a -> Matrix.Square sh a+increment (i,j) x =+ ArrMatrix.lift1 $ flip (StorableArray.accumulate (+)) [((i,j), x)] finish ::- (Shape.Indexed sh, Class.Real prob) =>- sh -> tdistr -> T sh prob -> Trained tdistr sh prob-finish sh tdistr (Cons f) =- case f sh of- (si, m, _so) ->- Trained {- trainedInitial = StorableArray.fromAssociations sh 0 [(si,1)],- trainedTransition = m,- trainedDistribution = tdistr- }+ (Distr.Info typ, Shape.Indexed sh, Class.Real prob) =>+ Distr.Trained typ sh prob -> T sh prob -> Trained typ sh prob+finish tdistr (Cons f) =+ let sh = Distr.statesShapeTrained tdistr+ (si, m, _so) = f sh+ in Trained {+ trainedInitial = Vector.unit sh si,+ trainedTransition = m,+ trainedDistribution = tdistr+ } _example :: HMM.DiscreteTrained Char (ShapeStatic.ZeroBased TypeNum.U2) Double@@ -112,10 +115,9 @@ let a = atom FL.i0 b = atom FL.i1 distr =- Distr.DiscreteTrained $ Map.fromList $- ('a', ShapeStatic.vector $ 1!:2!:FL.end) :+ Distr.DiscreteTrained $ NonEmptyMap.fromList $+ ('a', ShapeStatic.vector $ 1!:2!:FL.end) NonEmpty.!: ('b', ShapeStatic.vector $ 4!:3!:FL.end) : ('c', ShapeStatic.vector $ 0!:1!:FL.end) : []- in finish (ShapeStatic.ZeroBased Proxy) distr $- replicate 5 $ replicate 10 a <> replicate 20 b+ in finish distr $ replicate 5 $ replicate 10 a <> replicate 20 b
src/Math/HiddenMarkovModel/Private.hs view
@@ -1,15 +1,16 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-} module Math.HiddenMarkovModel.Private where import qualified Math.HiddenMarkovModel.Distribution as Distr import qualified Math.HiddenMarkovModel.CSV as HMMCSV-import Math.HiddenMarkovModel.Utility (SquareMatrix, diagonal)+import Math.HiddenMarkovModel.Utility (diagonal) +import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix+import qualified Numeric.LAPACK.Matrix.Square as Square import qualified Numeric.LAPACK.Matrix as Matrix import qualified Numeric.LAPACK.Vector as Vector import qualified Numeric.LAPACK.Format as Format-import Numeric.LAPACK.Matrix ((<#), (<#>), (#>))+import Numeric.LAPACK.Matrix ((-*#), (##*#), (#*##), (#*|)) import Numeric.LAPACK.Vector (Vector) import qualified Numeric.Netlib.Class as Class@@ -20,15 +21,15 @@ import Foreign.Storable (Storable) import qualified Data.Array.Comfort.Storable as StorableArray-import qualified Data.Array.Comfort.Boxed as Array import qualified Data.Array.Comfort.Shape as Shape import qualified Data.NonEmpty.Class as NonEmptyC import qualified Data.NonEmpty as NonEmpty import qualified Data.Semigroup as Sg import qualified Data.List as List+import Data.Semigroup ((<>)) import Data.Traversable (Traversable, mapAccumL)-import Data.Tuple.HT (mapPair, mapFst, mapSnd, swap)+import Data.Tuple.HT (mapFst, mapSnd, swap) {- |@@ -46,88 +47,84 @@ with respect to popular HMM descriptions. But I think this is the natural orientation, because this way you can write \"transition matrix times probability column vector\".--The type has two type parameters,-although the one for the distribution would be enough.-However, replacing @prob@ by @Distr.Probability distr@-would prohibit the derived Show and Read instances. -}-data T distr sh prob =+data T typ sh prob = Cons { initial :: Vector sh prob,- transition :: SquareMatrix sh prob,- distribution :: distr+ transition :: Matrix.Square sh prob,+ distribution :: Distr.T typ sh prob } deriving (Show) instance- (NFData distr, NFData sh, NFData prob, Storable prob) =>- NFData (T distr sh prob) where+ (Distr.NFData typ, NFData sh, Shape.C sh, NFData prob, Storable prob) =>+ NFData (T typ sh prob) where rnf (Cons initial_ transition_ distribution_) = rnf (initial_, transition_, distribution_) instance- (Class.Real prob, Format.FormatArray sh, Format.Format distr) =>- Format.Format (T distr sh prob) where+ (Distr.Format typ, Format.FormatArray sh, Class.Real prob) =>+ Format.Format (T typ sh prob) where format fmt (Cons initial_ transition_ distribution_) = Format.format fmt (initial_, transition_, distribution_) +mapStatesShape ::+ (Distr.EmissionProb typ, Shape.C sh0, Shape.C sh1) =>+ (sh0 -> sh1) -> T typ sh0 prob -> T typ sh1 prob+mapStatesShape f hmm =+ Cons {+ initial = StorableArray.mapShape f $ initial hmm,+ transition = Square.mapSize f $ transition hmm,+ distribution = Distr.mapStatesShape f $ distribution hmm+ } + emission ::- (Shape.C sh, Eq sh, sh ~ Distr.StateShape distr, Distr.EmissionProb distr,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>- T distr sh prob -> emission -> Vector sh prob+ (Distr.EmissionProb typ, Shape.C sh, Eq sh, Class.Real prob) =>+ T typ sh prob -> Distr.Emission typ prob -> Vector sh prob emission = Distr.emissionProb . distribution forward ::- (Shape.C sh, Eq sh, sh ~ Distr.StateShape distr, Distr.EmissionProb distr,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,- Traversable f) =>- T distr sh prob -> NonEmpty.T f emission -> prob+ (Distr.EmissionProb typ, Shape.C sh, Eq sh, Class.Real prob,+ Distr.Emission typ prob ~ emission, Traversable f) =>+ T typ sh prob -> NonEmpty.T f emission -> prob forward hmm = Vector.sum . NonEmpty.last . alpha hmm alpha ::- (Shape.C sh, Eq sh, sh ~ Distr.StateShape distr, Distr.EmissionProb distr,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,- Traversable f) =>- T distr sh prob ->- NonEmpty.T f emission -> NonEmpty.T f (Vector sh prob)+ (Distr.EmissionProb typ, Shape.C sh, Eq sh, Class.Real prob,+ Distr.Emission typ prob ~ emission, Traversable f) =>+ T typ sh prob -> NonEmpty.T f emission -> NonEmpty.T f (Vector sh prob) alpha hmm (NonEmpty.Cons x xs) = NonEmpty.scanl- (\alphai xi -> Vector.mul (emission hmm xi) (transition hmm #> alphai))+ (\alphai xi -> Vector.mul (emission hmm xi) (transition hmm #*| alphai)) (Vector.mul (emission hmm x) (initial hmm)) xs backward ::- (Shape.C sh, Eq sh, sh ~ Distr.StateShape distr, Distr.EmissionProb distr,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,- Traversable f) =>- T distr sh prob -> NonEmpty.T f emission -> prob+ (Distr.EmissionProb typ, Shape.C sh, Eq sh, Class.Real prob,+ Distr.Emission typ prob ~ emission, Traversable f) =>+ T typ sh prob -> NonEmpty.T f emission -> prob backward hmm (NonEmpty.Cons x xs) =- Vector.sum $- Vector.mul (initial hmm) $+ Vector.dot (initial hmm) $ Vector.mul (emission hmm x) $ NonEmpty.head $ beta hmm xs beta ::- (Shape.C sh, Eq sh, sh ~ Distr.StateShape distr, Distr.EmissionProb distr,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,- Traversable f) =>- T distr sh prob ->- f emission -> NonEmpty.T f (Vector sh prob)+ (Distr.EmissionProb typ, Shape.C sh, Eq sh, Class.Real prob,+ Distr.Emission typ prob ~ emission, Traversable f) =>+ T typ sh prob -> f emission -> NonEmpty.T f (Vector sh prob) beta hmm = NonEmpty.scanr- (\xi betai -> Vector.mul (emission hmm xi) betai <# transition hmm)- (Vector.constant (StorableArray.shape $ initial hmm) 1)+ (\xi betai -> Vector.mul (emission hmm xi) betai -*# transition hmm)+ (Vector.one $ StorableArray.shape $ initial hmm) alphaBeta ::- (Shape.C sh, Eq sh, sh ~ Distr.StateShape distr, Distr.EmissionProb distr,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,- Traversable f) =>- T distr sh prob ->+ (Distr.EmissionProb typ, Shape.C sh, Eq sh, Class.Real prob,+ Distr.Emission typ prob ~ emission, Traversable f) =>+ T typ sh prob -> NonEmpty.T f emission -> (prob, NonEmpty.T f (Vector sh prob), NonEmpty.T f (Vector sh prob)) alphaBeta hmm xs =@@ -139,29 +136,28 @@ biscaleTransition ::- (Shape.C sh, Eq sh, sh ~ Distr.StateShape distr,- Distr.EmissionProb distr, Distr.Probability distr ~ prob) =>- T distr sh prob -> Distr.Emission distr ->- Vector sh prob -> Vector sh prob -> SquareMatrix sh prob+ (Distr.EmissionProb typ, Shape.C sh, Eq sh, Class.Real prob) =>+ T typ sh prob -> Distr.Emission typ prob ->+ Vector sh prob -> Vector sh prob -> Matrix.Square sh prob biscaleTransition hmm x alpha0 beta1 =- diagonal (Vector.mul (emission hmm x) beta1)- <#>- transition hmm- <#>+ (diagonal (Vector.mul (emission hmm x) beta1)+ #*##+ transition hmm)+ ##*# diagonal alpha0 xiFromAlphaBeta ::- (Shape.C sh, Eq sh, sh ~ Distr.StateShape distr, Distr.EmissionProb distr,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>- T distr sh prob -> prob ->+ (Distr.EmissionProb typ, Shape.C sh, Eq sh, Class.Real prob,+ Distr.Emission typ prob ~ emission) =>+ T typ sh prob -> prob -> NonEmpty.T [] emission -> NonEmpty.T [] (Vector sh prob) -> NonEmpty.T [] (Vector sh prob) ->- [SquareMatrix sh prob]+ [Matrix.Square sh prob] xiFromAlphaBeta hmm recipLikelihood xs alphas betas = zipWith3 (\x alpha0 beta1 ->- Vector.scale recipLikelihood $+ Matrix.scale recipLikelihood $ biscaleTransition hmm x alpha0 beta1) (NonEmpty.tail xs) (NonEmpty.init alphas)@@ -169,7 +165,7 @@ zetaFromXi :: (Shape.C sh, Eq sh, Class.Real prob) =>- [SquareMatrix sh prob] -> [Vector sh prob]+ [Matrix.Square sh prob] -> [Vector sh prob] zetaFromXi = map Matrix.columnSums zetaFromAlphaBeta ::@@ -191,35 +187,41 @@ than the smallest representable number. -} reveal ::- (Shape.InvIndexed sh, Shape.Index sh ~ state,- Eq sh, sh ~ Distr.StateShape distr, Distr.EmissionProb distr,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission,- Traversable f) =>- T distr sh prob -> NonEmpty.T f emission -> NonEmpty.T f state-reveal hmm (NonEmpty.Cons x xs) =- fmap (Shape.revealIndex (StorableArray.shape $ initial hmm)) $+ (Distr.EmissionProb typ, Shape.InvIndexed sh, Eq sh, Shape.Index sh ~ state,+ Distr.Emission typ prob ~ emission, Class.Real prob, Traversable f) =>+ T typ sh prob -> NonEmpty.T f emission -> NonEmpty.T f state+reveal = revealGen id++revealGen ::+ (Distr.EmissionProb typ, Shape.InvIndexed sh, Eq sh, Shape.Index sh ~ state,+ Distr.Emission typ prob ~ emission, Class.Real prob, Traversable f) =>+ (Vector (Shape.Deferred sh) prob -> Vector (Shape.Deferred sh) prob) ->+ T typ sh prob -> NonEmpty.T f emission -> NonEmpty.T f state+revealGen normalize hmm =+ fmap (Shape.revealIndex (StorableArray.shape $ initial hmm)) .+ revealStorable normalize (mapStatesShape Shape.Deferred hmm)++revealStorable ::+ (Distr.EmissionProb typ, Shape.InvIndexed sh, Eq sh,+ Shape.Index sh ~ state, Storable state,+ Distr.Emission typ prob ~ emission, Class.Real prob, Traversable f) =>+ (Vector sh prob -> Vector sh prob) ->+ T typ sh prob -> NonEmpty.T f emission -> NonEmpty.T f state+revealStorable normalize hmm (NonEmpty.Cons x xs) = uncurry (NonEmpty.scanr (StorableArray.!)) $- mapFst- (fst . Vector.argAbsMaximum .- StorableArray.mapShape Shape.Deferred) $+ mapFst (fst . Vector.argAbsMaximum) $ mapAccumL (\alphai xi -> swap $ mapSnd (Vector.mul (emission hmm xi)) $- matrixMaxMul (transition hmm) alphai)+ matrixMaxMul (transition hmm) $ normalize alphai) (Vector.mul (emission hmm x) (initial hmm)) xs matrixMaxMul ::- (Shape.Indexed sh, Eq sh, Shape.Index sh ~ ix, Class.Real a) =>- SquareMatrix sh a -> Vector sh a ->- (Vector (Shape.Deferred sh) (Shape.DeferredIndex ix), Vector sh a)-matrixMaxMul m v =- let sh = StorableArray.shape v- in mapPair (Vector.fromList (Shape.Deferred sh), Vector.fromList sh) $- unzip $- map (Vector.argAbsMaximum .- StorableArray.mapShape Shape.Deferred .- Vector.mul v) $- Matrix.toRows m+ (Shape.InvIndexed sh, Eq sh, Shape.Index sh ~ ix, Storable ix,+ Class.Real a) =>+ Matrix.Square sh a -> Vector sh a ->+ (Vector sh ix, Vector sh a)+matrixMaxMul m v = Matrix.rowArgAbsMaximums $ Matrix.scaleColumns v m @@ -239,35 +241,35 @@ * derive it from state sequence patterns, cf. "Math.HiddenMarkovModel.Pattern". -}-data Trained distr sh prob =+data Trained typ sh prob = Trained { trainedInitial :: Vector sh prob,- trainedTransition :: SquareMatrix sh prob,- trainedDistribution :: distr+ trainedTransition :: Matrix.Square sh prob,+ trainedDistribution :: Distr.Trained typ sh prob } deriving (Show) instance- (NFData distr, NFData sh, NFData prob, Storable prob) =>- NFData (Trained distr sh prob) where+ (Distr.NFData typ, NFData sh, Shape.C sh, NFData prob, Storable prob) =>+ NFData (Trained typ sh prob) where rnf hmm = rnf (trainedInitial hmm, trainedTransition hmm, trainedDistribution hmm) sumTransitions :: (Shape.C sh, Eq sh, Class.Real e) =>- T distr sh e -> [SquareMatrix sh e] -> SquareMatrix sh e+ T typ sh e -> [Matrix.Square sh e] -> Matrix.Square sh e sumTransitions hmm =- List.foldl' Vector.add- (Vector.constant (StorableArray.shape $ transition hmm) 0)+ List.foldl' Matrix.add $+ Matrix.zero $ ArrMatrix.shape $ transition hmm {- | Baum-Welch algorithm -} trainUnsupervised ::- (Distr.Estimate tdistr distr, Distr.StateShape distr ~ sh, Eq sh,- Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>- T distr sh prob -> NonEmpty.T [] emission -> Trained tdistr sh prob+ (Distr.Estimate typ, Shape.C sh, Eq sh, Class.Real prob,+ Distr.Emission typ prob ~ emission) =>+ T typ sh prob -> NonEmpty.T [] emission -> Trained typ sh prob trainUnsupervised hmm xs = let (recipLikelihood, alphas, betas) = alphaBeta hmm xs zetas = zetaFromAlphaBeta recipLikelihood alphas betas@@ -279,37 +281,31 @@ sumTransitions hmm $ xiFromAlphaBeta hmm recipLikelihood xs alphas betas, trainedDistribution =- Distr.accumulateEmissions $- Array.fromList (StorableArray.shape zeta0) $- map (zip (NonEmpty.flatten xs)) $- List.transpose $ map Vector.toList $ NonEmpty.flatten zetas+ Distr.accumulateEmissionVectors $ NonEmptyC.zip xs zetas } mergeTrained ::- (Shape.C sh, Eq sh,- Distr.Estimate tdistr distr, Distr.Probability distr ~ prob) =>- Trained tdistr sh prob -> Trained tdistr sh prob -> Trained tdistr sh prob+ (Distr.Estimate typ, Shape.C sh, Eq sh, Class.Real prob) =>+ Trained typ sh prob -> Trained typ sh prob -> Trained typ sh prob mergeTrained hmm0 hmm1 = Trained { trainedInitial = Vector.add (trainedInitial hmm0) (trainedInitial hmm1), trainedTransition =- Vector.add (trainedTransition hmm0) (trainedTransition hmm1),+ Matrix.add (trainedTransition hmm0) (trainedTransition hmm1), trainedDistribution =- Distr.combine- (trainedDistribution hmm0) (trainedDistribution hmm1)+ trainedDistribution hmm0 <> trainedDistribution hmm1 } instance- (Shape.C sh, Eq sh,- Distr.Estimate tdistr distr, Distr.Probability distr ~ prob) =>- Sg.Semigroup (Trained tdistr sh prob) where+ (Distr.Estimate typ, Shape.C sh, Eq sh, Class.Real prob) =>+ Sg.Semigroup (Trained typ sh prob) where (<>) = mergeTrained toCells ::- (Distr.ToCSV distr, Shape.Indexed sh, Class.Real prob, Show prob) =>- T distr sh prob -> [[String]]+ (Distr.ToCSV typ, Shape.Indexed sh, Class.Real prob, Show prob) =>+ T typ sh prob -> [[String]] toCells hmm = (HMMCSV.cellsFromVector $ initial hmm) : (HMMCSV.cellsFromSquare $ transition hmm) ++@@ -317,9 +313,9 @@ (Distr.toCells $ distribution hmm) parseCSV ::- (Distr.FromCSV distr, Distr.StateShape distr ~ stateSh, Shape.C stateSh,+ (Distr.FromCSV typ, Shape.C stateSh, Eq stateSh, Class.Real prob, Read prob) =>- (Int -> stateSh) -> HMMCSV.CSVParser (T distr stateSh prob)+ (Int -> stateSh) -> HMMCSV.CSVParser (T typ stateSh prob) parseCSV makeShape = do v <- StorableArray.mapShape (makeShape . Shape.zeroBasedSize) <$>
src/Math/HiddenMarkovModel/Test.hs view
@@ -11,8 +11,10 @@ import qualified Math.HiddenMarkovModel.Normalized as Normalized import qualified Math.HiddenMarkovModel.Private as Priv import qualified Math.HiddenMarkovModel.Distribution as Distr-import Math.HiddenMarkovModel.Utility (SquareMatrix, squareFromLists, distance)+import Math.HiddenMarkovModel.Utility+ (squareFromLists, distance, matrixDistance) +import qualified Numeric.LAPACK.Matrix as Matrix import qualified Numeric.LAPACK.Vector as Vector import qualified Numeric.LAPACK.ShapeStatic as ShapeStatic import Numeric.LAPACK.Vector (Vector)@@ -30,10 +32,12 @@ import Control.DeepSeq (deepseq) import qualified Data.NonEmpty.Class as NonEmptyC+import qualified Data.NonEmpty.Map as NonEmptyMap import qualified Data.NonEmpty as NonEmpty import qualified Data.Traversable as Trav import qualified Data.Foldable as Fold import qualified Data.Map as Map+import Data.NonEmpty ((!:)) import Data.Tuple.HT (mapSnd) import Text.Printf (printf)@@ -53,8 +57,8 @@ stateVector 0.1 0.1 0.2 0.8 : [], HMM.distribution =- Distr.Discrete $ Map.fromList $- ('a', stateVector 1 0 0 0) :+ Distr.discreteFromList $+ ('a', stateVector 1 0 0 0) !: ('b', stateVector 0 1 0 1) : ('c', stateVector 0 0 1 0) : []@@ -83,8 +87,7 @@ 1 -> True _ -> error "invalid emission probability (must be 0 or 1)") $ Vector.toList $- Map.findWithDefault (error "invalid character") c $- case HMM.distribution hmm of Distr.Discrete m -> m+ case HMM.distribution hmm of Distr.Discrete m -> Matrix.takeRow m c {- | Should all be equal.@@ -140,7 +143,7 @@ {- | Lists should be equal -}-xis :: ([SquareMatrix StateSet Double], [SquareMatrix StateSet Double])+xis :: ([Matrix.Square StateSet Double], [Matrix.Square StateSet Double]) xis = let (recipLikelihood, alphas, betas) = Priv.alphaBeta hmm sequ in (Priv.xiFromAlphaBeta hmm recipLikelihood sequ alphas betas,@@ -153,7 +156,8 @@ xisDiff :: (Bool, Double) xisDiff = case xis of- (x0,x1) -> (length x0 == length x1, maximum $ zipWith distance x0 x1)+ (x0,x1) ->+ (length x0 == length x1, maximum $ zipWith matrixDistance x0 x1) reveal :: Bool@@ -172,13 +176,16 @@ trainUnsupervisedDiff = case trainUnsupervised of (hmm0,hmm1) ->- (distance (Priv.trainedTransition hmm0) (Priv.trainedTransition hmm1),+ (matrixDistance+ (Priv.trainedTransition hmm0) (Priv.trainedTransition hmm1), distance (Priv.trainedInitial hmm0) (Priv.trainedInitial hmm1), case (Priv.trainedDistribution hmm0, Priv.trainedDistribution hmm1) of (Distr.DiscreteTrained m0, Distr.DiscreteTrained m1) ->- (Map.size m0 == Map.size m1,- Fold.maximum $ Map.intersectionWith distance m0 m1))+ (NonEmptyMap.size m0 == NonEmptyMap.size m1,+ Fold.maximum $+ Map.intersectionWith distance+ (NonEmptyMap.flatten m0) (NonEmptyMap.flatten m1))) nonEmptyScanr :: Int -> [Int] -> Bool
src/Math/HiddenMarkovModel/Utility.hs view
@@ -4,10 +4,12 @@ import qualified Numeric.LAPACK.Matrix.Hermitian as Hermitian import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix import qualified Numeric.LAPACK.Matrix as Matrix import qualified Numeric.LAPACK.Vector as Vector import Numeric.LAPACK.Matrix.Triangular (Diagonal)-import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Matrix.Array (ArrayMatrix)+import Numeric.LAPACK.Vector (Vector, (.*|)) import qualified Numeric.Netlib.Class as Class @@ -22,15 +24,13 @@ import qualified Control.Monad.Trans.State as MS -type SquareMatrix sh = Square.Square sh- normalizeProb :: (Shape.C sh, Class.Real a) => Vector sh a -> Vector sh a normalizeProb = snd . normalizeFactor normalizeFactor :: (Shape.C sh, Class.Real a) => Vector sh a -> (a, Vector sh a) normalizeFactor xs = let c = Vector.sum xs- in (c, Vector.scale (recip c) xs)+ in (c, recip c .*| xs) -- see htam:Stochastic randomItemProp ::@@ -57,11 +57,13 @@ squareConstant ::- (Shape.C sh, Class.Real a) => sh -> a -> SquareMatrix sh a-squareConstant = Vector.constant . MatrixShape.square MatrixShape.RowMajor+ (Shape.C sh, Class.Real a) => sh -> a -> Matrix.Square sh a+squareConstant =+ (ArrMatrix.fromVector .) .+ Vector.constant . MatrixShape.square MatrixShape.RowMajor squareFromLists ::- (Shape.C sh, Eq sh, Storable a) => sh -> [Vector sh a] -> SquareMatrix sh a+ (Shape.C sh, Eq sh, Storable a) => sh -> [Vector sh a] -> Matrix.Square sh a squareFromLists sh = Square.fromGeneral . Matrix.fromRowArray sh . Array.fromList sh @@ -79,3 +81,8 @@ Class.switchReal (Distance $ (Vector.normInf .) . Vector.sub) (Distance $ (Vector.normInf .) . Vector.sub)++matrixDistance ::+ (Shape.C sh, Eq sh, Class.Real a) =>+ ArrayMatrix sh a -> ArrayMatrix sh a -> a+matrixDistance a b = distance (ArrMatrix.toVector a) (ArrMatrix.toVector b)