-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Docs: how to handle branching? #524
Comments
Hehe this is an oldie but goldie. Currently, IA uses the definition recommended by the IEEE standard for interval arithmetic, that is this definition stems from the work of Ulrich Kulisch about axiomatization of interval arithmetic, but in practice is not that useful and indeed it seems to unify developers in disappointment. The As a final small comment, in the specific example you posted I wouldn't say the result in incorrect because it still holds To play devil's advocate, here is a function with branching where a valid enclosure is not returned, so your point stands :) julia> f(x)= x > 0 ? x + 3 : x - 3
f (generic function with 1 method)
julia> f(-1..1)
[-4, -2] # the true range is [-4, 4] |
alternatively, you may want to have a look at NumberIntervals.jl which uses a ternary logic for boolean intervals, returning |
Thank you so much for the rapid response. It seems possible to handle conditions manually, but it would lead to quite have machinery to handle it automatically, similarly like in julia> using IntervalArithmetic
julia> X = 0.9..1.1
[0.899999, 1.10001]
julia> f(x) = x > 1 ? x-1 : x;
julia> f(X)
[0.899999, 1.10001] # incorrect
julia> function f(x::Interval)
if x > 1
return x-1
elseif x < 1
return x
else # 1 ∈ x
union(max(1,x)-1, min(1,x))
end
end;
julia> f(X)
[0, 1] # correct, but ... Further, branching seems to be related to
Unfortunately not, Finally, thanks for guiding me to NumberIntervals.jl, as they introduced |
absolutely!
🤦♂️ I should really learn not to check github before my morning coffee... :)
Yeah that's a beast on itself. Generally, interval functions are defined via interval extension, that is the interval hull of the image. However, that is not always useful, e.g. for the set difference or the mod function as you point out. This paper describes the ideas of using union of intervals and IntervalUnionArithmetic.jl by @AnderGray has an implementation for it. |
Branching is a tricky one with intervals.
I agree that this should be the answer. If you were to do a Monte Carlo simulation with a distribution in julia> using IntervalArithmetic, IRTools
julia> f(x) = x > 1 ? x-1 : x;
julia> X = 0.9..1.1
julia> @code_ir f(X)
1: (%1, %2)
%3 = %2 > 1
br 3 unless %3
2:
%4 = %2 - 1
return %4
3:
return %2
btw, if you mince, you do start getting an approximation: julia> hull(f.(mince(X, 1000)))
[0.000199999, 1.0002]
|
It seems possible to introduce a macro that transforms the basic example. I drafted some code, but I'm not an expert for macros. y = @interval x > 1 ? x-1 : x or y = @interval x > 1 ? f(x) : h(x) in general, where function https://gist.github.com/petvana/9e583dcc6471368322afec63c0fa81e3 |
Could this be (eventually) added to the existing |
I was not aware of existing |
Actually I think combining with julia> sin(0.1) + exp(0.3)*cos(0.2+log(0.523)) then to have a rigorous computation you should convert all numbers to intervals before evaluating any function. The julia> @macroexpand @interval sin(0.1) + exp(0.3)*cos(0.2+log(0.523))
:(IntervalArithmetic.Interval(sin(IntervalArithmetic.atomic(IntervalArithmetic.Interval{(IntervalArithmetic.parameters).precision_type}, 0.1)) + exp(IntervalArithmetic.atomic(IntervalArithmetic.Interval{(IntervalArithmetic.parameters).precision_type}, 0.3)) * cos(IntervalArithmetic.atomic(IntervalArithmetic.Interval{(IntervalArithmetic.parameters).precision_type}, 0.2) + log(IntervalArithmetic.atomic(IntervalArithmetic.Interval{(IntervalArithmetic.parameters).precision_type}, 0.523))))) as such this could be seen as an enhancement of That being said, if integrating into the existing |
But if some functions do not fully support intervals then it would be impossible to write |
See this comment about |
One nice way to handle functions like this is with an implementation of piecewise functions, e.g. this one. |
I like the code you linked. Note, with the new semantics, the code you shared reads: using IntervalArithmetic
using IntervalArithmetic.Symbols # to use the constructor `..`
piecewise(pieces::Tuple, x::Interval) = reduce(hull, f(intersect_interval(x, region)) for (region, f) ∈ pieces)
f(x) = piecewise((0..3 => x -> x + interval(1), 3..6 => x -> x, 6..Inf => x -> x + interval(2)), x)
f(2..5) Also, this gives us a good opportunity to highlight the fact that the decoration is |
This is more like a question. I haven't found any information in the docs about handling branching while using
InrervalArithmetic
. For exampleThe code produces an incorrect interval because
0.9..1.1 > 1 == false
is valid only for part of the interval. Is there any way to handle such situations?Btw, what about producing a warning?
The text was updated successfully, but these errors were encountered: