Open tomerarnon opened 4 years ago
Thanks for the write-up! Food for thought. I'd love to have such conversions working as well.
julia> P = convert(HPolytope, BallInf(zeros(2), 1.0))
HPolytope{Float64,LazySets.Arrays.SingleEntryVector{Float64}}(HalfSpace{Float64,LazySets.Arrays.SingleEntryVector{Float64}}[HalfSpace{Float64,LazySets.Arrays.
SingleEntryVector{Float64}}([1.0, 0.0], 1.0), HalfSpace{Float64,LazySets.Arrays.SingleEntryVector{Float64}}([0.0, 1.0], 1.0), HalfSpace{Float64,LazySets.Array
s.SingleEntryVector{Float64}}([-1.0, 0.0], 1.0), HalfSpace{Float64,LazySets.Arrays.SingleEntryVector{Float64}}([0.0, -1.0], 1.0)])
julia> P = convert(HPolytope{Float64, Vector{Float64}}, BallInf(zeros(2), 1.0))
ERROR: MethodError: Cannot `convert` an object of type BallInf{Float64,Array{Float64,1}} to an object of type HPolytope{Float64,Array{Float64,1}}
Closest candidates are:
convert(::Type{T}, ::T) where T at essentials.jl:171
Stacktrace:
I didn't mention this, but I don't know whether performing the conversion in two steps like proposed is less efficient than defining a direct conversion method, and if so, whether inlining could help or not. That's something probably worth knowing though in case this is a desirable direction.
This proposal is related to #1182 #965, and maybe other issues that have to do with conversion (and promotion).
Currently, a number of convenient conversions are missing. Defining every possible conversion seems infeasible, but I think with a few steps, you can get almost all conversions you could reasonably want without having to deal with any of the combinatorial conversion problem. As concrete examples, I would love it if conversions like the following were possible.
The proposal to allow this, and other such conversions, is the following:
convert
methods necessary to change its stored types. BasicallyL{N} -> L{M}
must be defined for each type. I think this requires as many functions as parameters. While this is still a lot of conversions, it is independently convenient to have. (For someone cleverer than me, maybe this can be done with fewer methods, like with a fancy inner constructor, or even with a macro...)For HalfSpaces, consider
These two methods allow conversions like the following:
1a. Once lower level conversions exist, higher level ones can be built on top of them. Consider
HPolytope
, which relies onHalfSpace
Now we can also do things like
L{N} -> L{M}
. However,L{N} -> S{N}
already exists in a lot of cases, as inconvert(HPolytope, hr)
, and we can and should take advantage of these! The last step is to break the conversion intoL{N} -> S{N} -> S{M}
, wherever both conversions are individually possible.get the "UnionAll name" from a type. E.g. _stripparameters(Vector{Int}) -> Vector
@inline _stripparameters(T::UnionAll) = _stripparameters(T.body) @inline _stripparameters(T::DataType) = T.name.wrapper
But these should exist anyway, so I don't consider this its own obstacle 😁
HPolytope(hr)
. I'm not sure if this contradicts the ethos behindconvert
for some types in LazySets, but if not, it can be achieved in general withThis part isn't really crucial for the rest of the proposal, but could be nice to have.
With all of the above combined, you could do basically anything: