Math 480 -- 2008-04-18: Prime and Factorization system:sage
<h1>Prime Numbers</h1>
A <b>prime number</b> is a positive integer divisible by only itself and 1.
id=8| 
for n in [1..20]:
    print '%-4s%-7s'%(n, is_prime(n))
///
1   False  
2   True   
3   True   
4   False  
5   True   
6   False  
7   True   
8   False  
9   False  
10  False  
11  True   
12  False  
13  True   
14  False  
15  False  
16  False  
17  True   
18  False  
19  True   
20  False
id=10| 
@interact
def pr(max=(10..1000)):
    v = prime_range(max)
    print v
    show(points([(x,0) for x in v], pointsize=10), xmin=0, ymin=-0.1, ymax=0.1, figsize=[10,2])
///
<html><div padding=6 id='div-interact-10'> <table width=800px height=400px bgcolor='#c5c5c5'
                 cellpadding=15><tr><td bgcolor='#f9f9f9' valign=top align=left><table><tr><td align=right><font color="black">max </font></td><td><div id='slider-max-10' class='ui-slider-1' style='padding:0px;margin:0px;'><span class='ui-slider-handle'></span></div><script>setTimeout(function() { $('#slider-max-10').slider({
    stepping: 1, minValue: 0, maxValue: 990, startValue: 0,
    change: function () { var position = Math.ceil($('#slider-max-10').slider('value')); interact(10, "sage.server.notebook.interact.update(10, \"max\", 68, sage.server.notebook.interact.standard_b64decode(\""+encode64(position)+"\"), globals())"); }
});}, 1);</script></td></tr>
</table><div id='cell-interact-10'><?__SAGE__START>
        <table border=0 bgcolor='#white' width=100% height=100%>
        <tr><td bgcolor=white align=left valign=top><pre><?__SAGE__TEXT></pre></td></tr>
        <tr><td  align=left valign=top><?__SAGE__HTML></td></tr>
        </table><?__SAGE__END></div></td>
                 </tr></table></div>
                 </html>
Finding the next prime after a given prime is quite fast
id=11| time next_prime(10^100, proof=False) /// 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000267 CPU time: 0.01 s, Wall time: 0.01 s
id=12| time next_prime(10^100, proof=True) /// 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000267 CPU time: 0.28 s, Wall time: 0.33 s
id=14| # Let's make a ``personal prime'' time next_prime(101010101010101010101010101010101010101010101010) /// 101010101010101010101010101010101010101010101039 Time: CPU 0.02 s, Wall: 0.02 s
<br><br>By the way, it was an open problem for a very long time to give a deterministic polynomial time algorithm for primality. This was done a few years ago finally. See <a href="http://en.wikipedia.org/wiki/AKS_primality_test">http://en.wikipedia.org/wiki/AKS_primality_test</a>.
<br><br>This is not a function in Sage though, since there are <i>better in practice</i> nondeterministic primality tests, especially for numbers that aren't too big.
<br><br>The distribution of prime numbers is a problem that has fascinated people for a very long time.
<br><br>But what the heck does <i>distribution</i> mean?! There are many possible interpretations.
<br><br>One way to measure the distribution is to simply count the primes up to 
: $$ 
- \pi(x) = \#\{\text{primes } p : p \leq x\}.
 
$$
id=17| 
@interact
def primecount(m=(1..1000)):
    n = 100*m
    print "Primes up to %s"%n
    show(plot(prime_pi, 1, n), xmin=0)
///
<html><div padding=6 id='div-interact-17'> <table width=800px height=400px bgcolor='#c5c5c5'
                 cellpadding=15><tr><td bgcolor='#f9f9f9' valign=top align=left><table><tr><td align=right><font color="black">m </font></td><td><div id='slider-m-17' class='ui-slider-1' style='padding:0px;margin:0px;'><span class='ui-slider-handle'></span></div><script>setTimeout(function() { $('#slider-m-17').slider({
    stepping: 1, minValue: 0, maxValue: 999, startValue: 0,
    change: function () { var position = Math.ceil($('#slider-m-17').slider('value')); interact(17, "sage.server.notebook.interact.update(17, \"m\", 69, sage.server.notebook.interact.standard_b64decode(\""+encode64(position)+"\"), globals())"); }
});}, 1);</script></td></tr>
</table><div id='cell-interact-17'><?__SAGE__START>
        <table border=0 bgcolor='#white' width=100% height=100%>
        <tr><td bgcolor=white align=left valign=top><pre><?__SAGE__TEXT></pre></td></tr>
        <tr><td  align=left valign=top><?__SAGE__HTML></td></tr>
        </table><?__SAGE__END></div></td>
                 </tr></table></div>
                 </html>
