IntervalArithmetic.jl
IntervalArithmetic.jl copied to clipboard
operations on bare and decorated intervals
The standard says (section 12.12.9 boolean functions on intervals)
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. Following 11.7, if any input
is NaI, the result is false (in particular equal(NaI, NaI) is false). Otherwise the result is obtained by
discarding the decoration and applying the corresponding bare interval operation
so I think the comparison of bare and decorated interval should be possible and the result be based on the interval part of both?
Codecov Report
Merging #455 (0ced07a) into master (f0eebb6) will increase coverage by
0.00%
. The diff coverage is100.00%
.
@@ Coverage Diff @@
## master #455 +/- ##
=======================================
Coverage 91.41% 91.42%
=======================================
Files 25 25
Lines 1723 1725 +2
=======================================
+ Hits 1575 1577 +2
Misses 148 148
Impacted Files | Coverage Δ | |
---|---|---|
src/decorations/functions.jl | 95.34% <100.00%> (+0.05%) |
: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 f0eebb6...0ced07a. Read the comment docs.
Good job finding the relevant section of the standard (this is never easy). As I understand it we are not forced to allow comparison between decorated and bare intervals, only between decorated intervals. But I think we can allow it (as far as I am concern this way of comparing interval only makes limited sense anyway).
So unless there is an argument against mixing decorated and bare intervals here, I think this is good to be merged.
Thank you very much for going through my PR @Kolaru ! I just noticed that there are also other operations not working on mixed bare/decorated inputs e.g.:
julia> a = @decorated 1 2
[1, 2]_com
julia> b = 2..3
[2, 3]
julia> a + b
ERROR: type DecoratedInterval has field offset -1431655776 that exceeds the page size
Stacktrace:
[1] promote_rule
@ ~\.julia\dev\IntervalArithmetic\src\decorations\intervals.jl:99 [inlined]
[2] promote_type(#unused#::Type{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Float64}}}}}}}}}}}}}}}}}}}}}}}}}}}}, #unused#::Type{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{Float64}}}}}}}}}}}}}}}}}}}}}}}}}}}})
@ Base .\promotion.jl:233
[3] promote_result(#unused#::Type, #unused#::Type, #unused#::Type{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Float64}}}}}}}}}}}}}}}}}}}}}}}}}}}},
#unused#::Type{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{DecoratedInterval{Interval{Float64}}}}}}}}}}}}}}}}}}}}}}}}}}}})
@ Base .\promotion.jl:247
[4] promote_type
@ .\promotion.jl:233 [inlined]
--- the last 2 lines are repeated 25 more times ---
[55] _promote
@ .\promotion.jl:268 [inlined]
[56] promote
@ .\promotion.jl:292 [inlined]
[57] +(x::DecoratedInterval{Float64}, y::Interval{Float64})
@ Base .\promotion.jl:321
I am not sure whether these should return a bare or decorated interval. I can try to go through the standard and see if I find some useful insight. 🤔
thoughts about defining promotion and conversion rules between bare and decorated intervals? I guess defining those rules would fix the issue I described on my comment above. cc @dpsanders @Kolaru @lbenet
After some thinking and reading, I am not sure whether the promotion makes sense and if it does, what direction would make the more sense. Naively, I would have guessed promote bare to decorated, but consider the following example (obtained after having implemented the promotion rule)
julia> a = @decorated 0 Inf
[0, ∞]_dac
julia> b = @decorated 1 2
[1, 2]_com
julia> c = a ∩ b
[1, 2]_trv
julia> c + b
[2, 4]_trv
julia> c.interval + b
[2, 4]_com
My point is that the conversion rule would just give the smallest allowed decoration (com
in the example above) but that is not necessarily the correct one if the bare interval is the result of some interval computations. Since it's impossible to know the history of the interval, maybe the promotion shouldn't be Interval -> DecoratedInterval?
Maybe the other way around? In the sense, if I compute bare + decorated
I don't know where bare comes from and I cannot know its decoration, so I cannot compute the output decoration and so I return a bare interval.
Or maybe just throw an error if the user tries to perform those mixed computations? It might still be good to throw a nicer error though, something like ERROR: operations between bare and decorated intervals not allowed
.
Yes I think ERROR: operations between bare and decorated intervals not allowed
is the way to go.
Codecov Report
Merging #455 (9956d95) into master (65ca77f) will decrease coverage by
0.01%
. The diff coverage is100.00%
.
@@ Coverage Diff @@
## master #455 +/- ##
==========================================
- Coverage 91.53% 91.51% -0.02%
==========================================
Files 25 25
Lines 1748 1756 +8
==========================================
+ Hits 1600 1607 +7
- Misses 148 149 +1
Impacted Files | Coverage Δ | |
---|---|---|
src/decorations/functions.jl | 94.97% <100.00%> (-0.35%) |
:arrow_down: |
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 65ca77f...9956d95. Read the comment docs.
I don't think comparisons should be allowed either? Basically you should not be able to do any operations with mixed bare / decorated intervals.
yeah I was also thinking that if we don't allow arithmetic operations maybe for consistency we shouldn't allow Boolean operations either. Just rebased the PR I'll update this soon.
I think throwing an error would certainly force the user to work thoroughly with decorated intervals, if that's the initial intention. Once said this, the alternative to promote it to the least decoration trv
should be save, I guess.
A question: In the example above, shouldn't c
be decorated as dac
? (I don't remember all subtleties of the decorations, but clearly the result is continuous and defined.)
Section 11.7.1 (page 47)
These give interval results but are not interval extensions of point functions:
– the reverse-mode operations of 10.5.4;
– the cancellative operations cancelPlus(x, y) and cancelMinus(x, y) of 10.5.6;
– The set-oriented operations intersection(x, y) and convexHull(x, y) of 10.5.7.
No one way of decorating these operations gives useful information in all contexts. Therefore, a trivial
decorated interval version is provided as follows. If any input is NaI, the result is NaI; otherwise the
corresponding operation is applied to the interval parts of the inputs, and its result decorated with trv. The
user may replace this by a nontrivial decoration via setDec(), see 11.5, where this can be deduced in a given
application.
I was also surprised by this though.
I checked what the octave package does, apparently it converts the bare interval to decorated but it also prints a warning about implicit conversion
>> a = infsup(1, 2)
a = [1, 2]
>> b = infsupdec(3, 4)
b = [3, 4]_com
>> a + b
warning: Implicitly decorated bare interval; resulting decoration may be wrong
warning: called from
infsupdec at line 206 column 13
plus at line 48 column 7
ans = [4, 6]_com
>> a < b
warning: Implicitly decorated bare interval; resulting decoration may be wrong
warning: called from
infsupdec at line 206 column 13
lt at line 45 column 7
ans = 1
We could do that too, then.
printing warning for every implicit promotion is quite a lot of noise though (does it hurt performance too?), I also found luis' proposal (promoting bare intervals to trv
) interesting. A similar approach might be to "promote" decorated intervals to bare and do computations using only bare intervals on mixed bare/decorated input. The rationale for this would be we are missing decoration knowledge on some inputs, so we cannot make deductions about the decoration and hence only bare computations are carried . I think this is conceptually equivalent to promoting to the bare interval to trv
, as that would "poison" all successive decorations to trv
, but maybe at this point for efficiency reasons promoting to bare might be better?
I like promotion to trivial decorated interval slightly more, this follows the convention that you only ever promote to a type that can represent both inputs.
With the trivial decoration poisonning the computations I don't think we need an error or a warning, the result will never pretend to be correct when it is not. Some utilities to track down when and why the decorations change could be nice in the future, but I don't think there is a huge need for it right now.
I am closing this PR since with PR #593 we did not allow mixing BareInterval
and Interval
(i.e. Interval
and DecoratedInterval
respectively). Especially since we have the isguaranteed
boolean field now.
That being said, please re-open and rebase the PR if this needs more discussion.