# How to avoid this Parallel Error

I want parallelize one task, but got some stupid error. I don't know why i got it and how to fix it. I have 2 examples. One works:

Do[s[a] =
NDSolve[{y'[x] == y[x] Cos[a x + y[x]], y == 1},
y, {x, 0, 5}], {a, 1, 10, .3}]
ListPlot[Table[{a, NIntegrate[y'[x]^2 /. s[a][], {x, 0, 5}]}, {a,
1, 10, .3}], PlotRange -> All]


This fails:

Do[s[a] =
NDSolve[{y'[x] == y[x] Cos[a x + y[x]], y == 1},
y, {x, 0, 5}], {a, 1, 10, .3}]
ListPlot[ParallelTable[{a,
N[Integrate[y'[x]^2 /. s[a][], {x, 0, 5}]]}, {a, 1, 10, .3}],
PlotRange -> All]


Why? How can i fi it? But if i change increment 0.3 to 0.5:

Do[s[a] =
NDSolve[{y'[x] == y[x] Cos[a x + y[x]], y == 1},
y, {x, 0, 5}], {a, 1, 10, .5}]
ListPlot[Table[{a, NIntegrate[y'[x]^2 /. s[a][], {x, 0, 5}]}, {a,
1, 10, .5}], PlotRange -> All]

Do[s[a] =
NDSolve[{y'[x] == y[x] Cos[a x + y[x]], y == 1},
y, {x, 0, 5}], {a, 1, 10, .5}]
ListPlot[ParallelTable[{a,
N[Integrate[y'[x]^2 /. s[a][], {x, 0, 5}]]}, {a, 1, 10, .5}],
PlotRange -> All]


Both examples works fine. I can't understand this. Can i fix it?

• First rule of debugging (or asking for debugging help here): reduce your code to the absolute smallest example that still exhibits the problem. Jun 15, 2016 at 15:28
• OK, I found the reason. Will write an answer shortly. Jun 15, 2016 at 15:35

The reason for this behaviour is that Table and ParallelTable generate the range from 1 to 10 by steps of 0.3 in slightly different ways. You are working with inexact (floating point) numbers. This means that even the slightest change in the order of arithmetic operations may change the result. (a+b) + c may give a different result from a + (b+c).

Obligatory reference:

Normally, Mathematica protects against this by allowing for a tolerance in ==-comparisons. But there is zero tolerance in pattern matching. Only two exactly equal expressions will be treated the same by MatchQ.

For this reason it is not a very good idea to define s[someNumber] = ... like this. Even without talking about precision, consider:

ff = "a";
ff[1.] = "b";
ff[1.10] = "c"; We have three different definitions for the three different kinds of numbers. Mathematically they are equal. But they are otherwise distinct expressions.

Thus,

1 == 1. == 1.10
(* True *)


With SameQ there is already a difference, but it considers some of them to be the same:

{1 === 1., 1. === 1.10, 1 === 1.10}
(* {False, True, False} *)


For pattern matching, they're all different:

{MatchQ[1, 1.], MatchQ[1., 1.10], MatchQ[1, 1.10]}
(* {False, False, False} *)


s /@ ParallelTable[a, {a, 1, 10, 0.3}]

(* s[2.8] fails to match on my system *)

s /@ Range[1,10,0.3]

(* there's a match for every value on my system *)

alist = {}
a = 1.;
While[a <= 10,
AppendTo[alist, a];
a += 0.3;
]
s /@ alist

(* s fails to match for 1.9 on my system *)


Workaround 1:

rules = Table[
a -> First@
NDSolve[{y'[x] == y[x] Cos[a x + y[x]], y == 1},
y, {x, 0, 5}], {a, 1, 10, .3}];

nf = Nearest[rules]


nf[1.] now gives the match for 1.. This is a bit dangerous because it also gives the same match for 1.1 since 1.1 is nearest to 1. out of the given points.

Workaround 2:

Use Round on a every time you set s or read s. Choose the desired precision. For example,

Do[s[Round[a, 0.001]] =
NDSolve[{y'[x] == y[x] Cos[a x + y[x]], y == 1},
y, {x, 0, 5}], {a, 1, 10, .3}];


Then, use s[Round[a,0.001]] when you read s too.