# Comparison of IntervalArithmetic.jl and Measurements.jl

**URL:** <https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474>\
**Category:** General Usage\
**Tags:** intervals\
**Created:** [May 4, 2022, 10:46am UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474 "2022-05-04T10:46:47Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![pierre-haessig](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pierre-haessig/32/217129_2.png) [@pierre-haessig](https://discourse.julialang.org/u/pierre-haessig)\
**Post date:** [May 4, 2022, 10:46am UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/1 "2022-05-04T10:46:47Z")

</div>

I was just discussing with colleagues some of the classical theoretical oddities of interval arithmetic, in particular the fact that, for an interval X = [a,b], we have X-X \neq 0 (we have instead only the inclusion 0 \in X-X, since X-X = [a-b, b-a]). References: Wikipedia’s [Interval arithmetic](https://en.wikipedia.org/wiki/Interval_arithmetic) and the [Interval arithmetic tutorial](https://juliaintervals.github.io/pages/tutorials/tutorialArithmetic/#interval_arithmetic_tutorial) from `IntervalArithmetic.jl` documentation).

This brought me to recheck what were the available option for interval computations in Julia. I was surprised to find two packages which seems to come from two points of views which are far enough so that they are, to the best of my knowledge, not cross-referencing each others:

- [IntervalArithmetic.jl](https://juliaintervals.github.io/pages/packages/intervalarithmetic/)
- [Measurements.jl](https://juliaphysics.github.io/Measurements.jl/stable/)

So I try to assemble here my notes for other people that may come across this potential choice. I welcome comments about what I may have missed or what I got wrong.

## IntervalArithmetic.jl

`IntervalArithmetic.jl`, which seems to come from a Validated Numerics and Global optimization background is perhaps the closest package to what I understand to be the classical definition of Interval arithmethic. Coherent with this, we have the non-cancellation when substracting intervals:

```julia-auto
julia> using IntervalArithmetic

julia> x = 5±1
[4, 6]

julia> x-x
[-2, 2]

```

## Measurements.jl

On the other hands `Measurements.jl` seems to come from a Physics background (e.g. it belongs to the [JuliaPhysics](https://juliaphysics.github.io/latest/) GitHub organization). The focus is not on Validated Numerics but rather on linear [error propagation](https://en.wikipedia.org/wiki/Propagation_of_uncertainty) theory (which is by principle an approximation from the true error). Although the syntax can look exactly the same as with IntervalArithmetic (see code below), the manipulated objects are _variables with some error_ (or combinations of such variables) rather than _interval sets_. This semantic changes allows Measurement to track what its author calls _functionnally correlated quantities_ (see [Giordano’s 2016 manuscript](https://arxiv.org/abs/1610.08716)). With this in mind, we get:

```julia-auto
julia> using Measurements

julia> x = 2±1
2.0 ± 1.0

julia> x-x
0.0 ± 0.0

```

Of course with both packages, we have `0*x` somehow equal to zero (either represented `0.0 ± 0.0` or `[0, 0]` which are subtly different).

---

<div class="post-metadata">

**Author:** ![pierre-haessig](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pierre-haessig/32/217129_2.png) [@pierre-haessig](https://discourse.julialang.org/u/pierre-haessig)\
**Post date:** [May 4, 2022, 12:33pm UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/2 "2022-05-04T12:33:19Z")

</div>

One other major difference I missed in my first post is the interpretation of the sum of intervals/variables:

## IntervalArithmetic.jl

The sum of intervals is understood in the worst case sense (i.e. a [Minkowski sum](https://en.wikipedia.org/wiki/Minkowski_addition) of the sets):

```julia-auto
julia> using IntervalArithmetic

julia> x = 0±1
[-1, 1]

julia> y = 0±1
[-1, 1]

julia> x+y
[-2, 2]

```

## Measurements.jl

The error term of each variable is understood is a _standard deviation of a random variable_ (while the nominal value is the expectation). Then, the rule for defining the error for the sum of two variables with some error is the rule for summing random variables\*\*.

If the random variables are _independant_, the square of the standard deviations add up (i.e. sum of variances):

```julia-auto
julia> using Measurements

julia> x = 0±1
0.0 ± 1.0

julia> y = 0±1
0.0 ± 1.0

julia> x+y
0.0 ± 1.4

```

However, if the two variables getting summed are 100% correlated, the error gets doubled:

```julia-auto
julia> x+x
0.0 ± 2.0

```

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [May 4, 2022, 1:16pm UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/3 "2022-05-04T13:16:01Z")

</div>

You might also be interested in [GitHub - baggepinnen/MonteCarloMeasurements.jl: Propagation of distributions by Monte-Carlo sampling: Real number types with uncertainty represented by samples.](https://github.com/baggepinnen/MonteCarloMeasurements.jl) which keeps track of a collection of samples rather than a mean and standard deviation.

Also [GitHub - kalmarek/Arblib.jl: Thin, efficient wrapper around Arb library (http://arblib.org/)](https://github.com/kalmarek/Arblib.jl) which is a wrapper around the C library Arb and is more similar to interval arithmetic (but using a midpoint-radius representation).

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [May 4, 2022, 1:23pm UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/4 "2022-05-04T13:23:35Z")

</div>

It’s worth noting that midpoint-radius is pretty much strictly superior to interval representation since it allows storing much tighter intervals.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [May 4, 2022, 1:28pm UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/5 "2022-05-04T13:28:54Z")

</div>

why do you say that? given you can losslessly convert between the two, I don’t really see how that’s possible, unless you mean the way they are usually implemented or something like that

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [May 4, 2022, 1:34pm UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/6 "2022-05-04T13:34:59Z")

</div>

You can’t lossless convert in finite precision arithmatic. The interval `1.0 +- eps(1.0)/4` isn’t representable using an interval.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [May 4, 2022, 1:37pm UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/7 "2022-05-04T13:37:58Z")

</div>

Oh! I see, good point. So since there’s more floats near 0, you can represent very small radii, and the density of floats might be much lower out where the endpoints of the interval are?

---

<div class="post-metadata">

**Author:** ![cvanaret](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cvanaret/32/11594_2.png) [@cvanaret](https://discourse.julialang.org/u/cvanaret)\
**Post date:** [May 4, 2022, 2:42pm UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/8 "2022-05-04T14:42:39Z")

</div>

Here’s an [introduction to Affine arithmetic](https://tema.sbmac.org.br/tema/article/download/352/291) (AA), which captures perfectly the linear relationships between variables (thus provides the optimal range).  
An over-approximation can be computed for nonlinear primitive functions. Overall, affine arithmetic is a powerful enclosure tool (although more expensive than naive interval arithmetic).  
IIRC, Jordan Ninin combined (= intersected) both the IA and the AA enclosures in his thesis.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [May 4, 2022, 4:15pm UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/9 "2022-05-04T16:15:04Z")

</div>

Since this is somewhat a misunderstanding sometimes, I want to stress there is no _correct_ way to handle these things: as you mentioned it already, `IntervalArithmetic.jl` and `Measurements.jl` (+ `MonteCarloMeasurements.jl`) are generally used in different fields, for different purposes. And even within Physics, there are cases where linear error propagation is sufficient (in which cases MonteCarlo propagation would be an overkill, but still consistent) and others where it’d return pretty garbage results (for example whenever derivatives are very small relative to some scale, think of stationary points of functions, in these cases something more advanced as second order derivatives or MonteCarlo propagation is necessary).

I’d also like to mention that most of the complexity in `Measurements.jl` comes from tracking the “functional correlation” between quantities (I couldn’t find a better term to distinguish it from statistical correlation): it’s pretty easy to implement a linear error propagation system without tracking the correlations (this is what the very first release of `Measurements.jl` did), but then you start getting inconsistent results like `x + x != 2 * x`, `x * x != x ^ 2`, and so on, which are also related to the already mentioned `x - x != 0`. Not having basic identities to hold, or changing the error estimation depending on whether you apply addition or multiplication, when you mean the same thing, would be pretty annoying.

---

<div class="post-metadata">

**Author:** ![cvanaret](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cvanaret/32/11594_2.png) [@cvanaret](https://discourse.julialang.org/u/cvanaret)\
**Post date:** [May 4, 2022, 5:45pm UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/10 "2022-05-04T17:45:02Z")

</div>

To (sometimes) address these problems, here’s a powerful but tedious way: if an expression is monotonic wrt a variable, the result is formed by taking the endpoint evaluations only.

Example:  
Let f(x) = x - x and X = [-5, 5]. The natural (= naive) evaluation is F\_N(X) = [-5, 5] - [-5, 5] = [-10, 10]. That’s bad.  
However, f is monotonic (increasing or decreasing) wrt x because f' = 0. So the result is (for example) [f(\underline{X}), f(\underline{X})], which is [0, 0]. Obviously, this also works for more complex expressions.

---

<div class="post-metadata">

**Author:** ![pierre-haessig](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pierre-haessig/32/217129_2.png) [@pierre-haessig](https://discourse.julialang.org/u/pierre-haessig)\
**Post date:** [May 5, 2022, 9:47am UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/11 "2022-05-05T09:47:03Z")

</div>

Thanks for pointing me to this 2003 manuscript about Affine arithmetic by Stolfi which I didn’t know. Very interesting indeed. Yesterday I was wondering what would @giordano’s package Measurements.jl look like with a new option to treat error sums in a _worst case_ sense rather than in its current _root mean square_ sense.

After reading Stolfi’s paper, I think that this is exactly what AA is doing (with an extra bonus for managing both the roundoff and the truncation of Taylor series at the first order). I guess that some of the references at the end, like the “first-order Taylor arithmetic” are also implementing this idea.

I wonder if there are AA implementations in Julia.

Perhaps a new option within Measurements.jl may be able to do it (without the extra bonus of managing truncation errors which would be pretty outside the original philosophy of this package, I think).

As an alternative, since the definition of Affine Arithmetic (eq. 3.1 in Stolfi 2003) looks very similar to dual numbers (extended to manage several parameters), it may be possible to perform the AA computation using [ForwardDiff](https://juliadiff.org/ForwardDiff.jl/stable/) to compute the input-output first-order sensitivities (again the truncation errors would not be handled). Then, the section 3.2 “Joint range of affine forms” seems to be readily applicable.

---

<div class="post-metadata">

**Author:** ![pierre-haessig](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pierre-haessig/32/217129_2.png) [@pierre-haessig](https://discourse.julialang.org/u/pierre-haessig)\
**Post date:** [May 5, 2022, 9:53am UTC](https://discourse.julialang.org/t/comparison-of-intervalarithmetic-jl-and-measurements-jl/80474/12 "2022-05-05T09:53:29Z")

</div>

Thanks for pointing me to the “ball arithmetic” keyword. I don’t have floating-point representation issues, but otherwise @Oscar_Smith’s explanation indeed makes the point about the advantage the midpoint-radius representation.

For the reference, I just quickly read [Arb lib features overview](https://arblib.org/overview.html) where an additional point is made: the radius can be stored using a lower precision floating point.
