InfiniteArrays.jl icon indicating copy to clipboard operation
InfiniteArrays.jl copied to clipboard

Infinite random sequence

Open stla opened this issue 4 years ago • 1 comments

Hello,

I don't know whether this is possible (it is in Haskell) nor whether this would fit the scope of this library but infinite random sequences would be a nice feature.

Cheers.

stla avatar Jan 09 '21 03:01 stla

I agree. This should be pretty easy to implement as <: AbstractCachedArray, by storing the seed for the last computed entry.

alternatively one could make it completely unallocating by only storing the seed for the first entry, though this will make getindex slow

dlfivefifty avatar Jan 09 '21 08:01 dlfivefifty

Did this ever get implemented anywhere? Something like

using LazyArrays: LazyArrays, AbstractCachedVector
using Random
using InfiniteArrays
mutable struct InfRandVector{T,RNG} <: AbstractCachedVector{T}
    const rng::RNG
    const data::Vector{T}
    datasize::Int
end
InfRandVector{T}(rng::RNG) where {T, RNG} = (_rng = copy(rng); InfRandVector{T,typeof(_rng)}(_rng, T[], 0)) # copy(rng) can have different type to rng
function InfRandVector(rng::RNG=Random.default_rng()) where {RNG}
    _rng = copy(rng) # don't disrupt seed
    T = typeof(rand(_rng))
    return InfRandVector{T}(rng)
end

Base.size(::InfRandVector) = ℵ₀
Base.axes(::InfRandVector) = (1:ℵ₀,)
Base.length(::InfRandVector) = ℵ₀
function LazyArrays.resizedata!(seq::InfRandVector{T}, inds) where {T}
    newlen = maximum(inds)
    curlen = length(seq.data)
    newlen > curlen || return seq
    resize!(seq.data, newlen)
    # rand!(seq.rng, view(seq.data, curlen+1:newlen), T)
    # ^ rand() is not actually sequential.. rand(Random.seed!(123), 1000) ≠ (rng = Random.seed!(123); [rand(rng) for _ in 1:1000])
    for i in (curlen+1):newlen 
        seq.data[i] = rand(seq.rng, T)
    end
    seq.datasize = newlen
    return seq
end

using Test 
seq = InfRandVector(Random.seed!(Random.default_rng(), 123))
@test seq[1] == seq[1]
val = seq[1]
@test seq[1:10000] == seq[1:10000]
@test seq[1] == val # didn't change after resizing
@inferred seq[1]
rng = Random.seed!(123)
_seq = [rand(rng) for _ in 1:1000]
@test _seq[1:1000] == seq[1:1000]

seems to work.

DanielVandH avatar Jun 17 '24 19:06 DanielVandH