Giter Site home page Giter Site logo

numberintervals.jl's Introduction

NumberIntervals.jl

A package for strict intervals-as-numbers.

Build Status codecov

Installation

NumberIntervals.jl is available from the General registry. To install enter the Pkg REPL (using ] in Julia REPL) and simply enter:

add NumberIntervals

Description

This package aims to provide intervals which can be safely used as drop-in replacements for numbers in Julia. It builds on the IntervalArithmetic.jl implementation of the IEEE 1788-2015 standard.

However, our NumberInterval type behaves more predictably and cautious in many contexts than the Interval type:

julia> using NumberIntervals, IntervalArithmetic
julia> iszero(Interval(-1, 1))
false
julia> iszero(NumberInterval(-1, 1))
missing

In this case, we cannot tell if the interval (-1, 1) represents zero or not; so the NumberInterval returns missing. The Interval (from IntervalArithmetic) is more forgiving which increases the risk of silent failure in algorithms expecting Number-like behavior.

In safe cases, NumberInterval yields the expected result:

julia> iszero(NumberInterval(-2, -1))
false

julia> iszero(NumberInterval(-0, +0))
true

This behavior is similar to the default Boost implementation.

Through try-catch statements fallback algorithms can be defined when certain methods fail. A good example is Base.hypot(x, y). It calculates sqrt(x^2 + y^2) avoiding over/underflows. Unfortunately, it is not always safe to use with intervals. This definition uses Base.hypot() in safe cases and falls back to sqrt(x^2 + y^2) in unsafe cases:

is_missing_exception(::Exception) = false
is_missing_exception(exc::TypeError) = ismissing(exc.got)

function my_hypot(x, y)
    try
        hypot(x, y)
    catch exc
        if is_missing_exception(exc)
            return sqrt(x^2 + y^2)
        end
        rethrow(exc)
    end
end

Check our example demonstrating how NumberIntervals can act as drop-in replacements for numbers without sacrificing numerical validity.

Unsupported functions

Some functions do not support NumberIntervals, usually because they call external C or FORTRAN libraries. For these functions, ApproxFun.jl produces a pure Julia approximation which can be used with NumberIntervals.

julia> using ApproxFun, NumberIntervals, SpecialFunctions
julia> besselj0(NumberInterval(1))
ERROR: StackOverflowError
julia> f = Fun(besselj0, Chebyshev(0..10))
julia> f(NumberInterval(1))
x โˆˆ [0.765197, 0.765198]
julia> besselj0(1)
0.7651976865579666

Debugging

For debugging purposes, enable exceptions in indeterminate cases, using:

    NumberIntervals.intercept_exception(::IndeterminateException) = false

numberintervals.jl's People

Contributors

gwater avatar juliatagbot avatar mforets avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

mforets

numberintervals.jl's Issues

Proposal: replace Indeterminate() with Base.missing

I feel like we're reinventing the wheel in indetermiate.jl; and it is leading to some method creep. There is a lot of support in Base for three-value logic, especially in Boolean array methods, like all() or any(). Keeping a custom three-value logic means reimplementing all those functions.

On the other hand, the only reason for using a custom type instead of Base.missing (as far as I can tell) is that it would allow something like

ifelse(::Indeterminate, a::Real, b::Real) = NumberInterval(a, b) 

(assuming a<b). With Base.missing that would be type-piracy.

Since extending ifelse() is currently off the table anyway, I think we should switch to Base.missing as soon as possible. Am I missing something, @oschulz? (No pun intended.)

redefine isfinite

by definition IEEE intervals cannot have infinite members, only infinite bounds, see Sec 3.2

infinite `promote_rule` loop when combining with `IntervalArithmetic.jl`

I don't expect this to be common, but I did just run into it.

import NumberIntervals
import IntervalArithmetic
julia> [NumberIntervals.NumberInterval(0, 1), IntervalArithmetic.Interval(0, 1)]
ERROR: StackOverflowError:
Stacktrace:
 [1] promote_rule(::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}}, ::Type{T} where T) at /Users/goretkin/.julia/packages/NumberIntervals/H1EA0/src/types.jl:57
 [2] promote_type(::Type{NumberIntervals.NumberInterval{Float64}}, ::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}}) at ./promotion.jl:223
 [3] promote_rule(::Type{IntervalArithmetic.Interval{NumberIntervals.NumberInterval{Float64}}}, ::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}}) at /Users/goretkin/.julia/packages/IntervalArithmetic/sRFlx/src/intervals/conversion.jl:8
 [4] promote_rule(::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}, ::Type{T} where T) at /Users/goretkin/.julia/packages/NumberIntervals/H1EA0/src/types.jl:57
 [5] promote_type at ./promotion.jl:223 [inlined]
 [6] promote_result(::Type{T} where T, ::Type{T} where T, ::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}, ::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}}) at ./promotion.jl:237
 [7] promote_type(::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}, ::Type{NumberIntervals.NumberInterval{Float64}}) at ./promotion.jl:223
 [8] promote_rule(::Type{IntervalArithmetic.Interval{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}}, ::Type{NumberIntervals.NumberInterval{Float64}}) at /Users/goretkin/.julia/packages/IntervalArithmetic/sRFlx/src/intervals/conversion.jl:8
 ... (the last 8 lines are repeated 11424 more times)
 [91401] promote_rule(::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}}, ::Type{T} where T) at /Users/goretkin/.julia/packages/NumberIntervals/H1EA0/src/types.jl:57
 [91402] promote_type(::Type{NumberIntervals.NumberInterval{Float64}}, ::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}}) at ./promotion.jl:223
 [91403] promote_rule(::Type{IntervalArithmetic.Interval{NumberIntervals.NumberInterval{Float64}}}, ::Type{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{NumberIntervals.NumberInterval{Float64}}}}) at /Users/goretkin/.julia/packages/IntervalArithmetic/sRFlx/src/intervals/conversion.jl:8

Possibly it is an issue with IntervalArithmetic. Here is the corresponding issue: JuliaIntervals/IntervalArithmetic.jl#426

Three-valued logic instead of exception on comparisons?

@gwater, at JuliaCon2019, @dpsanders and I discussed possible ways to handle comparisons of intervals.

I was thinking about how to enable generic code with conditional statements, so that it can work both with intervals and standard reals. With the current implementation in NumberIntervals, one would need try/catch, which is not ideal performance-wise.

How about three-valued logic instead? I was thinking about two possible representations

  • true, false and true_or_false (with a custom true_or_false singleton value of type TrueOrFalse similar to missing and Missing)

  • Logic intervals: [true], [false], [false, true]

The latter seems elegant to me (Bool <: Real so why not have boolean intervals), but is probably more complex to implement since IntervalArithmetic currently doesn't support integer intervals.

Also, using missing (or some custom true_or_false value) would mimic the current behavior: In a standard if statement, it'll result in an exception (ERROR: TypeError: non-boolean (TrueOrFalse) used in boolean context). But, unlike the current implementation that throws an exception directly, the user can write code in a fashion that handles true_or_false:

c = a < b
if c == true
    ...
elseif c == false
    ...
else
    ...
end

Such code would work generically for with interval numbers and non-interval numbers.

Also, we could overload ifelse to handle the true_or_false outcome automatically, be returning an interval that spans both ifelse return values.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.