import primes_in_intervals as pii
Jump to: ↓ Example 2 | ↓↓ Example 3 | ↓↓ Example 4
Example 1. Tables from Gauss's Nachlass. Create data for primes in disjoint intervals of length
By the bye, an interval of the form
C = list(range(0,10*10**6 + 1, 10**5))
H = 100
nachlass = pii.intervals(C,H,'disjoint')
Gauss and Goldschmidt summarize their data in tables of primes up to
NACHLASS = { }
for i in range(1,11):
NACHLASS[i] = pii.extract(nachlass, [(i - 1)*10**6, i*10**6] , option='narrow')
pii.partition(NACHLASS[i])
Let's display one of these tables: the one for primes between
NACHLASS3df = pii.display(NACHLASS[3], count='partition', orient='columns')
pii.dfi.export(NACHLASS3df, 'NACHLASS3df.png')
Here's the original: Gauss/Goldschmidt were only short by
Jump to: ↑ Example 1 | ↓ Plot | ↓ Example 3 | ↓↓ Example 4
Example 2. Let's look at a series of nested intervals centred around
import numpy as np
N = int(np.exp(17))
HH = [64, 68, 72, 76, 80]
C = list(range(N - 10**4,N + 10**4 + 1, 10**2))
EXP17 = {}
for H in HH:
EXP17[H] = pii.intervals(C, H, 'overlap')
Right now we have data for the intervals
EXP17NEST = {}
for H in HH:
EXP17NEST[H] = pii.nest(EXP17[H])
pii.analyze(EXP17NEST[H])
Let's display what we have for
EXP17_76_NESTtable = pii.display(EXP17NEST[76])
pii.dfi.export(EXP17_76_NESTtable, 'EXP17_76_NESTtable.png')
Let's compare the data (for
Our prediction is
Our alternative prediction is, with
The table below shows tuples
We'll just show the last five rows of the table as it's a bit long and hard to read.
pii.compare(EXP17NEST[76])
EXP17_76_NESTcompare = pii.display(EXP17NEST[76], comparisons='absolute').tail(5)
pii.dfi.export(EXP17_76_NESTcompare, 'EXP17_76_NESTcompare_tail.png')
We can perhaps work on the formatting of such tables.
Now, we want to know which prediction is the "best", and this is hard to see by glancing at the above table. By "best" we mean gives the smallest sum-of-squared-error over
We'll use our winners
function to determine the best predictions for each interval. For each prediction, this function also gives us the
pii.winners(EXP17NEST[76])
EXP17_76_NESTwinners = pii.display(EXP17NEST[76], winners='show')
pii.dfi.export(EXP17_76_NESTwinners, 'EXP17_76_NESTwinners.png')
Finally, let's make an animated plot, with one frame for each of the intervals considered.
import matplotlib.pyplot as plt # for plotting distributions
from matplotlib import animation # for animating sequences of plots
from matplotlib import rc # to help with the animation
from IPython.display import HTML # to save animations
from matplotlib.animation import PillowWriter # to save animations as a gif
# HH = [64, 68, 72, 76, 80]
X = EXP17NEST[HH[0]]
interval_type = X['header']['interval_type']
A = X['header']['lower_bound']
H = X['header']['interval_length']
C = list(X['distribution'].keys())
plt.rcParams.update({'font.size': 22})
fig, ax = plt.subplots(figsize=(22, 11))
fig.suptitle('Primes in intervals')
hor_axis = list(X['distribution'][C[-1]].keys())
y_min, y_max = 0, 0
for c in C:
for m in X['distribution'][c].keys():
if y_max < X['distribution'][c][m]:
y_max = X['distribution'][c][m]
def plot(c):
ax.clear()
mu = X['statistics'][c]['mean']
sigma = X['statistics'][c]['var']
med = X['statistics'][c]['med']
if med == int(med):
med = int(med)
modes = X['statistics'][c]['mode']
# Bounds for the plot, and horizontal axis tick marks.
ax.set(xlim=(hor_axis[0]-0.5, hor_axis[-1]+0.5), ylim=(0,np.ceil(1000*y_max)/1000 ))
# The data and histogram
ver_axis = list(X['distribution'][c].values())
ax.bar(hor_axis, ver_axis, color='#e0249a', zorder=2.5, alpha=0.3, label=r'$\mathrm{Prob}(X = m)$')
ax.plot(hor_axis, ver_axis, 'o', color='red', zorder=2.5)
# Predictions for comparison
A = c[0]
B = c[1]
N = (A + B)//2
exponent= str(int(np.log(N)) + 1)
M = N - A
k = M//10**2
p = 1/(np.log(N) - 1)
x = np.linspace(hor_axis[0],hor_axis[-1],100)
ax.plot(x, pii.binom_pmf(H,x,p), '--', color='orange', zorder=3.5, label=r'$\mathrm{Binom}(H,\lambda/H)$')
ax.plot(x, pii.frei(H,x,H*p), '--', color='green', zorder=3.5, label=r'$\mathrm{F}(H,m,\lambda)$')
# Overlay information
if B != C[-1][1]:
ax.text(0.75,0.15,fr'$X = \pi(a + H) - \pi(a)$' + '\n\n'
+ fr'$N - M < a \leq N + M$' + '\n\n'
+ fr'$H = {H}$' + '\n\n'
+ r'$N = [e^{17}]$' + '\n\n'
+ fr'$M = 10^2k$, $k = {k}$' + '\n\n'
+ fr'$\lambda = H/(\log N - 1) = {H*p:.5f}$' + '\n\n'
+ r'$\mathbb{E}[X] = $' + f'{mu:.5f}' + '\n\n'
+ r'$\mathrm{Var}(X) = $' + f'{sigma:.5f}' + '\n\n'
+ fr'median : ${med}$' + '\n\n'
+ fr'mode(s): ${modes}$', bbox=dict(facecolor='white', edgecolor='white', alpha=0.5), transform=ax.transAxes)
if B == C[-1][1]:
ax.text(0.75,0.15,fr'$X = \pi(a + H) - \pi(a)$' + '\n\n'
+ fr'$N - M < a \leq N + M$' + '\n\n'
+ fr'$H = {H}$' + '\n\n'
+ r'$N = [e^{17}]$' + '\n\n'
+ fr'$M = 10^4$' + '\n\n'
+ fr'$\lambda = H/(\log N - 1) = {H*p:.5f}$' + '\n\n'
+ r'$\mathbb{E}[X] = $' + f'{mu:.5f}' + '\n\n'
+ r'$\mathrm{Var}(X) = $' + f'{sigma:.5f}' + '\n\n'
+ fr'median : ${med}$' + '\n\n'
+ fr'mode(s): ${modes}$', bbox=dict(facecolor='white', edgecolor='white', alpha=0.5), transform=ax.transAxes)
# Formating/labeling
ax.set_xticks(hor_axis)
ax.set_xlabel(r'$m$ (number of primes in an interval)')
ax.set_ylabel('prop\'n of intervals with' + r' $m$ ' + 'primes')
ax.legend(loc=2, ncol=1, framealpha=0.5)
# A grid is helpful, but we want it underneath everything else.
ax.grid(True,zorder=0,alpha=0.7)
# Generate the animation
X_anim = animation.FuncAnimation(fig, plot, frames=C, interval=100, blit=False, repeat=False)
# This is supposed to remedy the blurry axis ticks/labels.
plt.rcParams['savefig.facecolor'] = 'white'
plot(C[-1])
plt.show()
The final frame looks like this:
Save the animation...
HTML(X_anim.to_html5_video())
Jump to: ↑↑ Example 1 | ↓ Plot | ↑ Example 2 | ↓ Example 4
Example 3. Let's go through the steps of Example 2, but instead of counting all intervals of the form
First we generate the data using the 'prime_start'
option in our intervals
function.
N = int(np.exp(17))
HH = [64, 68, 72, 76, 80]
C = list(range(N - 10**4,N + 10**4 + 1, 10**2))
PSEXP17 = {}
for H in HH:
PSEXP17[H] = pii.intervals(C, H, 'prime_start')
Let's centre the intervals around nest
function.
PSEXP17NEST = {}
for H in HH:
PSEXP17NEST[H] = pii.nest(PSEXP17[H])
pii.analyze(PSEXP17NEST[H])
Let's have a look at the data in a table.
PSEXP17_76_NESTtable = pii.display(PSEXP17NEST[76])
PSEXP17_76_NESTtable
pii.dfi.export(PSEXP17_76_NESTtable.tail(5), 'PSEXP17_76_NESTtable.png')
Although our predictions have only been worked out for the case of overlapping intervals, and the secondary term in the case of disjoint/left-endpoint-prime intervals might well be a bit different, we can nevertheless compare the data to these "predictions"...
pii.compare(PSEXP17NEST[76])
PSEXP17_76_NESTcompare = pii.display(PSEXP17NEST[76], comparisons='absolute').tail(5)
pii.dfi.export(PSEXP17_76_NESTcompare, 'PSEXP17_76_NESTcompare_tail.png')
...and see which not-really-a-prediction fares best...
pii.winners(PSEXP17NEST[76])
PSEXP17_76_NESTwinners = pii.display(PSEXP17NEST[76], winners='show')
pii.dfi.export(PSEXP17_76_NESTwinners, 'PSEXP17_76_NESTwinners_tail10.png')
And now we can grok everything with an animation... Actually, these not-necessarily-predictions look half-decent, given that there are only about
# HH = [64, 68, 72, 76, 80]
X = PSEXP17NEST[HH[3]]
interval_type = X['header']['interval_type']
A = X['header']['lower_bound']
H = X['header']['interval_length']
C = list(X['distribution'].keys())
plt.rcParams.update({'font.size': 22})
fig, ax = plt.subplots(figsize=(22, 11))
fig.suptitle('Primes in intervals')
hor_axis = list(X['distribution'][C[-1]].keys())
y_min, y_max = 0, 0
for c in C:
for m in X['distribution'][c].keys():
if y_max < X['distribution'][c][m]:
y_max = X['distribution'][c][m]
def plot(c):
ax.clear()
mu = X['statistics'][c]['mean']
sigma = X['statistics'][c]['var']
med = X['statistics'][c]['med']
if med == int(med):
med = int(med)
modes = X['statistics'][c]['mode']
# Bounds for the plot, and horizontal axis tick marks.
ax.set(xlim=(hor_axis[0]-0.5, hor_axis[-1]+0.5), ylim=(0,np.ceil(100*y_max)/100 ))
# The data and histogram
ver_axis = list(X['distribution'][c].values())
ax.bar(hor_axis, ver_axis, color='#e0249a', zorder=2.5, alpha=0.3, label=r'$\mathrm{Prob}(X = m)$')
ax.plot(hor_axis, ver_axis, 'o', color='red', zorder=2.5)
# Predictions for comparison
A = c[0]
B = c[1]
N = (A + B)//2
exponent= str(int(np.log(N)) + 1)
M = N - A
k = M//10**2
PI = sum(X['nested_interval_data'][c].values())
p = 1/(np.log(N) - 1)
p_alt = 1/(np.log(N))
x = np.linspace(hor_axis[0],hor_axis[-1],100)
ax.plot(x, pii.binom_pmf(H,x,p), '--', color='orange', zorder=3.5, label=r'$\mathrm{Binom}(H,\lambda/H)$')
ax.plot(x, pii.binom_pmf(H,x,p_alt), '--', color='yellow', zorder=3.5, label=r'$\mathrm{Binom}(H,\lambda^*/H)$')
ax.plot(x, pii.frei(H,x,H*p), '--', color='green', zorder=3.5, label=r'$\mathrm{F}(H,m,\lambda)$')
ax.plot(x, pii.frei_alt(H,x,H*p_alt), '--', color='blue', zorder=3.5, label=r'$\mathrm{F^*}(H,m,\lambda^*)$')
# Overlay information
ax.text(0.25,0.90,r'NB: $F$ and $F^*$ might not be applicable' + '\n' + 'in this case, without modification.', bbox=dict(facecolor='white', edgecolor='white', alpha=0.5), transform=ax.transAxes)
if B != C[-1][1]:
ax.text(0.75,0.15,fr'$X = \pi(p + H) - \pi(p)$' + '\n\n'
+ fr'$N - M < p \leq N + M$, $p$ prime' + '\n\n'
+ fr'$\pi(N + M) - \pi(N - M) = {PI}$'+ '\n\n'
+ fr'$H = {H}$, '
+ r'$N = [e^{17}]$, '
+ fr'$M = 10^2k$, $k = {k}$' + '\n\n'
+ fr'$\lambda = H/(\log N - 1) = {H*p:.5f}$' + '\n\n'
+ fr'$\lambda^* = H/\log N = {H*p_alt:.5f}$' + '\n\n'
+ r'$\mathbb{E}[X] = $' + f'{mu:.5f}' + '\n\n'
+ r'$\mathrm{Var}(X) = $' + f'{sigma:.5f}' + '\n\n'
+ fr'median : ${med}$' + '\n\n'
+ fr'mode(s): ${modes}$', bbox=dict(facecolor='white', edgecolor='white', alpha=0.5), transform=ax.transAxes)
if B == C[-1][1]:
ax.text(0.75,0.15,fr'$X = \pi(p + H) - \pi(p)$' + '\n\n'
+ fr'$N - M < p \leq N + M$, $p$ prime' + '\n\n'
+ fr'$\pi(N + M) - \pi(N - M) = {PI}$'+ '\n\n'
+ fr'$H = {H}$, '
+ r'$N = [e^{17}]$, '
+ fr'$M = 10^4$' + '\n\n'
+ fr'$\lambda = H/(\log N - 1) = {H*p:.5f}$' + '\n\n'
+ fr'$\lambda^* = H/\log N = {H*p_alt:.5f}$' + '\n\n'
+ r'$\mathbb{E}[X] = $' + f'{mu:.5f}' + '\n\n'
+ r'$\mathrm{Var}(X) = $' + f'{sigma:.5f}' + '\n\n'
+ fr'median : ${med}$' + '\n\n'
+ fr'mode(s): ${modes}$', bbox=dict(facecolor='white', edgecolor='white', alpha=0.5), transform=ax.transAxes)
# Formating/labeling
ax.set_xticks(hor_axis)
ax.set_xlabel(r'$m$ (number of primes in an interval)')
ax.set_ylabel('prop\'n of intervals with' + r' $m$ ' + 'primes')
ax.legend(loc=2, ncol=1, framealpha=0.5)
# A grid is helpful, but we want it underneath everything else.
ax.grid(True,zorder=0,alpha=0.7)
# Generate the animation
X_anim = animation.FuncAnimation(fig, plot, frames=C, interval=100, blit=False, repeat=False)
# This is supposed to remedy the blurry axis ticks/labels.
plt.rcParams['savefig.facecolor'] = 'white'
plot(C[-1])
plt.show()
HTML(X_anim.to_html5_video())
Jump to: ↑↑ Example 1 | ↑↑ Example 2 | | ↑ Example 3
Example 4. We use
Thus, the average density of primes up to
(Indeed, Gauss's observation from his numerical data was that the density of primes around
and so
In fact, the details leading to our prediction
Notwithstanding, we can still play around with
Again, letting this be
What we should really like to do is, instead of fixing