JuliaMath / JuliaMath/MeasureTheory.jl

Specifying "outer" type for `rand`

Open
#129 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Julia
Stars
401
Forks
31
PR merge metrics
No merged PRs in 30d

Description

On the Julia Slack, @sethaxen asked
> When calling rand on a measure, we need some information about what kind of object should be returned. e.g. how would a user request that `rand(::Hausdorff(Sphere(2)))` return some `SphericalCoordinateVector` type or an `SVector{3}` instead of a boring `Vector`?
>
> Currently this requires storing a point of the intended type in the measure,
`Hausdorff(Sphere(2), randn(3))` so the rand function can call similar. But this is a little clunky if one wants to use this in a PPL. Does MeasureTheory have a solution here?

Great question, I've been fighting with this for a while. Some ideas...

First, we took @devmotion’s suggestion of including an optional float type in the `rand` call. This propagates downward, until eventually influencing the call to `rand(::Type, ::AbstractRNG)`. This is a sort of "inner type".

1. One option would be to have an optional first argument for the "outer type", the constructor for the type to be returned. One issue here is that if the result is nested, say a vector of vectors, it can be awkward to describe in this way. Doesn't seem to compose well.

2. Next, we could base this entirely off the parameters. If you have an `MvNormal` where the mean is a `StaticArray`, maybe you should get another in return. But this is less flexible, and doesn't allow for cases where there's no parameter with the same structure. Just checked again, and see your concern on this as well.

3. Another concern is allocation. So maybe we could have the low-level work entirely in terms of `rand!` Then each user-level `rand` would involve constructing an `undef` and then calling `rand` on the result. I kind of like this one, but for composability we'd also need a way to specify an unboxed array element. This could also maybe work like (1). So far I kind of like this one.

4. Another idea I've played with is to not allocate at all. If samples are sequential, maybe the returned result should be a generator? Then, like (3), the top level could allocate and then traverse the structure and generator together, writing as it goes. This could be ok, but it forces sequential access, and I'm not sure if there's overhead in a traversal like this.

5. Finally, we could do something similar, but always use a StrideArray. This would make it easy to avoid allocation altogether when we know the size statically, and we could copy it into a different structure at the end, similar to (4). But this would require lots of inlining and `GC.@preserve` s throughout the code, and I think there could be big problems for very large results.

These are all just ideas, but so far (3) seems the best to me.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.