···3636-- | Utility Functions
37373838-- | Multiply each number by a constant such that the sum is 1.0
3939-4039normalise :: (Fractional a, Foldable f, Functor f) => f a -> f a
4140normalise xs | null xs = xs
4241 | otherwise =
···108107sensorDiagonal :: (KnownNat s, KnownNat t, Eq b) => HMM s t a b -> b -> Maybe (SensorDiagonal s a)
109108sensorDiagonal hmm e = findIndexOf (sDist.folded) (== e) hmm >>= (\i -> hmm ^? sModel . ix i)
110109110110+-- | Filtering message propagated forward
111111+forward :: (KnownNat s) => HMM s t R b -> SensorDiagonal s R -> Message s R -> Message s R
112112+forward hmm ot f = normalise (ot !*! Linear.transpose (hmm ^. tModel) !*! f)
113113+114114+-- | Smoothing message propagated backward
115115+backward :: (KnownNat s) => HMM s t R b -> SensorDiagonal s R -> Message s R -> Message s R
116116+backward hmm ok1 bk2 = (hmm ^. tModel) !*! ok1 !*! bk2
117117+118118+111119-- | Fixed Lag Smoothing
112120113121-- | Persistent State
···122130-- | State to start with
123131persistentInit :: forall s b d. (KnownNat s, Integral d) => Message s R -> Persistent s R b d
124132persistentInit p = Persistent { _t = 1, _f_msg = p, _b = identity, _e_td_t = Vec.empty}
125125-126126--- | Filtering message propagated forward
127127-forward :: (KnownNat s) => HMM s t R b -> SensorDiagonal s R -> Message s R -> Message s R
128128-forward hmm ot f = normalise (ot !*! Linear.transpose (hmm ^. tModel) !*! f)
129129-130130--- | Smoothing message propagated backward
131131-backward :: (KnownNat s) => HMM s t R b -> SensorDiagonal s R -> Message s R -> Message s R
132132-backward hmm ok1 bk2 = (hmm ^. tModel) !*! ok1 !*! bk2
133133-134133135134-- | Online Algorithm for smoothing with a fixed time lag of `d` steps
136135-- hmm -- HMM model
···166165-- evs - list of evidences for each time step
167166forwardBackward :: forall s t u b . (KnownNat t, KnownNat s, KnownNat u, Eq b) => HMM s u R b -> V t b -> V t (Distribution s R)
168167forwardBackward hmm evs = let
169169- -- forward messages
168168+ -- reifying the number of evidences
169169+ tNat = dim evs
170170+ -- forward messages from time t .. 0
170171 fv :: V (t + 1) (Message s R)
171172 fv = V $ Vec.fromList $ foldl' (\m@(x:_) e -> forward hmm (sensorDiagonal hmm e ^?! _Just) x : m) [hmm ^. prior] evs
172172- -- reifying the number of evidences
173173- tNat = dim evs
174173 -- getting rid of the prior message from the end of the list
174174+ -- so now forward messages vector is from time t .. 1
175175 fv_0 :: V t (Message s R)
176176 fv_0 = V $ Vec.fromList $ fv ^.. taking tNat traversed
177177- -- backward messages
177177+178178+ -- backward messages from time 1 .. t
178179 bs :: V t (Message s R)
179180 bs = V $ Vec.fromList $ foldl' (\m@(x:_) e -> backward hmm (sensorDiagonal hmm e ^?! _Just) x : m) [unitColumn] $ reverseV evs
181181+ -- reversing the backward messages
182182+ -- so now the backward messages vector is from time t .. 1
183183+ revBs :: V t (Message s R)
184184+ revBs = reverseV bs
180185 in
181186 -- smoothing probabilities in reverse order of the list of evidences
182182- liftA2 (\f b' -> extract1 $ normalise $ f !**! b') fv_0 (reverseV bs)
187187+ -- i.e. starting from time t .. 1
188188+ liftA2 (\f b' -> extract1 $ normalise $ f !**! b') fv_0 revBs
183189184190-- | execution
185191umbrellaHMM :: HMM 2 2 R Bool
186192umbrellaHMM = mkHMM1 (V2 (V2 0.7 0.3) (V2 0.3 0.7)) (V2 (V2 0.9 0.2) (V2 0.1 0.8))
187193188188-runFLSAlgo :: [Bool] -> [Maybe (Distribution 2 String)]
189189-runFLSAlgo bs = let hmm = mkHMM1 (V2 (V2 0.7 0.3) (V2 0.3 0.7)) (V2 (V2 0.9 0.2) (V2 0.1 0.8))
190190- initState = persistentInit (V $ Vec.fromList [V $ Vec.singleton 0.5, V $ Vec.singleton 0.5]) :: Persistent 2 R Bool Integer
191191- algo = fixedLagSmoothing hmm 1
192192- a :: ([Maybe (Distribution 2 R)], Persistent 2 R Bool Integer)
193193- a = foldl' (\(rs, s) x -> runState (runMaybeT $ algo x) s & _1 #%~ ((rs ++) . pure)) ([], initState) bs
194194- in
195195- (a ^. _1) & traverse.traverse.traverse %~ \(x :: R) -> printf "%.3f" x :: String
194194+runFLSAlgo :: [Bool] -> Integer -> [Maybe (Distribution 2 String)]
195195+runFLSAlgo bs d = let hmm = mkHMM1 (V2 (V2 0.7 0.3) (V2 0.3 0.7)) (V2 (V2 0.9 0.2) (V2 0.1 0.8))
196196+ initState = persistentInit (V $ Vec.fromList [V $ Vec.singleton 0.5, V $ Vec.singleton 0.5]) :: Persistent 2 R Bool Integer
197197+ algo = fixedLagSmoothing hmm d
198198+ a :: ([Maybe (Distribution 2 R)], Persistent 2 R Bool Integer)
199199+ a = foldl' (\(rs, s) x -> runState (runMaybeT $ algo x) s & _1 #%~ ((rs ++) . pure)) ([], initState) bs
200200+ in
201201+ (a ^. _1) & traverse.traverse.traverse %~ \(x :: R) -> printf "%.3f" x :: String
196202197203198198-runFBAlgo :: (KnownNat t) =>V t Bool -> [Distribution 2 R]
199199-runFBAlgo bs = toList $ forwardBackward umbrellaHMM bs
204204+runFBAlgo :: [Bool] -> [Distribution 2 R]
205205+runFBAlgo bs = reifyVectorNat (Vec.fromList bs) (toList . forwardBackward umbrellaHMM)