# Mathematica 12.1: Don't use Accumulate or Differences on Around objects!

SUMMARY:

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.

------------------------------------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}]

Then, Accumulate these data:

symbolicTotals = Accumulate@symbolicData

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

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

Given my understanding of error propagation, this is correct.

Now, generate numerical data:

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

Acculumate these data:

numericalTotals = Accumulate@numericalData

Compare the last value's uncertainty and square root:

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

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!

(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.

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.

• For the workaround and for reporting the bug, I'm accepting this answer! Even though I've other problems with Around objects, and might have to resort to AroundReplace after all... – Aaron Eiben 2 days ago
• @AaronEiben It might be worth trying alternative methods as well. Like I said, FolList[Plus, 0, list] is a valid alternative for Accumulate and such alternatives exist for Differences as well. For example, #2 - #1 & @@@ Partition[Range[5], 2, 1]. – Sjoerd Smit 2 days ago
• Agreed. AroundReplace took over ten minutes to replace the values in a symbolic TimeSeries--one that had not yet been operated upon! ReplaceAll was a thousand times faster, but the documentation suggests it will introduce its own problems with Around objects if not used carefully. So, I'm testing FoldList[Plus] as an alternative to Accumulate and MovingMap[Subtract[#[[2]], #[[1]]] &, #, 1]& as an alternative to Differences. These seem to work so far, and I'll update the original post as I learn more. Thanks again for your help! – Aaron Eiben 2 days ago
• It turns out FoldList doesn't play nicely with TimeSeries. For example, if test = TimeSeries[val /@ Range[0, 9]] then FoldList[Plus, 0, test] produces an error. Any other suggestions? – Aaron Eiben 2 days ago
• @AaronEiben Hmmm, not really. You can pull the timeseries apart with Normal; then fold the values (keeping the timestamps apart); and then put it all back together. That's the best I've got right now. – Sjoerd Smit yesterday

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)

• No, I think this is correct. Adding two different numbers with uncorrelated errors is different from adding the same number with the same error to itself. In the first case, the errors partially cancel because they're uncorrelated, which gives a smaller error overall. That's why AroundReplace exists along with ReplaceAll. Compare, e.g., AroundReplace[a + Sqrt[a], a -> Around[2., 0.3]] with ReplaceAll[a + Sqrt[a], a -> Around[2., 0.3]]. In the second case, the two terms are assumed to be uncorrelated. – Sjoerd Smit Feb 22 at 22:39
• Ahh darng...yes I think you are correct. This gotcha hit me already multiple times since I started using Around. Thanks. – Julien Kluge Feb 22 at 22:43
• No wait, wouldn't that mean, that Accumulate implicitly assumes the values to be the same and thus dependent? – Julien Kluge Feb 22 at 22:52
• @SjoerdSmit. I agree with Julien Kluge in that it's an Accumulate bug rather than an issue with Around. Consider a non-integer common value with the same uncertainty: Accumulate[{Around[4.5, 4], Around[4.5, 4]}][[2]] gives Around[9., 8.] when it should give Around[4.5 + 4.5, Sqrt[4^2 + 4^2]] which is Around[9., 5.656854249492381]. But if the uncertainties are different, then it gives the expected answer: Accumulate[{Around[4.5, 4], Around[4.5, 6]}][[2]] results in Around[9., 7.211102550927978] which is what Around[4.5 + 4.5, Sqrt[4^2 + 6^2]] produces. – JimB Feb 23 at 0:46
• Ah, yes. I see now. This is definitely confusing. It seems like you can obtain the right behaviour with Accumulate[{Around[a, b], Around[a, b2]}][[2]] /. b2 -> b. You can also see that Accumulate[{Around[1, 2.], Around[1, 2.0]}][[2]] is different from Accumulate[{Around[1, 2.], Around[1, 2.0001]}][[2]]. That's definitely a bug. I'll file it today. – Sjoerd Smit Feb 23 at 7:44