Skip to main content

bugs - A weird issue with Interval[$MaxNumber]


Bug introduced in 9.0 or earlier and persisting through 11.0.1 or later




From the Interval documentation:



For approximate machine- or arbitrary-precision numbers x, Interval[x] yields an interval reflecting the uncertainty in x.



$Version

(* 10.4.0 for Microsoft Windows (64-bit) (February 26, 2016) *)

Interval @ $MaxNumber === Uncompress @ Compress @ Interval @ $MaxNumber
(* True *)

IntervalMemberQ[Interval @ $MaxNumber, $MaxNumber]
(* True *)

IntervalMemberQ[Uncompress @ Compress @ Interval @ $MaxNumber, $MaxNumber]
(* False *)


What is going on here? What happens with the interval after the compress-uncompress round-trip?



Answer



A new and mostly rewritten version of the original answer which was flawed. See edit history if interested.


As any operation making $MaxNumber higher (more precisely: higher enough for its Precision to notice) results in an overflow, the Interval created here has the form


Interval[{$MaxNumber - something small, Overflow[]}]

The "something small" is approximately $MaxNumber / 10^$MachinePrecision (not so small, on second thought). Now it holds that


0 < Underflow[] < $MinNumber <= anything positive finite <= $MaxNumber < Overflow[] < ∞,


so it would make sense to accept Overflow[] for a bound of an interval, at least an open one. As the comments to the original version of this answer show, since there are only unions and intersections in Mathematica's interval arithmetic, even that works in the presence of Overflow[]. Of course, some problems will arise with a symbol that effectively represents an out of bounds error, like comparison with itself, but by any means $MaxNumber should be a member of the above interval.


I have done a bit of hacking on DumpSaves and discovered the following: Mathematica sorts Intervals into those that have numerical inputs and those that don't. I would call the latter "incomplete" because this category includes not only Intervals with unassigned symbols appearing in the bounds but also those with Slots and Blanks. Any incomplete Interval automatically returns False on IntervalMemberQ: try


(* This gets only evaluated after substitution *)
f[a_, b_, c_] := IntervalMemberQ[Interval[{a, b}], c];
f[1, 3, 2] (* True *)

(* This is evaluated immediately with the incomplete Interval *)
g[a_, b_, c_] = IntervalMemberQ[Interval[{a, b}], c];
g[1, 3, 2] (* False *)


or even


f = IntervalMemberQ[Interval[{#1, #2}], #3] &;
f[1, 3, 2] (* True *)

g = Evaluate[IntervalMemberQ[Interval[{#1, #2}], #3]] &;
g[1, 3, 2] (* False *)

My speculation is that this has to do with optimization: with a numeric Interval, all the bounds are compared, sorted along the real line and merged as appropriate as shown by the example


Interval[{-1, √2}, {0, Ï€}, {7, 8}, {-5, -4}]


(* Interval[{-5, -4}, {-1, π}, {7, 8}] *)

This can't be done with incomplete intervals. It might be an "expensive" operation so it's good to do it once the interval becomes complete, and if two of these are intersected, unified, or compared, take this condition for granted.


Now what happens in the original examples is that the "incomplete" bit gets set when Overflow[] is manually provided as a bound to the Interval (even though Overflow[] is even explicitly recognized as numeric by NumericQ and compares with other numbers well). Somehow the Interval produced by Interval@$MaxNumber is still marked as numerical, though, and this is preserved under interval operations. This explains the situations with Uncompress@Compress@ and Identity/@ applied on the pre-made Interval since these force reevaluation of its parts.


In pattern and slot substitutions, a new object is formed so the incomplete bit is reexamined (and the optimizations done, if complete). But as long as the object stays unchanged there is no reason to touch this metainformation. Importantly, this flag is not a part of the expression tree displayed to the user and is ignored in comparisons. So if two objects only differ in this (due to an incoherent assignment at one or the other's creation) they look identical and are even considered equal in === and similar commands. It is enough difference, however, to prevent Share from merging them.


Of course, there are many good points supporting Mathematica's decision not to allow Overflow[] as a bound for Interval – if it was a design choice in the first place, that is. But one way or the other, this behaviour should be consistent. I agree the inconsistency is a bug, most likely originating in Interval.


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

calculus and analysis - Integral of the Sinc product

Let us consider the following integral $$ B_n = \int_0^\infty \prod_{k=1,3,5,\dots}^n\frac{\sin (x/k)}{x/k}dx $$ By definition, Sinc[x] == Sin[x]/x , therefore B[n_?OddQ] := Integrate[Product[Sinc[x/k], {k, 1, n, 2}], {x, 0, Infinity}] B /@ Range[1, 13, 2] {Pi/2, Pi/2, Pi/2, Pi/2, Pi/2, Pi/2, Pi/2} OK, everything is fine. But... B[15] 467807924713440738696537864469 Pi/935615849440640907310521750000 What's going on? Answer As Eckhard wrote in comments B[n] is the n-th Borwein integral . (The letter B was not accidental :) ) This funny properties of Borwein integrals is related to the Fourier transform of Sinc function FourierTransform[Sinc[x], x, k] 1/2 Sqrt[Pi/2] (Sign[1 - k] + Sign[1 + k]) Plot[%, {k, -2, 2}, Filling -> 0] which is the box function. The result is $\pi/2$ while the sum $$ 1/3+1/5+\dots+1/n $$ B_n = \frac{\pi}{2} - \pi \bigg(\sum_{k=3,5,\ldots}^n\frac{1}{k} -1\biggr)^\frac{n-1}{2}\prod_{k=3,5,\dots}^n\frac{k}{k-1}. $$ For $n=15$ it is equal to $$ \frac{46780...

list manipulation - Selecting multiple columns from a matrix?

Sample data: data = { {{2013, 1, 1}, 24.13, 167.67, 231.82}, {{2013, 1, 2}, 32.15, 170.92, 225.99}, {{2013, 1, 3}, 35.43, 172.68, 221.67}, {{2013, 1, 4}, 36.73, 173.05, 218.32}, {{2013, 1, 5}, 58.19, 165.96, 197.05}, {{2013, 1, 6}, 69.99, 163.50, 187.52}, {{2013, 1, 7}, 71.37, 154.21, 175.58}, {{2013, 1, 8}, 72.51, 149.66, 163.25}}; I want a DateListPlot with three graphs, so for a matrix formed by columns 1 and 2, one for columns 1 and 3, and 1 for columns 1 and 4. At the moment I'm using this code: data2 = Transpose[{data[[All, 1]], data[[All, 2]]}]; data3 = Transpose[{data[[All, 1]], data[[All, 3]]}]; data4 = Transpose[{data[[All, 1]], data[[All, 4]]}]; DateListPlot[{data2, data3, data4}, Joined -> True, Filling -> {3 -> {1}}] but I have a hunch that this can be done more efficiently. I don't like the Transpose s in particular. Any ideas? edit (for extra credit) What if I need to multiply the second column by 2, which in my solution is simp...