From 8f7f1a718d174b8a64de4f02bdd53cc7c2b1cefc Mon Sep 17 00:00:00 2001 From: Peter Norvig Date: Fri, 6 Apr 2018 17:50:12 -0700 Subject: [PATCH] Add files via upload --- ipynb/Beal.ipynb | 294 ++++++++++++++++++----------------------------- 1 file changed, 111 insertions(+), 183 deletions(-) diff --git a/ipynb/Beal.ipynb b/ipynb/Beal.ipynb index e41e1c8..24ac4bd 100644 --- a/ipynb/Beal.ipynb +++ b/ipynb/Beal.ipynb @@ -33,7 +33,7 @@ "\n", "# Online Beal Counterexample Checker\n", "\n", - "Got a counterexample? Check it with my [Online Beal Counterexample Checker](http://norvig.com/bealcheck.html).\n", + "Got a counterexample? Verify it with my [Beal Counterexample Checker](http://norvig.com/bealcheck.html).\n", "\n", "# How to Not Win A Million Dollars\n", "\n", @@ -53,7 +53,7 @@ "* Another claimed that $2^3+2^3=2^4$ was a counterexample, because all the bases are 2, which is prime, and prime numbers have no prime factors. But that's not true; a prime number has itself as a factor.\n", "\n", "\n", - "* A creative person offered $1359072^4 - 940896^4 = 137998080^3$, which fails both because $3^3 2^5 11^2$ is a common factor, and because it has a subtraction rather than an addition (although, as Julius Jacobsen pointed out, it could be rewritten as $137998080^3 + 940896^4 = 1359072^4$).\n", + "* A creative person offered $ 1359072^4 - 940896^4 = 137998080^3$, which fails both because $ 3^3 2^5 11^2 $ is a common factor, and because it has a subtraction rather than an addition (although, as Julius Jacobsen pointed out, it could be rewritten as $ 137998080^3 + 940896^4 = 1359072^4 $).\n", "\n", "\n", "* Mustafa Pehlivan came up with an example involving 76-million-digit numbers, which took some work to prove wrong (using modulo arithmetic). \n", @@ -89,16 +89,27 @@ } ], "source": [ + "from math import gcd #### In Python versions < 3.5, use \"from fractions import gcd\"\n", + "\n", "A, B, C = 60000000000000000000, 70000000000000000000, 82376613842809255677\n", "x = y = z = 3.\n", - "A ** x + B ** y == C ** z" + "\n", + "A ** x + B ** y == C ** z and gcd(gcd(A, B), C) == 1" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "button": false, + "new_sheet": false, + "run_control": { + "read_only": false + } + }, "source": [ - "That's interesting; the equality is true. But to show that this is a valid counterexample, we have to show that `A, B, C` have no common factor; that is, that their greatest common divisor (`gcd`) is 1:" + "**WOW! The result is `True`!** The two sides of the equation are equal, and the greatest common divisor is 1. Is this a real counterexample to Beal? And also a disproof of Fermat's Last Theorem?\n", + "\n", + "Alas, it is not. The decimal point in \"`x = y = z = 3.`\" indicates a floating point number, with inexact, limited precision. Change the inexact \"`3.`\" to an exact \"`3`\" and the two sides of the equation are no longer equal. Below we see they are the same for the first 18 digits, but differ starting with the 19th: " ] }, { @@ -112,50 +123,6 @@ "read_only": false } }, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from math import gcd #### In Python versions < 3.5, use \"from fractions import gcd\"\n", - "\n", - "gcd(gcd(A, B), C) == 1" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "button": false, - "new_sheet": false, - "run_control": { - "read_only": false - } - }, - "source": [ - "**WOW! The result is `True`!** Is this a real counterexample to Beal? And also a disproof of Fermat's Last Theorem?\n", - "\n", - "Alas, it is not. The decimal point in \"`x = y = z = 3.`\" indicates a floating point number, with inexact, limited precision. Change the inexact \"`3.`\" to an exact \"`3`\" and the two sides of the equation are no longer equal. Below we see they are the same for the first 18 digits, but differ starting with the 19th: " - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "button": false, - "collapsed": false, - "new_sheet": false, - "run_control": { - "read_only": false - } - }, "outputs": [ { "data": { @@ -164,7 +131,7 @@ " 559000000000000000063037470301555182935702892172500189973733)" ] }, - "execution_count": 3, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -196,131 +163,92 @@ "$3987^{12} + 4365^{12} = 4472^{12}$ and $1782^{12} + 1841^{12} = 1922^{12}$. These were designed by *Simpsons* writer David X. Cohen to be correct up to the precision found in most handheld calculators. Cohen found the equations with a program that must have been something like this:" ] }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1782**12 + 1841**12 == 1922**12 has relative error of 3e-10\n", + "3987**12 + 4365**12 == 4472**12 has relative error of 2e-11\n" + ] + } + ], + "source": [ + "from itertools import combinations\n", + "\n", + "def Fermat(A, B, n):\n", + " \"Return a tuple of the form (error, A, B, C, n)\"\n", + " C = int(round((A ** n + B ** n) ** (1/n)))\n", + " lhs, rhs = A ** n + B ** n, C ** n\n", + " error = abs(lhs - rhs) / rhs\n", + " return (error, A, B, C, n)\n", + "\n", + "def simpsons(bases, powers):\n", + " \"\"\"Find the Fermat equation that minimizes the error.\"\"\"\n", + " return min(Fermat(A, B, n) \n", + " for A, B in combinations(bases, 2) \n", + " for n in powers)\n", + "\n", + "def show(fermat):\n", + " (error, A, B, C, n) = fermat\n", + " print('{}**{} + {}**{} == {}**{} has relative error of {:.0g}'\n", + " .format(A, n, B, n, C, n, error))\n", + " \n", + "show(simpsons(range(1000, 2000), [12]))\n", + "show(simpsons(range(3000, 5000), [12]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These are the same two equations that David X. Cohen found. The sides of the equations are nearly equal, up to 10 or 11 decimal places, respectively.\n", + "\n", + "Can we do better? The following search will take about 8 minutes:" + ] + }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, - "outputs": [], - "source": [ - "from collections import namedtuple\n", - "from itertools import combinations\n", - "\n", - "Fermat = namedtuple('Fermat', 'A, B, C, n')\n", - "\n", - "def err(equation):\n", - " \"The relative error in a Fermat-style equation\"\n", - " (A, B, C, n) = equation\n", - " return abs(A ** n + B ** n - C ** n) / C ** n\n", - "\n", - "def simpsons(bases, powers):\n", - " \"\"\"Find the Fermat equation that minimizes the error (the\n", - " difference between A ** n + B ** n and C ** n). \n", - " Let A, B range over all pairs of bases and n over all powers.\"\"\"\n", - " return min((Fermat(A, B, int((A ** n + B ** n) ** (1/n)), n) \n", - " for A, B in combinations(bases, 2) for n in powers),\n", - " key=err)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "button": false, - "collapsed": false, - "new_sheet": false, - "run_control": { - "read_only": false - } - }, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2196**3 + 5984**3 == 6081**3 has relative error of 4e-12\n" + ] + }, { "data": { "text/plain": [ - "Fermat(A=3987, B=4365, C=4472, n=12)" + "(224866629440, 224866629441)" ] }, - "execution_count": 5, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "simpsons(range(3000, 5000), range(11, 14))" + "(_, A, B, C, n) = f = simpsons(range(1000, 6000), range(3, 13))\n", + "show(f)\n", + "A ** n + B ** n, C ** n" ] }, { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "button": false, - "collapsed": false, - "new_sheet": false, - "run_control": { - "read_only": false - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Fermat(A=1010, B=1897, C=1988, n=3)" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "simpsons(range(1000, 2000), range(3, 16))" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(63976656349698612616236230953154487896987106,\n", - " 63976656348486725806862358322168575784124416)" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "3987 ** 12 + 4365 ** 12, 4472 ** 12" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(2541210258614589176288669958142428526657,\n", - " 2541210259314801410819278649643651567616)" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "1782 ** 12 + 1841 ** 12, 1922 ** 12" + "This is an equation that differs by just 1 in the 12th and last decmal place." ] }, { @@ -348,7 +276,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": { "button": false, "collapsed": true, @@ -414,7 +342,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 6, "metadata": { "button": false, "collapsed": false, @@ -428,8 +356,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 362 ms, sys: 3.33 ms, total: 366 ms\n", - "Wall time: 406 ms\n" + "CPU times: user 354 ms, sys: 4.32 ms, total: 358 ms\n", + "Wall time: 376 ms\n" ] } ], @@ -447,12 +375,12 @@ } }, "source": [ - "The execution time goes up roughly with the square of `max_A`, so the following should take about 100 times longer:" + "The execution time goes up roughly with the square of `max_A`, so the following should take about 25 times longer:" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 7, "metadata": { "button": false, "collapsed": false, @@ -466,13 +394,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 43.3 s, sys: 335 ms, total: 43.7 s\n", - "Wall time: 46.5 s\n" + "CPU times: user 11.1 s, sys: 152 ms, total: 11.3 s\n", + "Wall time: 12.3 s\n" ] } ], "source": [ - "%time beal(1000, 100)" + "%time beal(500, 100)" ] }, { @@ -497,7 +425,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 8, "metadata": { "button": false, "collapsed": false, @@ -518,7 +446,7 @@ " 6: [216, 1296, 7776, 279936]}" ] }, - "execution_count": 12, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -543,7 +471,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "metadata": { "button": false, "collapsed": false, @@ -579,7 +507,7 @@ " 279936: 6}" ] }, - "execution_count": 13, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -591,7 +519,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 10, "metadata": { "collapsed": false }, @@ -602,7 +530,7 @@ "3" ] }, - "execution_count": 14, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -631,7 +559,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 11, "metadata": { "button": false, "collapsed": false, @@ -680,7 +608,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 12, "metadata": { "button": false, "collapsed": false, @@ -696,7 +624,7 @@ "{True}" ] }, - "execution_count": 16, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -730,7 +658,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 13, "metadata": { "button": false, "collapsed": true, @@ -761,7 +689,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 14, "metadata": { "button": false, "collapsed": false, @@ -777,7 +705,7 @@ "'tests pass'" ] }, - "execution_count": 18, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -882,7 +810,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 15, "metadata": { "button": false, "collapsed": true, @@ -947,7 +875,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 16, "metadata": { "collapsed": false }, @@ -963,7 +891,7 @@ " 6: [(216, 3), (296, 4), (776, 5), (936, 7)]}" ] }, - "execution_count": 20, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -989,7 +917,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 17, "metadata": { "button": false, "collapsed": false, @@ -1024,7 +952,7 @@ " 936: [(6, 7)]})" ] }, - "execution_count": 21, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -1048,7 +976,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 18, "metadata": { "button": false, "collapsed": false, @@ -1062,8 +990,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 1min 2s, sys: 646 ms, total: 1min 3s\n", - "Wall time: 1min 8s\n" + "CPU times: user 55.9 s, sys: 530 ms, total: 56.4 s\n", + "Wall time: 59.6 s\n" ] } ],