TransWikia.com

Mathematica 12.x: Don't use Accumulate or Differences on Around objects!

Mathematica Asked on May 7, 2021

Bug introduced in 12.0 or earlier and persisting through 12.2 or later

It seems we’ve discovered a bug! The following is a summary of the problem and possible workarounds. Scroll down to ORIGINAL POST to see the original statement of the issue.

If a List, TimeSeries, etc. of Around objects contains any identical elements, Accumulate produces propagated uncertainties that are too large. FoldList[Plus, 0, list] and FoldList[Plus]@list are valid alternatives that do not present this issue for Lists, but these do not work with TimeSeries! Finding something which does work with TimeSeries is still a work in progress.

If a List, TimeSeries, etc. of Around objects contains consecutive identical elements, Differences produces 0., which does not have an associated uncertainty. MovingMap[Subtract[#[[2]], #[[1]]] &, list, 1] and MovingMap[Subtract[#[[2]], #[[1]]] &, #, 1] &@list are valid alternatives which do not present this issue. And they work with TimeSeries!

Analysis of these and other functions can be found here.

For now, my best solution is to create a symbolic TimeSeries to manipulate with Accumulate, Differences, Ratios, etc., and then use ReplaceAll to insert the Around data in the final step. I’m not using AroundReplace because that function took over ten minutes to process a single TimeSeries! But, one must be careful when using ReplaceAll in lieu of AroundReplace. According to the documentation,

[ReplaceAll and AroundReplace] coincide if each replaced variable appears once in the original
expression.

One must therefore perform calculations in a manner that ensures this is the case.

————————————ORIGINAL POST————————————

I am working with several TimeSeries containing Around objects. I find that the propagated uncertainties for numerical values are larger than I expect them to be. In contrast, the propagated uncertainties for symbolic values are exactly what I expect them to be.

This is also true for lists of Around objects, so I will use List to demonstrate. Note that the original data values are all integers greater than or equal to zero (0 ≤ n[i] ∈ ℤ) and their original uncertainties equal their square roots (δn[i] = √n[i])

First, generate a list of symbolic data:

symbolicData = Table[Around[n[i], Sqrt[n[i]]], {i, 10}]

enter image description here

Then, Accumulate these data:

symbolicTotals = Accumulate@symbolicData

enter image description here

The uncertainty of the last value is the square root of that value:

{symbolicTotals[[-1]]["Uncertainty"], Sqrt@symbolicTotals[[-1]]["Value"]}

enter image description here

Given my understanding of error propagation, this is correct.

Now, generate numerical data:

numericalData = Table[Around[#, Sqrt[#]] &@RandomInteger[10], {i, 10}]

enter image description here

Acculumate these data:

numericalTotals = Accumulate@numericalData

enter image description here

Compare the last value’s uncertainty and square root:

{numericalTotals[[-1]]["Uncertainty"], Sqrt@numericalTotals[[-1]]["Value"]}

enter image description here

The uncertainty is larger than the square root. This happens for any long list of numbers.

Why? And how can I fix it? (Assuming there’s an actual problem here, and not simply a lack of knowledge on my end.)

My guess is that this discrepancy is a consequence of the fact that

When Around is used in computations, uncertainties are by default propagated using a first-order series approximation, assuming no correlations.

What exactly is being approximated here, and if Around always does this, why doesn’t it affect symbolic values?

I understand that AroundReplace allows for higher-order approximations, but it starts with a symbolic expression and substitutes numerical values. I’m starting with numerical values. Is my only option to generate TimeSeries objects with symbolic values, do all my computations, and then AroundReplace the symbols with the original numerical data?

Is there a better way?

————————————UPDATE————————————

@JulienKluge, @SjoerdSmit, and @JimB have suggested and demonstrated that this is a bug in Accumulate. I’ve done my own investigation, and I agree. Accumulate produces incorrectly propagated uncertainty whenever the same Around object appears multiple times in whatever is being accumulated. This error seems to increase with the number of duplicates.

Accumulate is not the only function with an issue. When the same Around object appears consecutively in a list, Differences produces a zero with no uncertainty!

enter image description here
(If you’d like a copy of the notebook in which I performed this investigation, click here.)

I’ve encountered the problem with Differences before, but I’m only now recognizing it as a serious issue. I suppose bugs like this are why Around is still an experimental function…

In light of everything, I think I will try doing all my calculations on symbolic TimeSeries objects and finishing them off with AroundReplace. Hopefully, that will circumvent the Accumulate and Differences issues as well as some other minor problems I’ve encountered. If that doesn’t work, I’ll compute the uncertainty bands myself…

Wish me luck!

————————————UPDATE————————————

AroundReplace took over ten minutes to replace the values of a symbolic TimeSeries with Around objects. No other functions such as Accumulate had yet been used. So, I won’t be using AroundReplace. ReplaceAll was much faster, but the documentation suggests it might introduce its own problems when working with Around.

Following the advice of @SjoerdSmit, I am going to try using FoldList[Plus]@list and MovingMap[Subtract[#[[2]], #[[1]]] &, #, 1] &@list as alternatives to Accumulate and Differences, respectively.

I’ll report back if there are any major changes.

3 Answers

Yes, this seems to be a bug. Compare, for example:

list1 = {Around[1., 2.], Around[1., 2.0001]};
Plus @@ list1
Fold[Plus, 0, list1]
Last @ Accumulate[list1]

Around[2., 2.8284978363081703`]

with

list2 = {Around[1., 2.], Around[1., 2.]};
Plus @@ list2
Fold[Plus, 0, list2]
Last @ Accumulate[list2]

Around[2., 2.8284271247461903`]

Around[2., 4.] (* result from Accumulate*)

I reported the issue. In the mean while you can use:

FoldList[Plus, 0, list2]

to get a correctly accumulated list.

Correct answer by Sjoerd Smit on May 7, 2021

Okay, wow. This stumped me for a bit.

But I found the answer. It seems to be a bug. An innocent looking one.

The fact you tried Integers instead of Reals triggered it. (I tried to use Reals first and failed to reproduce)

What happens is the following. Whenever Accumulate sees two equal values, it multiplies them by two instead of adding them. Which makes sense for reals

Accumulate[{a, b}]
Accumulate[{a, a}]

{a, a + b}

{a, 2a}

But not for Around's. The multiplication by two yields a different error propagation in the standard linear Gaussian approach

Accumulate[{a,b}]/.{a->Around[v,d],b->Around[v,d]}
Accumulate[{a,a}]/.{a->Around[v,d]}

{v±d,2 v±Sqrt[2] Sqrt[d^2]}

{v±d,2 v±2 d}

Judging from the comments, seems to be a bug. Someone/You should file it with Wolfram.

12.1.0 for Microsoft Windows (64-bit) (March 14, 2020)

Answered by Julien Kluge on May 7, 2021

I don't have enough reputation yet to comment but I will note that Accumulate can be particularly tricky with TimeSeries objects. This is well documented elsewhere but, in short, Accumulate applied to a TimeSeries object will interpolate "missing" values if your TimeSeries is not, by default, what Mathematica considers to be "Regularly Sampled". There are good reasons "under the hood" why this is the default behaviour but it's a trap for users who are inexperienced with the quirks of TimeSeries

To get around this, you can specify that your TimeSeries object is regularly sampled when you create it.

For the purpose of this example, assume you have some data ready to be created as a timeseries assigned to xyz:

newTimeseries = TimeSeries[xyz,TemporalRegularity->True]

When you now run Accumulate on this newTimeSeries object, you should get values as expected...but you may break other functionality by forcing the TemporalRegularity to True if it actually isn't.

Answered by R110 on May 7, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP