A curious infinite sum investigated with Python.
An investigation of the the following curious result:
Tracking the explanation given on Numberphile.
In [1]:
from IPython.display import YouTubeVideo
YouTubeVideo("w-I6XTVZXww")
Out[1]:
Series definitions
The video starts with an introduction, then at ~1:40 into the video he defines three series S1, S2 and S.
I would like to be able to define those same series in an as nearly as simple Python format, so defined a dummy class so I could concentrate on getting a nice description in Python.
Note: The class captures the series not the Sum of the series.
In [2]:
class Series(object):
"placeholder"
def __init__(self, **kwargs):
pass
In [3]:
# Numberphile 1:40
S1 = Series(fk=lambda k: (-1)**(k - 1), starts=[1, -1, 1, -1, 1, -1])
S2 = Series(fk=lambda k: (k*(-1)**(k - 1) if k > 1 else 1),
starts=[1, -2, 3, -4, 5, -6])
S = Series(fk=lambda k: k, starts=[1, 2, 3, 4, 5, 6])
Sum of the infinite series
At ~1:55 we need to find the sum of an infinite series by looking at the sum approaches.
I'll flesh out the Series class definition to handle what we have so far...
In [4]:
from fractions import Fraction
from itertools import islice, izip, count, chain
class Series(object):
"Represents infinite series by its generating function"
STARTSMAX = 10 # Limit on starts
def __init__(self, fk, starts=[]):
'''
Arguments
fk: Generating function
starts: Sample starting values of series. (checked)
'''
self.fk = fk
assert all(fk(k) == start for k, start in enumerate(starts, 1)),\
"Generating function does not create same starting values"
self.starts = [fk(k) for k in range(1, self.STARTSMAX + 1)]
def __call__(self):
"Generate successive values of the series"
k = 1
while True:
yield self.fk(k)
k += 1
In [5]:
# Numberphile 1:40
S1 = Series(fk=lambda k: (-1)**(k - 1), starts=[1, -1, 1, -1, 1, -1])
S2 = Series(fk=lambda k: (k*(-1)**(k - 1) if k > 1 else 1),
starts=[1, -2, 3, -4, 5, -6])
S = Series(fk=lambda k: k, starts=[1, 2, 3, 4, 5, 6])
Lets doodle...
In [6]:
S1.starts
Out[6]:
In [7]:
[x for n, x in zip(range(15), S2())]
Out[7]:
In [8]:
S.starts
Out[8]:
So you can see that
.starts
is a list of the first ten generated values, and calling an instance of the class gives a generator of successive values of the series (with no fixed upper limit).Sum S1 = 1 + -1 +1 + -1 ... == 1/2
From 2:00 minutes into the video he shows that the sum of the terms of S1 alternate between 1 and zero
In [9]:
running_sums = [sum(islice(S1(), termcount)) for termcount in range(1,21)]
running_sums
Out[9]:
Lets take the infinite sum as the average of the sums i.e.
Sum S1 = 1 -1 +1 -1 +1 ... = 0.5
2 * (Sum S2) == Sum S1
From 2:45 in the video.
Lets take S2, and S2 with an initial 0 inserted . (Adding zeroes will not affect the sum of the series remember).
In [10]:
S2.starts
Out[10]:
In [11]:
# S2 with an initial +0
[0] + S2.starts
Out[11]:
In [12]:
added_terms = (x + y for x, y in izip(S2(), chain([0], S2())))
list(islice(added_terms, 10))
Out[12]:
So, for the purposes of summation, 2 * S2 == S1 = 0.5
And therefore Sum S2 = 0.25
S - S2
From 4:08 in Video.
In [13]:
S.starts
Out[13]:
In [14]:
S2.starts
Out[14]:
Lets do the subtraction by subtracting the generating functions this time.
In [15]:
S_sub_S2 = Series(fk=lambda k: S.fk(k) - S2.fk(k))
S_sub_S2.starts
Out[15]:
Take a factor of four out and ignore the zeroes (as they do nothing for infinite sums).
In [16]:
list(islice((x/4 for x in S_sub_S2() if x), 10))
Out[16]:
End run
So:
sum(S) - sum(S2) = 4*(1+2+3+4+...) = 4 * ( sum(S) )
Solving:
sum(S) - 1/4 = 4*sum(S)
- 1/4 = 3*sum(S)
- 1/(4*3) = sum(S)
sum(S) = -1/12
Proving that the infinite sum 1+2+3+4+... = -1/12
The proof is in the eating
Remember that although it is a weird result, when used in scientific experiments we can predict nature.
For me, I now know that when dealing with equations involving infinite series I will annotate then with "There be dragons".