Markov chain as an iterable

I want to provide an iteration interface for a Markov chain, eg MWE:

using Random

struct RandomWalk{G, T}
    σ::T
    rng::G
end

RandomWalk(σ) = RandomWalk(σ, Random.GLOBAL_RNG)

Base.iterate(rw::RandomWalk, x = 0.0) = x, x + rw.σ*randn()
Base.IteratorSize(::RandomWalk) = Base.IsInfinite()
collect(Iterators.take(RandomWalk(0.2), 10))

The only question is how to specify the initial state. The only solution I could come up with is a wrapper type

struct RandomWalkInit{R <: RandomWalk,S}
    rw::R
    x₀::S
end

Base.iterate(rwi::RandomWalkInit, x = rwi.x₀) = Base.iterate(rwi.rw, x)
Base.IteratorSize(::RandomWalkInit) = Base.IsInfinite()
collect(Iterators.take(RandomWalkInit(RandomWalk(0.2), -3.0), 10))

but I wonder if there is anything simpler — the above just introduces a type for delegating code.

1 Like