Figured out problem with Fermat test in problem 58.

main
Felix Martin 2019-02-02 12:22:43 -05:00
parent fe73c53c46
commit 45c7e862d3
3 changed files with 160 additions and 57 deletions

View File

@ -33,7 +33,9 @@
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_last_corner_value(side_length):\n",
@ -81,7 +83,7 @@
" return (base * expmod(base, exp - 1, m) % m)\n",
" \n",
"\n",
"def fermat_test(n):\n",
"def fermat_test_sicp(n):\n",
" if n < 40:\n",
" return n in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 39]\n",
" a = n - 3\n",
@ -145,10 +147,10 @@
" return False\n",
" return trial_division(n)[0] == n\n",
"\n",
"assert(fermat_test(3))\n",
"assert(fermat_test(107))\n",
"assert(fermat_test(108) == False)\n",
"assert(fermat_test(109))"
"assert(fermat_test_sicp(3))\n",
"assert(fermat_test_sicp(107))\n",
"assert(fermat_test_sicp(108) == False)\n",
"assert(fermat_test_sicp(109))"
]
},
{
@ -210,44 +212,33 @@
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import random\n",
"\n",
"def is_prime(n):\n",
" if n == 1:\n",
" return False\n",
" for _ in range(100):\n",
" a = n - random.randint(1, n - 1)\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" return True\n",
"\n",
"assert(fermat_test(3))\n",
"assert(fermat_test(107))\n",
"assert(fermat_test(108) == False)\n",
"assert(fermat_test(109))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"n: 26641 count_total: 53281 count_primes: 5328 ratio: 0.09999812315834913\n"
"n: 26641 count_total: 53281 count_primes: 5328 ratio: 0.09999812315834913\n",
"26641\n",
"Expected n is 26241.\n"
]
}
],
"source": [
"s = get_solution()"
"import random\n",
"\n",
"def is_prime(n):\n",
" if n == 1:\n",
" return False\n",
" for _ in range(10):\n",
" a = n - random.randint(1, n - 1)\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" return True\n",
"\n",
"print(get_solution())\n",
"print(\"Expected n is 26241.\")"
]
},
{
@ -261,6 +252,65 @@
"Try this algorithm instead [https://en.wikipedia.org/wiki/MillerRabin_primality_test](https://en.wikipedia.org/wiki/MillerRabin_primality_test)."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"n: 26241 count_total: 52481 count_primes: 5248 ratio: 0.09999809454850327\n",
"26241\n",
"For 561 sicp says True and real test says False.\n",
"For 1105 sicp says True and real test says False.\n",
"For 1729 sicp says True and real test says False.\n",
"For 2465 sicp says True and real test says False.\n",
"For 2821 sicp says True and real test says False.\n",
"For 6601 sicp says True and real test says False.\n"
]
}
],
"source": [
"carmichael_number = [561, 1105, 1729, 2465, 2821, 6601]\n",
"\n",
"def little_fermat(a, p): # SICP uses this\n",
" return (a ** p) % p == a % p\n",
"\n",
"def little_fermat_simple(a, p): # Wikipedia uses this\n",
" assert(a < p)\n",
" return (a ** (p - 1)) % p == 1\n",
"\n",
"def expmod(base, exp, m):\n",
" if exp == 0:\n",
" return 1\n",
" if (exp % 2 == 0):\n",
" return (expmod(base, exp // 2, m) ** 2 % m)\n",
" return (base * expmod(base, exp - 1, m) % m)\n",
"\n",
"def fermat_test(n):\n",
" ps = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 39]\n",
" if n <= ps[-1]:\n",
" return n in ps\n",
" for a in ps:\n",
" #if not little_fermat_simple(a, n):\n",
" if expmod(a, n - 1, n) != 1:\n",
" #print(\"Fermat witness for {} is {}.\".format(n + 1, a))\n",
" return False\n",
" return True\n",
"\n",
"def is_prime(n):\n",
" return fermat_test(n)\n",
"\n",
"print(get_solution())\n",
"\n",
"for n in carmichael_number:\n",
" r_sicp = fermat_test_sicp(n)\n",
" r = fermat_test(n)\n",
" print(\"For {} sicp says {} and real test says {}.\".format(n, r_sicp, r))\n"
]
},
{
"cell_type": "code",
"execution_count": null,

View File

@ -11846,7 +11846,7 @@ div#notebook {
<span class="k">return</span> <span class="p">(</span><span class="n">base</span> <span class="o">*</span> <span class="n">expmod</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">exp</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="o">%</span> <span class="n">m</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">fermat_test</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">fermat_test_sicp</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">40</span><span class="p">:</span>
<span class="k">return</span> <span class="n">n</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">17</span><span class="p">,</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">29</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">37</span><span class="p">,</span> <span class="mi">39</span><span class="p">]</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">3</span>
@ -11910,10 +11910,10 @@ div#notebook {
<span class="k">return</span> <span class="kc">False</span>
<span class="k">return</span> <span class="n">trial_division</span><span class="p">(</span><span class="n">n</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">n</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test</span><span class="p">(</span><span class="mi">3</span><span class="p">))</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test</span><span class="p">(</span><span class="mi">107</span><span class="p">))</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test</span><span class="p">(</span><span class="mi">108</span><span class="p">)</span> <span class="o">==</span> <span class="kc">False</span><span class="p">)</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test</span><span class="p">(</span><span class="mi">109</span><span class="p">))</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test_sicp</span><span class="p">(</span><span class="mi">3</span><span class="p">))</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test_sicp</span><span class="p">(</span><span class="mi">107</span><span class="p">))</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test_sicp</span><span class="p">(</span><span class="mi">108</span><span class="p">)</span> <span class="o">==</span> <span class="kc">False</span><span class="p">)</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test_sicp</span><span class="p">(</span><span class="mi">109</span><span class="p">))</span>
</pre></div>
</div>
</div>
@ -11989,7 +11989,7 @@ div#notebook {
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [5]:</div>
<div class="prompt input_prompt">In [12]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">random</span>
@ -11997,27 +11997,14 @@ div#notebook {
<span class="k">def</span> <span class="nf">is_prime</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">n</span> <span class="o">-</span> <span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">expmod</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">==</span> <span class="n">a</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test</span><span class="p">(</span><span class="mi">3</span><span class="p">))</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test</span><span class="p">(</span><span class="mi">107</span><span class="p">))</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test</span><span class="p">(</span><span class="mi">108</span><span class="p">)</span> <span class="o">==</span> <span class="kc">False</span><span class="p">)</span>
<span class="k">assert</span><span class="p">(</span><span class="n">fermat_test</span><span class="p">(</span><span class="mi">109</span><span class="p">))</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [6]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">s</span> <span class="o">=</span> <span class="n">get_solution</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="n">get_solution</span><span class="p">())</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Expected n is 26241."</span><span class="p">)</span>
</pre></div>
</div>
</div>
@ -12028,6 +12015,8 @@ div#notebook {
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>n: 26641 count_total: 53281 count_primes: 5328 ratio: 0.09999812315834913
26641
Expected n is 26241.
</pre>
</div>
</div>
@ -12046,6 +12035,70 @@ div#notebook {
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [10]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">carmichael_number</span> <span class="o">=</span> <span class="p">[</span><span class="mi">561</span><span class="p">,</span> <span class="mi">1105</span><span class="p">,</span> <span class="mi">1729</span><span class="p">,</span> <span class="mi">2465</span><span class="p">,</span> <span class="mi">2821</span><span class="p">,</span> <span class="mi">6601</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">little_fermat</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span> <span class="c1"># SICP uses this</span>
<span class="k">return</span> <span class="p">(</span><span class="n">a</span> <span class="o">**</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span> <span class="o">==</span> <span class="n">a</span> <span class="o">%</span> <span class="n">p</span>
<span class="k">def</span> <span class="nf">little_fermat_simple</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span> <span class="c1"># Wikipedia uses this</span>
<span class="k">assert</span><span class="p">(</span><span class="n">a</span> <span class="o">&lt;</span> <span class="n">p</span><span class="p">)</span>
<span class="k">return</span> <span class="p">(</span><span class="n">a</span> <span class="o">**</span> <span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span> <span class="o">==</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">expmod</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">exp</span><span class="p">,</span> <span class="n">m</span><span class="p">):</span>
<span class="k">if</span> <span class="n">exp</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">if</span> <span class="p">(</span><span class="n">exp</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">expmod</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">exp</span> <span class="o">//</span> <span class="mi">2</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">%</span> <span class="n">m</span><span class="p">)</span>
<span class="k">return</span> <span class="p">(</span><span class="n">base</span> <span class="o">*</span> <span class="n">expmod</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">exp</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="o">%</span> <span class="n">m</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">fermat_test</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">ps</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">17</span><span class="p">,</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">29</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">37</span><span class="p">,</span> <span class="mi">39</span><span class="p">]</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="n">ps</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">return</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">ps</span>
<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">ps</span><span class="p">:</span>
<span class="c1">#if not little_fermat_simple(a, n):</span>
<span class="k">if</span> <span class="n">expmod</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
<span class="c1">#print("Fermat witness for {} is {}.".format(n + 1, a))</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="k">def</span> <span class="nf">is_prime</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">return</span> <span class="n">fermat_test</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">get_solution</span><span class="p">())</span>
<span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">carmichael_number</span><span class="p">:</span>
<span class="n">r_sicp</span> <span class="o">=</span> <span class="n">fermat_test_sicp</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">fermat_test</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"For </span><span class="si">{}</span><span class="s2"> sicp says </span><span class="si">{}</span><span class="s2"> and real test says </span><span class="si">{}</span><span class="s2">."</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">r_sicp</span><span class="p">,</span> <span class="n">r</span><span class="p">))</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>n: 26241 count_total: 52481 count_primes: 5248 ratio: 0.09999809454850327
26241
For 561 sicp says True and real test says False.
For 1105 sicp says True and real test says False.
For 1729 sicp says True and real test says False.
For 2465 sicp says True and real test says False.
For 2821 sicp says True and real test says False.
For 6601 sicp says True and real test says False.
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
<div class="input_area">

View File

@ -11770,7 +11770,7 @@ div#notebook {
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h1 id="Problem-Name-(Euler-Problem-xxx)">Problem Name (Euler Problem xxx)<a class="anchor-link" href="#Problem-Name-(Euler-Problem-xxx)"></a></h1><p><a href="/euler">Back to overview.</a></p>
<h1 id="Magic-5-gon-ring-(Euler-Problem-68)">Magic 5-gon ring (Euler Problem 68)<a class="anchor-link" href="#Magic-5-gon-ring-(Euler-Problem-68)"></a></h1><p><a href="/euler">Back to overview.</a></p>
</div>
</div>
</div>