tpapp / TransformVariables.jl

Transformations to contrained variables from ℝⁿ.
Other
66 stars 14 forks source link

Inverse transformation for empty vectors fails #73

Open sdewaele opened 4 years ago

sdewaele commented 4 years ago

I am working on an algorithm where I want to define a transformation for a vector of length p. Importantly, p may be zero. This transformation is part of a tuple of transformations. Therefore, the final full parameter vector has a non-zero dimension. What I have done in the past is to omit the zero-dimensional transform, but this leads to additional coding to "compensate" for the missing element. Also, I think it can result in type instability.

I can define a transform for a vector of dimension zero. Also, the forward transform does work:

julia> trans = as(Vector,0)
TransformVariables.ArrayTransform{TransformVariables.Identity,1}(asℝ, (0,))
julia> trans([])
0-element Array{Any,1}

However, the inverse transform fails:

julia> inverse(trans,[])
ERROR: BoundsError: attempt to access 0-element Array{Any,1} at index [1]
Stacktrace:
 [1] getindex at ./array.jl:788 [inlined]
 [2] first at ./abstractarray.jl:323 [inlined]
 [3] inverse_eltype(::TransformVariables.ArrayTransform{TransformVariables.Identity,1}, ::Array{Any,1}) at /home/student/.julia/packages/TransformVariables/gAt5r/src/aggregation.jl:78
 [4] inverse(::TransformVariables.ArrayTransform{TransformVariables.Identity,1}, ::Array{Any,1}) at /home/student/.julia/packages/TransformVariables/gAt5r/src/generic.jl:236
 [5] top-level scope at REPL[47]:1
 [6] eval(::Module, ::Any) at ./boot.jl:331
 [7] eval_user_input(::Any, ::REPL.REPLBackend) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [8] run_backend(::REPL.REPLBackend) at /home/student/.julia/packages/Revise/Pcs5V/src/Revise.jl:1073
 [9] top-level scope at none:0

It would be great if this could work.

Just as a thought - I am not sure if this makes sense in the grand scheme of things - but perhaps this and other cases could be handled by having the option to define the transform for a constant? This would also have a zero-dimensional parameter space, and zero jacobian.

tpapp commented 4 years ago

I am open to the idea of having a constant, but wouldn't that also violate type stability? You would have to special case 0-length (I am assuming that lengths are known at runtime, not compile time). Also, would it thrown an error when the input of inverse is not == that constant?

The way this library is currently written makes special-casing this kind of tricky in a type-stable way even for arrays, but I will think about it.