<br><br> That curve above looks pretty smooth. It's natural to wonder what it is. Maybe it's just really complicated since there isn't a known easy way to find primes?!
<br><br> In fact, there is a <b>one hundred thousand dollar (100,000)</b> cash prize for finding a prime with at least ten million (10,000,000) decimal digits. See <a href="http://w2.eff.org/awards/coop-prime-rules.php">http://w2.eff.org/awards/coop-prime-rules.php</a>. (Note: a 50,000 dollar award was given in 2000 for a million digit prime.)
<br><br> Surprisingly $$
- \pi(x) \sim x/\log(x)
 
$$
id=21| 
@interact
def primecount(m=(1..1000)):
    n = 100*m; var('x')
    print "Primes up to %s"%n
    show(plot(prime_pi, 2, n) + plot(x/log(x), 4, n, color='red') , xmin=0, figsize=[9,3])
///
<html><div padding=6 id='div-interact-21'> <table width=800px height=400px bgcolor='#c5c5c5'
                 cellpadding=15><tr><td bgcolor='#f9f9f9' valign=top align=left><table><tr><td align=right><font color="black">m </font></td><td><div id='slider-m-21' class='ui-slider-1' style='padding:0px;margin:0px;'><span class='ui-slider-handle'></span></div><script>setTimeout(function() { $('#slider-m-21').slider({
    stepping: 1, minValue: 0, maxValue: 999, startValue: 0,
    change: function () { var position = Math.ceil($('#slider-m-21').slider('value')); interact(21, "sage.server.notebook.interact.update(21, \"m\", 70, sage.server.notebook.interact.standard_b64decode(\""+encode64(position)+"\"), globals())"); }
});}, 1);</script></td></tr>
</table><div id='cell-interact-21'><?__SAGE__START>
        <table border=0 bgcolor='#white' width=100% height=100%>
        <tr><td bgcolor=white align=left valign=top><pre><?__SAGE__TEXT></pre></td></tr>
        <tr><td  align=left valign=top><?__SAGE__HTML></td></tr>
        </table><?__SAGE__END></div></td>
                 </tr></table></div>
                 </html>
<br><br> In fact it is a <b>theorem</b> (the prime number theorem) that $$
- \lim_{x\to\infty} \pi(x) / (x/\log(x)) = 1.
 
$$
<br><br> Actually 
 isn't <i>that</i> good, though it looks superb in the picture above... 
id=28| prime_pi(10^7) /// 664579
id=29| float(10^7/log(10^7)) /// 620420.68843321688
<br><br> Let $$
- \text{Li}(x) = \int_{2}^x \frac{1}{\log(t)} dt
 
$$ This is just the area under the curve of the graph of 
, which is somehow a more precise way of <i>counting</i>. 
id=35| 
@interact
def primecount(m=(1..1000)):
    n = 100*m; var('x')
    print "Primes up to %s"%n
    show(plot(prime_pi, 2, n) + plot(Li, 4, n, color='red') , xmin=0, figsize=[9,3])
///
<html><div padding=6 id='div-interact-35'> <table width=800px height=400px bgcolor='#c5c5c5'
                 cellpadding=15><tr><td bgcolor='#f9f9f9' valign=top align=left><table><tr><td align=right><font color="black">m </font></td><td><div id='slider-m-35' class='ui-slider-1' style='padding:0px;margin:0px;'><span class='ui-slider-handle'></span></div><script>setTimeout(function() { $('#slider-m-35').slider({
    stepping: 1, minValue: 0, maxValue: 999, startValue: 0,
    change: function () { var position = Math.ceil($('#slider-m-35').slider('value')); interact(35, "sage.server.notebook.interact.update(35, \"m\", 71, sage.server.notebook.interact.standard_b64decode(\""+encode64(position)+"\"), globals())"); }
});}, 1);</script></td></tr>
</table><div id='cell-interact-35'><?__SAGE__START>
        <table border=0 bgcolor='#white' width=100% height=100%>
        <tr><td bgcolor=white align=left valign=top><pre><?__SAGE__TEXT></pre></td></tr>
        <tr><td  align=left valign=top><?__SAGE__HTML></td></tr>
        </table><?__SAGE__END></div></td>
                 </tr></table></div>
                 </html>
<br><br> This is <i>really good!</i>
id=34| prime_pi(10^7) /// 664579
id=33| Li(10^7) /// 664917.35989
<br><br> It is a <b>conjecture</b> (the <i>Riemann Hypothesis</i>!) that for all 
, we have $$ 
- |\pi(x) - \text{Li}(x)| \leq \sqrt{x}\cdot \log(x).
 
$$ That is <i>square root accurate</i>, which is amazingly good.
<br><br> Oh, by the way, you get a million dollars if you can prove the above inequality... <a href="http://www.claymath.org/millennium/">http://www.claymath.org/millennium/</a>
id=39| ///
id=38| ///
<br><br> <b>THEOREM:</b> Every positive integer can be written uniquely as product of primes. Proof:  Surprisingly not trivial.  Basically use the Euclidean algorithm to prove a special divisibility property, namely "if 
 divides 
, then 
 divides a or 
 divides 
