Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a flatten function #22

Open
theogf opened this issue Dec 17, 2021 · 4 comments
Open

Add a flatten function #22

theogf opened this issue Dec 17, 2021 · 4 comments

Comments

@theogf
Copy link
Contributor

theogf commented Dec 17, 2021

In order to play with methods expecting a AbstractArray{<:isbits}, it would be great to have a flatten method such that

X = TupleVector(;w=rand(10), y=rand(10))
x, re = flatten(X)
re(x) == X

A direct possibility is to implement the ParameterHandling.jl interface but I know that would be an annoying dependency (Requires.jl could be used).
It could also be done very easily as a specific TupleVector function.

Do you think it belongs to this package?

@cscherrer
Copy link
Owner

Can you give some more detail on the application you have in mind? I do have a flatten in NestedTuples.jl, which is already a dependency. This flattens the nested tuples or nested named tuples, e.g.

julia> using TupleVectors, NestedTuples

julia> flatten(unwrap(X))
([0.748023, 0.536496, 0.697929, 0.0655981, 0.321656, 0.490697, 0.0419858, 0.739381, 0.643946, 0.362884], [0.688543, 0.260613, 0.484324, 0.323937, 0.14058, 0.51499, 0.887539, 0.210438, 0.318889, 0.0818039])

Also this may not be the best example, since

julia> X = TupleVector(;w=rand(10), y=rand(10))
10-element TupleVector with schema (w = Float64, y = Float64)
(w = 0.46±0.26, y = 0.39±0.25)

julia> isbits(X[1])
true

julia> isbitstype(eltype(X))
true

Are you maybe thinking of something like

julia> tv = TupleVector(;x=TupleVectors.chainvec(rand(2),1000), y=TupleVectors.chainvec(rand(3),1000));

julia> randn!(tv.x.data);

julia> randn!(tv.y.data);

julia> tv
1000-element TupleVector with schema (x = SubArray{Float64, 1, ElasticMatrix{Float64, Vector{Float64}}, Tuple{Slice{OneTo{Int64}}, Int64}, true}, y = SubArray{Float64, 1, ElasticMatrix{Float64, Vector{Float64}}, Tuple{Slice{OneTo{Int64}}, Int64}, true})
(x = [-0.06±0.99, -0.03±0.99], y = [0.0±1.0, 0.07±1.0, 0.093±0.99])

?

@theogf
Copy link
Contributor Author

theogf commented Jan 12, 2022

I do have a flatten in NestedTuples.jl, which is already a dependency.

This only solves one part of the problem. The later problem is how to reconstruct the appropriate TupleVector given its flattened representation.

@cscherrer
Copy link
Owner

If you think of a nested tuple as a tree, unflattening sets values at the leaves. So the terminology is a little weird, but there's a leaf_setter function that handles this.

julia> using TupleVectors

julia> using NestedTuples: flatten, leaf_setter

julia> using TupleVectors: unwrap

julia> x = TupleVector((;w=(rand(1:5, 10), rand(10)), y=rand(10)))
10-element TupleVector with schema (w = (Int64, Float64), y = Float64)
(w = (2.8±1.1, 0.39±0.25), y = 0.45±0.29)

julia> unflatten = leaf_setter(unwrap(x))
function = (##274, ##275, ##276;) -> begin
    begin
        (w = (var"##274", var"##275"), y = var"##276")
    end
end

julia> TupleVector(unflatten(1:10, 1:10, 1:10))
10-element TupleVector with schema (w = (Int64, Int64), y = Int64)
(w = (5.5±3.0, 5.5±3.0), y = 5.5±3.0)

@cscherrer
Copy link
Owner

Just to be sure we're talking about the same thing, this is very different from flattening each row of a TupleVector, or entirely flattening (so you just end up with a single array). Both of those are possible but would take some more machinery

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants