-- | Deterministic and probabilistic generatorsmoduleNumeric.Probability.TransitionwhereimportqualifiedNumeric.Probability.Distribution asDistimportqualifiedNumeric.Probability.Either asPEimportqualifiedData.MapasMapimportqualifiedData.List.HTasListHTimportqualifiedData.ListasListimportPreludehiding(map,maybe,id,)-- * Transitions-- | deterministic generatortypeChange a =a ->a -- | probabilistic generatortypeT prob a =a ->Dist.T prob a id::(Numprob )=>T prob a id =Dist.certainly {- | 'map' maps a change function to the result of a transformation ('map' is somehow a lifted form of 'Dist.map') The restricted type of @f@ results from the fact that the argument to @t@ cannot be changed to @b@ in the result 'T' type. -}map::(Numprob ,Orda )=>Change a ->T prob a ->T prob a map f t =Dist.map f .t {- | unfold a distribution of transitions into one transition NOTE: The argument transitions must be independent -}unfold::(Numprob ,Orda )=>Dist.T prob (T prob a )->T prob a unfold d x =Dist.unfold (fmap($x )d ){- | Composition of transitions similar to 'Numeric.Probability.Monad.compose' but with intermediate duplicate elimination. -}compose::(Numprob ,Orda )=>[T prob a ]->T prob a compose =foldl(\acc x v ->Dist.norm (acc v >>=x ))returnuntilLeft::(Numprob ,Orda ,Ordb )=>(a ->Dist.T prob (Eitherb a ))->Dist.T prob a ->Dist.T prob b untilLeft f =letgo final dist =ifnull(Dist.deconsdist )thenDist.Cons $Map.toListfinal elsecaseListHT.unzipEithers$List.map(\(e ,p )->either(\l ->Left(l ,p ))(\r ->Right(r ,p ))e )$Dist.decons$Dist.norm $dist >>=f of(newFinal ,stillActive )->go (Map.unionWith(+)(Map.fromListWith(+)newFinal )final )$Dist.Cons stillActive ingo Map.empty{- | In @fix $ \go a -> do ...; go xy@ any action after a 'go' is ignored. -}fix::(Numprob ,Orda ,Ordb )=>((a ->PE.EitherT a (Dist.T prob )b )->(a ->PE.EitherT a (Dist.T prob )b ))->Dist.T prob a ->Dist.T prob b fix f =untilLeft $\a ->casef PE.throw a ofPE.EitherT m ->fmap(eitherRightLeft)m -- * Spreading changes into transitions-- | functions to convert a list of changes into a transitiontypeSpreadC prob a =[Change a ]->T prob a apply::(Numprob )=>Change a ->T prob a apply f =id .f maybe::(Numprob )=>prob ->Change a ->T prob a maybe p f x =Dist.choose p (f x )x lift::Dist.Spread prob a ->SpreadC prob a lift s cs x =s $List.map($x )cs uniform::(Fractionalprob )=>SpreadC prob a uniform =lift Dist.uniform linear::(Fractionalprob )=>SpreadC prob a linear =lift Dist.linear normal::(Floatingprob )=>SpreadC prob a normal =lift Dist.normal enum::(RealFloatprob )=>[Int]->SpreadC prob a enum xs =lift (Dist.enum xs )relative::(RealFloatprob )=>[prob ]->SpreadC prob a relative xs =lift (Dist.relative xs )-- * Spreading transitions into transitions-- | functions to convert a list of transitions into a transitiontypeSpreadT prob a =[T prob a ]->T prob a liftT::(Numprob ,Orda )=>Dist.Spread prob (T prob a )->SpreadT prob a liftT s =unfold .s uniformT::(Fractionalprob ,Orda )=>SpreadT prob a uniformT =liftT Dist.uniform linearT::(Fractionalprob ,Orda )=>SpreadT prob a linearT =liftT Dist.linear normalT::(Floatingprob ,Orda )=>SpreadT prob a normalT =liftT Dist.normal enumT::(RealFloatprob ,Orda )=>[Int]->SpreadT prob a enumT xs =liftT (Dist.enum xs )relativeT::(RealFloatprob ,Orda )=>[prob ]->SpreadT prob a relativeT xs =liftT (Dist.relative xs )