".  The rest is straightforward. 
id=42| 
import random
def ftree(rows, v, i, F):
    if len(v) > 0: # add a row to g at the ith level.
        rows.append(v)
    w = []
    for i in range(len(v)):
        k, _, _ = v[i]
        if k is None or is_prime(k):
            w.append((None,None,None))
        else:
            d = random.choice(divisors(k)[1:-1])
            w.append((d,k,i))
            e = k//d
            if e == 1:
                w.append((None,None))
            else:
                w.append((e,k,i))
    if len(w) > len(v):
        ftree(rows, w, i+1, F)
def draw_ftree(rows,font):
    g = Graphics()
    for i in range(len(rows)):
        cur = rows[i]
        for j in range(len(cur)):
            e, f, k = cur[j]
            if not e is None:
                if is_prime(e):
                     c = (1,0,0)
                else:
                     c = (0,0,.4)
                g += text(str(e), (j*2-len(cur),-i), fontsize=font, rgbcolor=c)
                if not k is None and not f is None:
                    g += line([(j*2-len(cur),-i), ((k*2)-len(rows[i-1]),-i+1)], 
                    alpha=0.5)
    return g
@interact
def factor_tree(n=100, font=(10, (8..20)), redraw=['Redraw']):
    n = Integer(n)
    rows = []
    v = [(n,None,0)]
    ftree(rows, v, 0, factor(n))
    show(draw_ftree(rows, font), axes=False)
///
<html><div padding=6 id='div-interact-42'> <table width=800px height=400px bgcolor='#c5c5c5'
                 cellpadding=15><tr><td bgcolor='#f9f9f9' valign=top align=left><table><tr><td align=right><font color="black">n </font></td><td><input type='text' value='100' width=200px onchange='interact(42, "sage.server.notebook.interact.update(42, \"n\", 72, sage.server.notebook.interact.standard_b64decode(\""+encode64(this.value)+"\"), globals())")'></input></td></tr>
<tr><td align=right><font color="black">font </font></td><td><div id='slider-font-42' class='ui-slider-1' style='padding:0px;margin:0px;'><span class='ui-slider-handle'></span></div><script>setTimeout(function() { $('#slider-font-42').slider({
    stepping: 1, minValue: 0, maxValue: 12, startValue: 2,
    change: function () { var position = Math.ceil($('#slider-font-42').slider('value')); interact(42, "sage.server.notebook.interact.update(42, \"font\", 73, sage.server.notebook.interact.standard_b64decode(\""+encode64(position)+"\"), globals())"); }
});}, 1);</script></td></tr>
<tr><td align=right><font color="black">redraw </font></td><td><table style="border:1px solid #dfdfdf;background-color:#efefef">
<tr><td><button style='' value='0' onclick='interact(42, "sage.server.notebook.interact.update(42, \"redraw\", 74, sage.server.notebook.interact.standard_b64decode(\""+encode64(this.value)+"\"), globals())")'>Redraw</button>
</td></tr></table></td></tr>
</table><div id='cell-interact-42'><?__SAGE__START>
        <table border=0 bgcolor='#white' width=100% height=100%>
        <tr><td bgcolor=white align=left valign=top><pre><?__SAGE__TEXT></pre></td></tr>
        <tr><td  align=left valign=top><?__SAGE__HTML></td></tr>
        </table><?__SAGE__END></div></td>
                 </tr></table></div>
                 </html>
id=44| ///
id=48| n = next_prime(10^28) * next_prime(10^29) ///
id=45| time factor(n) /// 10000000000000000000000000331 * 100000000000000000000000000319 CPU time: 10.84 s, Wall time: 11.67 s
Integer factorization in Sage:
<ol>
<li> The <tt>factor</tt> command. This calls PARI's factor command, which implements the standard modern factoring algorithms including the elliptic curve method and the quadratic sieve. <li> The <tt>qsieve</tt> command. This calls Sage's (Bill Hart's) quadratic sieve implementation of the quadratic sieve. The sieve reduces factoring to an linear algebra problem. This implementation is better than the one in PARI. <li> The <tt>ecm</tt> command. This calls Sage's GMP-ECM (Paul Zimmerman), which is better than the ECM implementation in PARI.
</ol>
<br><br> The Sage factor command never calls qsieve or ecm. It should. Fixing this would be a <i>superb student project</i>.
id=47| time qsieve(n) /// ([10000000000000000000000000331, 100000000000000000000000000319], '') CPU time: 0.01 s, Wall time: 6.83 s
id=43| n = next_prime(10^14) * next_prime(10^50) ///
id=40| time factor(n) /// 100000000000031 * 100000000000000000000000000000000000000000000000151 CPU time: 3.81 s, Wall time: 3.95 s
id=50| time ecm.factor(n) /// [100000000000031, 100000000000000000000000000000000000000000000000151] CPU time: 0.01 s, Wall time: 0.45 s
<br><br> Parallel computation is extremely relevant fast integer factorization, though it's not used at all above. See the <tt>DistributedFactor</tt> command in Sage...
id=53| ///
id=51| ///
id=52| ///
id=49| ///