-
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
A common "thick numbers" package? #585
Comments
Thanks for the opening this issue! To add context: interval arithmetic has stringent specifications which play poorly with generic code intended for real numbers (in the mathematical sense). To illustrate, let me copy-paste @Kolaru's recent example f(x, y) = (x == y) ? 1 : exp(x - y) which fails for the reasons mentioned already in @timholy's comment. So to prevent silent failures, we have to fight quite a bit against Julia's flexibility (that's the reason for the recent changes on It may also be worth mentioning here that recently we opened #584 as a way to recover interoperability with the ecosystem by exploiting the decoration system. This came up when thinking about conversion, see recently #580. One scenario could be to define struct Interval{T} <: Real
interval :: BareInterval{T}
decoration :: Decoration
end
struct BareInterval{T}
lo :: T
hi :: T
end Then, |
To compare with other similar packages having the same problem ( What we want:
What we do not want:
What we can kind of live with:
I am pretty sure that I am missing some elements, but that's what come to mind right now. Does it leaves enough in common with other packages ? I am not sure. |
Update (sorry for the delay, I've been immersed in other things): I've realized that Measurements.jl doesn't implement the arithmetic rules I want: julia> using Measurements
julia> (0 ± 1) * (0 ± 1)
0.0 ± 0.0 Instead I want something consistent with the algebra of random variables (what I think of as "soft intervals"). AFAICT there isn't really a package doing what I want, so I may start one (locally for now), and as I develop it I'll look for common interests. I may have a more informed view on this in a couple of weeks. |
CC @baggepinnen for I don't think it's particularly easy to define a common generic interface. For example I feel quite strongly about making @timholy |
There's an initial implementation at https://github.com/timholy/ThickNumbers.jl. Durng this preliminary phase, I'll host it in my personal GitHub account, but if we decide to adopt it I'll transfer it to JuliaMath. It's preliminary in the sense that I've not actually tried it in practical usage, and I don't plan to register it until I've created or rebased at least two packages on it, so we know if the generalizations "work" in real-world practice. However, it's got a lot going for it already:
Note that it mirrors the "new" direction for IntervalArithmetic, but with a couple changes in terms of unicode operators. I decided to aim for "dot" consistency, riffing off of |
There were some initial issues with doc depoloyment, but those have been fixed and additional improvements made. |
Toy package serving as a proof-of-principle: https://github.com/HolyLab/GaussianRandomVariables.jl |
CC To @AnderGray, who has experience and may add something to the discussion. |
I think a package implementing a base uncertain number type, with common interface, would be very useful. I would have used it when making ProbabilityBoundsAnalysis.jl and MomentArithmetic.jl. Note: if you're looking for an easy-ish way to reduce puffiness in interval arithmetic, centred from interval arithmetic is still rigorous but uses the first derivative (we can use ForwardDiff.jl) to reduce puffiness. I think when you use higher orders, it generalises to Taylor Models. Unfortunately gaussian random variables aren't closed under arithmetic operations (except linear transformations), so the distribution's shape will change for anything non-linear. Essentially why first-order error propagation is only accurate for linear-enough functions. You can however perform computations with moments, or at least bound them in non-linear transformations. So unless you additionally track the shapes, the transformed moments become intervals. Afterwards however, probabilities can be bounded from the moment, using e.g. the Chebyshev inequality. If useful, we did publish open access article on the topic, and a sort of repository/package. Inside the paper you can find some tables containing the arithmetic rules we worked out (similar to the algebra of random variables) Reducing puffiness is all about correlations: julia> using MomentArithmetic, IntervalArithmetic
julia> a = Moments(0, 1, -1 .. 1) # mean 0, var 1, range [-1, 1]
julia> b = Moments(0, 1, -1 .. 1)
julia> a - b # Default is unknown correlation
moment: ~ ( mean = 0, var = [0.0,4.0] , range = [-2.0,2.0] )
julia> subIndep(a, b) # Independence gives precise variance
moment: ~ ( mean = 0, var = 2 , range = [-2.0,2.0] ) At the end of the paper there is some discussion on using covariances to reduce puffiness in arithmetic like in the above. |
Thanks, this looks useful. In case you're not aware, I tried building MomentArithmetic on 1.10 and got this: julia> using MomentArithmetic
Precompiling MomentArithmetic
Info Given MomentArithmetic was explicitly requested, output will be shown live
WARNING: could not import ProbabilityBoundsAnalysis.plot into MomentArithmetic
WARNING: Method definition (::Type{MomentArithmetic.Moments})() in module MomentArithmetic at /home/tim/.julia/packages/MomentArithmetic/x2Mva/src/Moments.jl:43 overwritten at /home/tim/.julia/packages/MomentArithmetic/x2Mva/src/Moments.jl:52.
ERROR: LoadError: Method overwriting is not permitted during Module precompile.
Stacktrace:
[1] top-level scope
@ ~/.julia/packages/MomentArithmetic/x2Mva/src/Moments.jl:52
... 1.10 is pickier about turning things that may have been warnings on previous releases into errors, because it was found that in some cases unfixed warnings were the source of serious, very difficult-to-track-down bugs. (In other cases they are fairly harmless, and this may be such a case.) |
I also like this line:
😆 |
CC @giordano, @devmotion (and others?)
I've not been
Watching
this package but it looks like interesting and important changes are afoot, and I wonder if it's an opportunity for some shared development among packages like Measurements and possibly even dual-number packages like ForwardDiff (and probably more, feel free to CC others). All of these packages share a somewhat-awkward desire to do math on objects that act like numbers but also have some "thickness" to them. (In ForwardDiff the thickness is infinitesimal, so maybe it's not quite as relevant to this discussion.) All of these packages have been tempted to inherit fromReal
, but many have recognized that this has some issues. I wonder if it's time to create a core package---let me throw outThickNumbers.jl
as a possible name---that defines abstract types and exports common operators, traits, fallbacks, errors, etc., but leaves all concrete implementations to downstream packages.To make this a bit concrete, here's an example from the development (
master
) branch of IntervalArithmetic:Note the use of a new operator
≛
. My understanding is that IntervalArithmetic is trying to adhere more strictly to the fundamental principle thatf(X, Y)
(heref
is==
) includes all possible values off(x, y)
for anyx ∈ X, y ∈ Y
; since almost any independent choice ofx, y
are not equal, testing interval equality is nearly useless. One could make a case forInterval{Bool}(false, true)
, but having the operation be undefined is at least safe, and gets you to the same result (an error) that puttinga == b
inside anif
statement would generate even if it did returnInterval{Bool}(false, true)
(becauseif
requires aBool
). This is just one example among many.I tend to think of Measurement as kind of like an interval, but less strict and less affected by the dependency problem. I actually have a practical use case where I'd like to be able to support users choosing whether they want to perform a computation using IntervalArithmetic (guaranteed but probably overly-conservative bounds) or Measurements (approximate but probably tighter bounds) and hence it would be interesting to consider making the two packages more compatible.
While I haven't actually written a line of code, I wonder if a shared "abstract package" might standardize some of the difficult decisions we have in common, or at least provide a social gathering point for discussing such issues. Julia's own
base/numbers.jl
andbase/operators.jl
might serve as inspiration for what could go in there, as well as noticing and sharing relevant patterns that are currently in the packages that might eventually useThickNumbers.jl
.The text was updated successfully, but these errors were encountered: