Files
pytudes/ipynb/Euler's Conjecture.ipynb
2018-07-09 13:35:54 -07:00

5.7 KiB

Euler's Sum of Powers Conjecture

In 1769, Leonhard Euler conjectured that for all integers n and k greater than 1, if the sum of n kth powers of positive integers is itself a kth power, then n is greater than or equal to k. For example, this would mean that no sum of a pair of cubes (a3 + b3) can be equal to another cube (c3), but a sum of three cubes can, as in 33 + 43 + 53 = 63.

It took 200 years to disprove the conjecture: in 1966 L. J. Lander and T. R. Parkin published a refreshingly short article giving a counterexample of four fifth-powers that summed to another fifth power. They found it via a program that did an exhaustive search. Can we duplicate their work and find integers greater than 1 such that a5 + b5 + c5 + d5 = e5 ?

Algorithm

An exhaustive O(m4) algorithm woud be to look at all values of a, b, c, d < m and check if a5 + b5 + c5 + d5 is a fifth power. But we can do better: a sum of four numbers is a sum of two pairs of numbers, so we are looking for

     pair1 + pair2 = e5    where   pair1 = a5 + b5 and pair2 = c5 + d5.

We will define pairs be a dict of {a5 + b5: (a5, b5)} entries for all ab < m; for example, for a=2 and b=10, the entry is {100032: (32, 100000)}. Then we can ask for each pair1, and for each e, whether there is a pair2 in the dict that makes the equation work. There are O(m2) pairs and O(m) values of e, and dict lookup is O(1), so the whole algorithm is O(m3):

In [1]:
import itertools

def euler(m):
    """Yield tuples (a, b, c, d, e) such that a^5 + b^5 + c^5 + d^5 = e^5,
    where all are integers, and 1 < a ≤ b ≤ c ≤ d < e < m."""
    powers = [e**5 for e in range(2, m)] 
    pairs  = {sum(pair): pair 
              for pair in itertools.combinations_with_replacement(powers, 2)}
    for pair1 in pairs:
        for e5 in powers:
            pair2 = e5 - pair1
            if pair2 in pairs:
                yield fifthroots(pairs[pair1] + pairs[pair2] + (e5,))
    
def fifthroots(nums): 
    "Sorted integer fifth roots of a collection of numbers." 
    return tuple(sorted(int(round(x ** (1/5))) for x in nums))

Let's look for a solution (arbitrarily choosing m=500):

In [2]:
%time next(euler(500))
CPU times: user 1.07 s, sys: 21.4 ms, total: 1.09 s
Wall time: 1.11 s
Out[2]:
(27, 84, 110, 133, 144)

That was easy, and it turns out this is the same answer that Lander and Parkin got: 275 + 845 + 1105 + 1335 = 1445.

We can keep going, collecting all the solutions up to *m*=1000:

In [3]:
%time set(euler(1000))
CPU times: user 1min 53s, sys: 706 ms, total: 1min 54s
Wall time: 1min 57s
Out[3]:
{(27, 84, 110, 133, 144),
 (54, 168, 220, 266, 288),
 (81, 252, 330, 399, 432),
 (108, 336, 440, 532, 576),
 (135, 420, 550, 665, 720),
 (162, 504, 660, 798, 864)}

All the answers are multiples of the first one (this is easiest to see in the middle column: 110, 220, 330, ...). Since 1966 other mathematicians have found other solutions, but all we need is one to disprove Euler's conjecture.