JuliaApproximation / DomainSets.jl

A Julia package for describing domains as continuous sets of elements
MIT License
72 stars 12 forks source link

VcatDomain(ℝ, ℕ) causes MethodError #154

Closed msagarpatel closed 7 months ago

msagarpatel commented 7 months ago

I may be misunderstanding the intended use of VcatDomain, but I assumed it represents a Cartesian Product based on this code: https://github.com/JuliaApproximation/DomainSets.jl/blob/3b914a2b81015c706e6ea7f4be1444eb58c6d49b/src/domains/numbers.jl#L64-L71

So, I tried to represent $\mathbb{R} \times \mathbb{N}$, but was met with an error:

julia> using DomainSets

julia> VcatDomain(ℝ, ℕ)
ERROR: MethodError: no method matching similardomain(::DomainSets.NaturalNumbers, ::Type{Float64})

Closest candidates are:
  similardomain(::IntersectDomain, ::Type{T}) where T
   @ DomainSets ~/.julia/packages/DomainSets/0afEf/src/generic/setoperations.jl:255
  similardomain(::IndicatorFunction, ::Type{T}) where T
   @ DomainSets ~/.julia/packages/DomainSets/0afEf/src/domains/indicator.jl:35
  similardomain(::EmptySpace, ::Type{T}) where T
   @ DomainSets ~/.julia/packages/DomainSets/0afEf/src/domains/trivial.jl:13
  ...

Stacktrace:
  [1] convert(::Type{Domain{Float64}}, d::DomainSets.NaturalNumbers)
    @ DomainSets ~/.julia/packages/DomainSets/0afEf/src/generic/domain.jl:17
  [2] convert_numtype(d::DomainSets.NaturalNumbers, ::Type{Float64})
    @ DomainSets ~/.julia/packages/DomainSets/0afEf/src/generic/domain.jl:9
  [3] _broadcast_getindex_evalf(::typeof(convert_numtype), ::DomainSets.NaturalNumbers, ::Type)
    @ Base.Broadcast ./broadcast.jl:709
  [4] _broadcast_getindex
    @ Base.Broadcast ./broadcast.jl:697 [inlined]
  [5] (::Base.Broadcast.var"#31#32"{Base.Broadcast.Broadcasted{…}})(k::Int64)
    @ Base.Broadcast ./broadcast.jl:1118
  [6] ntuple
    @ Base ./ntuple.jl:49 [inlined]
  [7] copy(bc::Base.Broadcast.Broadcasted{Base.Broadcast.Style{…}, Nothing, typeof(convert_numtype), Tuple{…}})
    @ Base.Broadcast ./broadcast.jl:1118
  [8] materialize
    @ ./broadcast.jl:903 [inlined]
  [9] (VcatDomain{2, Float64})(::RealNumbers, ::Vararg{Any})
    @ DomainSets ~/.julia/packages/DomainSets/0afEf/src/generic/productdomain.jl:134
 [10] VcatDomain(::RealNumbers, ::Vararg{Any})
    @ DomainSets ~/.julia/packages/DomainSets/0afEf/src/generic/productdomain.jl:128
 [11] top-level scope
    @ REPL[33]:1
Some type information was truncated. Use `show(err)` to see complete types.
daanhb commented 7 months ago

Sorry for the lack of documentation. The VcatDomain will concatenate its elements into a vector, in the process promoting them as in

julia> vcat(2.3, 5)
2-element Vector{Float64}:
 2.3
 5.0

The set of natural numbers can not be promoted to have Float64 type, that is why you're getting an error.

The VcatDomain is a concrete subtype of ProductDomain. The more generic function productdomain decides, based on the arguments, which concrete subtype of ProductDomain is most suited to return. However, that will also fail here, because by default it chooses VcatDomain for domains with scalar eltypes.

The type you're probably after is TupleProductDomain, which represents its elements as a Tuple rather than a Vector and which doesn't promote them:

julia> d = TupleProductDomain(ℝ, ℕ)
RealNumbers() × NaturalNumbers()

julia> eltype(d)
Tuple{Float64, Int64}

julia> (2.3,5) ∈ d
true

Alternatively, you could type ProductDomain{Tuple{Float64,Int}}(ℝ, ℕ).

msagarpatel commented 7 months ago

Thank you, @daanhb! That makes sense.