IntervalArithmetic.jl icon indicating copy to clipboard operation
IntervalArithmetic.jl copied to clipboard

nai() not working with rational intervals

Open lucaferranti opened this issue 4 years ago • 4 comments

At the moment nai(Rational) returns an error

julia> nai(Rational)
ERROR: InexactError: Int64(NaN)
Stacktrace:
 [1] Int64
   @ .\float.jl:723 [inlined]
 [2] rationalize(#unused#::Type{Int64}, x::Float64, tol::Int64)
   @ Base .\rational.jl:161
 [3] #rationalize#184
   @ .\rational.jl:216 [inlined]
 [4] Rational
   @ .\rational.jl:119 [inlined]
 [5] Rational
   @ .\rational.jl:123 [inlined]
 [6] convert(#unused#::Type{Rational}, x::Float64)
   @ Base .\number.jl:7
 [7] nai(#unused#::Type{Rational})
   @ IntervalArithmetic ~\.julia\dev\IntervalArithmetic\src\decorations\functions.jl:14
 [8] top-level scope
   @ REPL[25]:1

as Luis proposed, one solution might be to define

nai(::Rational) = DecoratedInterval(Interval(1//0, -1//0), ill)

I think this would work because NaI is allowed only as decorated interval and not as bare, hence it would not be confused with [1//0, -1//0]_trv which is the empty interval. This might require manually adjusting a couple of functions (at least hardcoding the printing for NaI and possibly checking that the current definitions of isnai and isnan still work), but other than that I don't see why it would not work.

lucaferranti avatar May 18 '21 18:05 lucaferranti

actually it seems decorated intervals with rationals do not work at all

julia> a = DecoratedInterval(1//2, 3//4)
ERROR: MethodError: no method matching atomic(::Type{Interval{Interval{Rational{Int64}}}}, ::Interval{Interval{Rational{Int64}}})
Closest candidates are:
  atomic(::Type{Interval{T}}, ::Interval) where T<:AbstractFloat at C:\Users\lucaa\.julia\dev\IntervalArithmetic\src\intervals\conversion.jl:122
  atomic(::Type{Interval{T}}, ::S) where {T<:AbstractFloat, S<:Real} at C:\Users\lucaa\.julia\dev\IntervalArithmetic\src\intervals\conversion.jl:79
Stacktrace:
 [1] convert(#unused#::Type{Interval{Interval{Rational{Int64}}}}, x::Interval{Interval{Rational{Int64}}})
   @ IntervalArithmetic ~\.julia\dev\IntervalArithmetic\src\intervals\conversion.jl:20
 [2] Interval{Interval{Interval{Rational{Int64}}}}(a::Interval{Interval{Rational{Int64}}}, b::Interval{Interval{Rational{Int64}}})
   @ IntervalArithmetic ~\.julia\dev\IntervalArithmetic\src\intervals\intervals.jl:33
 [3] Interval(a::Interval{Interval{Rational{Int64}}}, b::Interval{Interval{Rational{Int64}}})
   @ IntervalArithmetic ~\.julia\dev\IntervalArithmetic\src\intervals\intervals.jl:42
 [4] DecoratedInterval(a::Interval{Interval{Rational{Int64}}}, d::IntervalArithmetic.DECORATION) (repeats 2 times)
   @ IntervalArithmetic ~\.julia\dev\IntervalArithmetic\src\decorations\intervals.jl:54
 [5] DecoratedInterval(I::Interval{Rational{Int64}})
   @ IntervalArithmetic ~\.julia\dev\IntervalArithmetic\src\decorations\intervals.jl:63
 [6] DecoratedInterval(a::Rational{Int64}, b::Rational{Int64})
   @ IntervalArithmetic ~\.julia\dev\IntervalArithmetic\src\decorations\intervals.jl:67
 [7] top-level scope
   @ REPL[19]:1

lucaferranti avatar May 19 '21 20:05 lucaferranti

That's not quite true:

julia> DecoratedInterval{Rational{Int}}(Interval(1//1, 2//2), com)
[1//1, 1//1]

Rather, it's a constructor issue I believe.

dpsanders avatar May 19 '21 22:05 dpsanders

found the problem with the constructor. At the moment we have

DecoratedInterval(I::Interval{T}, d::DECORATION) where T<:AbstractFloat =
    DecoratedInterval{T}(I, d)

since Rational is not AbstractFloat calling DecoratedInterval(Interval(1//2, 2//1), com) falls back to

DecoratedInterval(a::T, d::DECORATION) where T<:Real =
    DecoratedInterval(Interval(a,a), d)

and then it fails. Was there any particular reason for having AbstractFloat? Changing to Real all tests still pass?

lucaferranti avatar May 30 '21 07:05 lucaferranti

there's still a small problem with nai(Rational) = [1//0, -1//0]_ill, namely that the standard says inf(NaI) and sup(NaI) should return NaN, from the end of section 12.12.8

Each bare interval operation in this subclause shall have a decorated version, where each input of bare interval type is replaced by an input having the corresponding decorated interval type, and the result format is that of the bare operation. Following 11.7, if any input is NaI, the result is NaN. Otherwise the result is obtained by discarding the decoration and applying the corresponding bare interval operation.

The problem is that Rational does not have anything for NaN, what should those return in that case?

lucaferranti avatar Jun 02 '21 07:06 lucaferranti