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

update decorated intervals constructors

Open lucaferranti opened this issue 2 years ago • 2 comments

What

This PR fixes issues in 1.0-dev with decorated interval constructors. After this all related ITF tests pass.

Changes

Check for validity of interval

Added inner constructor that checks if the given decoration is appropriate and behaves accordingly. Also for ill the interval part is normalized to [NaN, NaN], which simplifies computations since NaN poisons everything

  • before
julia> DecoratedInterval(Interval(0, Inf), com)
[0, ∞]_com

julia> DecoratedInterval(Interval(2, 1), com)
[2, 1]_com

julia> DecoratedInterval(Interval(0, Inf), com)
[0, ∞]_com

julia> DecoratedInterval(Interval(2, 1), com)
[2, 1]_com

julia> a = DecoratedInterval(2, 1)
[2, 1]_ill

julia> inf(a)
2.0
  • after
julia> DecoratedInterval(Interval(0, Inf), com)
[0, ∞]_dac

julia> DecoratedInterval(Interval(2, 1), com)
[NaI]

julia> ans.interval
[NaN, NaN]

julia> DecoratedInterval(2, 1)
[NaI]

julia> ans.interval
[NaN, NaN]

julia> inf(a)
NaN

there was (and still is) some asymmetry between constructors of decorated intervals and bare intervals. For bare intervals, we have the unsafe constructor Interval which does nothing, the safe constructor interval and the safe macro with correct rounding @interval. For decorated intervals we have the safe macro with correct rounding interval @decorated, but only one constructor DecoratedInterval, which before this PR was unsafe and after this PR is safe (at the price of extra overhead). Are we happy with this? Or should we have a safe decorated constructor and unsafe DecoratedInterval constructor? I don't have strong opinions about this.

Interval part of nai()

according to the standard, the interval part of the [NaI] should be the empty interval and a warning should be thrown. This mainly had a few consequences

  1. for a few functions (e.g. inf, sup) interval could not be used directly, since inf(nai()) should still be NaN
  2. Now all tests pass, so I guess it's fine but as a drawback, warnings are emitted in the middle
julia> nai() + DecoratedInterval(1, 2)
┌ Warning: trying to access interval part of [NaI], returning empty interval
└ @ IntervalArithmetic ~/.julia/dev/IntervalArithmetic/src/decorations/intervals.jl:63
[NaI]

is this fine? The alternatives are

  1. use x.interval internally. This would probably work but might be a little contradictory with the latest decision to use inf, sup internally instead of .lo, .hi. On the other side, This matters only when implementing operations for decorated intervals but the end user who writes some generic algorithm with intervals would not note the difference, as would write generic code for AbstractInterval and hence would not need to access the interval part.
  2. have an interval function _interval(x::DecoratedInterval) = x.interval and external interval that does the "standard" behavior. Alternatively the internal could be called interval and external intervalPart or viceversa.

Personally, I think option 1 would be better in this case.

printing

  • changed printing on [NaI] now it's displayed as [NaI]

lucaferranti avatar May 26 '22 10:05 lucaferranti

Codecov Report

Merging #527 (33f8650) into 1.0-dev (1b84a19) will increase coverage by 0.91%. The diff coverage is 100.00%.

@@             Coverage Diff             @@
##           1.0-dev     #527      +/-   ##
===========================================
+ Coverage    84.50%   85.42%   +0.91%     
===========================================
  Files           34       34              
  Lines         1775     1784       +9     
===========================================
+ Hits          1500     1524      +24     
+ Misses         275      260      -15     
Impacted Files Coverage Δ
src/decorations/decorations.jl 71.42% <100.00%> (-3.58%) :arrow_down:
src/decorations/functions.jl 81.76% <100.00%> (ø)
src/decorations/intervals.jl 84.21% <100.00%> (+0.87%) :arrow_up:
src/display.jl 82.69% <100.00%> (+0.11%) :arrow_up:
src/intervals/arithmetic/basic.jl 91.52% <0.00%> (-1.49%) :arrow_down:
src/intervals/interval_operations/extended_div.jl 100.00% <0.00%> (ø)
src/multidim/intervalbox.jl 87.30% <0.00%> (+0.41%) :arrow_up:
src/intervals/arithmetic/power.jl 97.10% <0.00%> (+10.80%) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 1b84a19...33f8650. Read the comment docs.

codecov-commenter avatar May 26 '22 10:05 codecov-commenter

Let me add few thoughts about Decoratedintervals, and then this PR:

  • There is some an implicit dependence on the flavor which should be made explicit here: Concretely, in what is a valid interval. For example, if we (would) have a flavor that considers as a valid interval [2,1], then decoration( DecoratedInterval(interval(2,1)) ) == def should be true, and it should not return a nai(). (I think in this case the decoration should be at most def, but I may be wrong.)
  • Regarding the asymmetry, I think we must check the validity of the interval for DecoratedInterval, and as mentioned, this is flavor dependent. This is then tricky and unconfortable, in the sense we should use interval instead of Interval...
  • Regarding the interval part of nai(), if it is supposed to be the empty interval, then interval(nai()) == emptyinterval() should be true. Then, this imposes to also have that [NaN,NaN] corresponds to the empty interval, and I guess that [Inf, Inf] or [-Inf, -Inf] should behave similarly when the intervals are decorated. As a side note, let me note that e.g. interval(Inf,Inf) returns the empty interval.

lbenet avatar May 27 '22 14:05 lbenet

Superseded by #590.

OlivierHnt avatar Dec 01 '23 23:12 OlivierHnt