Primes and the Zeta Function

Math 242 Modern Computational Mathematics

The Riemann Zeta Function

The Riemann zeta function is one of the most important functions in number theory, with deep connections to π — in fact, deep connections the prime counting function π(x) and to the circle constant π=3.14159... . The zeta function is defined:

ζ(s)=(∑_(n=1)^∞)(1/(n^s))

Note that this function has the form of a p-series, which you may remember from Calculus II. Although the series above only converges for s>1, the zeta function can be extended to the complex plane via analytic continuation, resulting in the Riemann zeta function.

Computing values of ζ(s)

Let's start with ζ(2). That is, we want to compute (1/(1^2))+(1/(2^2))+(1/(3^2))+(1/(4^2))+….  Computing this sum is known as the Basel Problem, first posed in 1650 and solved by Euler in 1734.

The function zeta[s] below approximates ζ(s) by adding up the first one million terms of the sum . To do this quickly, we’ll use the N (“numeric”) function to convert each fraction to a decimal with 40 digits of precision.

zeta[s_]:=Sum[N[n^(-s),40],{n,1,1000000}]

Try it out, approximating ζ(2):

zeta[2]

Exercise 1

Find an exact value for the number ζ(2). Here is one approach: create a new input cell and type == to get the Wolfram Alpha input prompt. Enter the fist few digits of  ζ(2) and see what responses Wolfram Alpha gives. What number do you think is equal to ζ(2)?

Values in the Complex Plane

The function ζ(s) can be extended to the entire complex plane by the process of analytic continuation. This means that there is another function defined on the complex plane, that agrees with (∑_(n=1)^∞)(1/(n^s)) for s>1, and that is complex differentiable in a neighborhood of every point in the complex plane (except s=1).

In Mathematica, the Riemann zeta function is implemented as Zeta[s], where s can be any complex number.

The Riemann zeta function has many interesting values. For example, what is ζ(0)? Find out:

Zeta[0]

Exercise 2

What are the values of ζ(s) when s is a negative integer? Do you notice any patterns? If you find a negative integer s such that ζ(s)=0, then you have found a “trivial” zero of the Riemann zeta function.

Visualizing ζ(s)

It is tough to visualize graphs of complex-valued functions. Since the domain and range each have two real dimensions, plotting the graph of a complex-valued function would require four dimensions! Since we don’t have four spatial dimensions, we’ll have to do something else.

Domain Coloring

One common approach for visualizing a function f:ℂ→ℂ is to color each point z of the complex plane according to the value of f(z). For example, if f(z)=r (e^(i θ)), we could color z such that θ determines the hue of the color and r determines the brightness of the color.

The next plot shows the complex plane colored according to this scheme. First, we define a “paint” function, and then we produce the plot.

paint[z_]:=Module[{color, shade},
color=Hue[Rescale[Arg[-z],{-Pi,Pi}]];
shade=Exp[-Abs[z]]/1.3;
Darker[color,shade]
]

ParametricPlot[{x,y},{x,-5,5},{y,-5,5},ColorFunction->Function[{x,y},paint[x+y I]],ColorFunctionScaling->False,PlotPoints->{100,100},PlotRangePadding->0,ImageSize->250,Axes->False,FrameLabel->{"real","imaginary"}]

Note that in this plot, the positive real numbers are red (■) and negative real numbers are cyan (■). Numbers on the positive imaginary axis are green (■), and numbers on the negative imaginary axis are purple (■). Darker colors mean that the number is closer to zero (that is, smaller in absolute value). Points very close to the origin are almost black.

Domain coloring the Riemann zeta function

Now we will color the complex plane by the values of the Riemann zeta function.

ParametricPlot[{x,y},{x,-20,20},{y,-30,30},ColorFunction->Function[{x,y},paint[Zeta[x+y I]]],ColorFunctionScaling->False,PlotPoints->{200,300},PlotRangePadding->0,ImageSize->300,Axes->False,FrameLabel->{"real","imaginary"}] // Quiet

From the plot, we can see the trivial zeros on the negative real axis. We can also see the “pole” of the function, where the function blows up to infinity, at (1,0). These features are easier to see if we zoom in.

In the following plot, observe the small black regions at negative even integers. These are the “trivial” zeros of the Riemann zeta function.

ParametricPlot[{x,y},{x,-24,4},{y,-4,4},ColorFunction->Function[{x,y},paint[Zeta[x+y I]]],ColorFunctionScaling->False,PlotPoints->{280,80},PlotRangePadding->0,ImageSize->500,Axes->False,FrameLabel->{"real","imaginary"}] // Quiet

Here is a close-up plot of the pole at (1,0). There is no black dot here, because the values of the function get huge rather than going to zero. Hence, the point (1,0) is a pole, not a zero.

ParametricPlot[{x,y},{x,0.5,1.5},{y,-0.5,0.5},ColorFunction->Function[{x,y},paint[Zeta[x+y I]]],ColorFunctionScaling->False,PlotPoints->{100,100},PlotRangePadding->0,ImageSize->300,Axes->False,FrameLabel->{"real","imaginary"}] // Quiet

The Riemann hypothesis says that the non-trivial zeros of ζ(s) all have real part (1/2). This is considered to be one of the greatest unsolved problems in mathematics. More than 1 trillion nontrivial zeros of ζ(s) have been computed numerically, and they all have real part (1/2). The hypothesis appears to be true, but no one has found a proof.

In our domain coloring, we can see some nontrivial zeros on the line Re(s)=(1/2). Again, zoom in:

ParametricPlot[{x,y},{x,-4,6},{y,-2,28},ColorFunction->Function[{x,y},paint[Zeta[x+y I]]],ColorFunctionScaling->False,PlotPoints->{100,300},PlotRangePadding->0,ImageSize->200,Axes->False,FrameLabel->{"real","imaginary"}] // Quiet

Exercise 3

Modify the code above to produce a domain coloring of the sine function on the complex plane. You should type the function as Sin[x + y I]. Where are the zeros of the sine function? Confirm that the domain coloring agrees with what you know about the sine function on the real line.

Nontrivial Zeros of ζ(s)

Computing the nontrivial zeros of ζ(s) is challenging. (Shall we say it’s “nontrivial”?) Fortunately, Mathematica provides a built-in function, ZetaZero[k], that gives the (k^th) nontrivial zero of the Riemann zeta function. For example:

N[ZetaZero[1]]

As expected, the real part of this zero is 0.5. The imaginary part is about 14.1347. Does this agree with the location of a zero in the domain coloring plot above?

We can also ask Mathematica for a bunch of nontrivial zeros:

ZetaZero /@Range[10] //N

Do these zeros agree with what you observe in the domain coloring plot?

For one further visualization, we can plot the real and imaginary parts of the Riemann Zeta function ζ(s) along the line Re(s)=(1/2).

Plot[{Re[Zeta[1/2+I*t]],Im[Zeta[1/2+I*t]]},{t,0,50},PlotLegends->{"real","imaginary"},AspectRatio->1/3]

The zeros of ζ(s) occur where its real and imaginary parts are simultaneously equal to zero. Confirm that the location of zeros given by the plot above agree with the values returned by ZetaZero.

Connection to Primes

One connection between the Riemann zeta function and prime numbers is given by Euler’s product formula:

ζ(s)=(∑_(n=1)^∞)(1/(n^s))=(∏_(p prime))(1/(1-(p^(-s))))

Is this a surprising formula?

Exercise 4

Compute some approximations (“partial products”) of the infinite product above using the first k terms. (That is, the product over the first k primes). You decide what values of k to use, but try several different numbers. Do your approximations agree with ζ(s)? Try several values of s.

An approximation to the prime counting function

Last time, we encountered the prime counting function π(x), which counts the number of primes less than or equal to a real number x. We will now see one way in which the Riemann zeta function ζ(x) is connected to the prime counting function π(x).

First we define a function R(x), which involves the Riemann zeta function.

R(x)=1+(∑_(k=1)^∞)((((ln x))^k)/(k k! ζ(k+1)))

It turns out that R(x) is a very good approximation to the prime-counting function. To see this, we would like to plot R(x) and π(x). Since R(x) is an infinite sum, we will instead use a partial sum with the first m terms; the next line implements this:

r[x_,m_]:=1+Sum[Log[x]^k/(k*k!*Zeta[k+1]),{k,1,m}]

Now we can plot the prime counting function π(x) and our approximation consisting of the first 20 terms of R(x):

n=100;
countPlot=Plot[ PrimePi[x], {x,0,n} ];
rPlot=Plot[ r[x,20],{x,1,n},PlotStyle->Red];
Show[countPlot,rPlot]

Are you surprised at how closely R(x) approximates π(x)? Note that R(x) approximates π(x) much more closely that the functions we saw last time! Re-draw the plot with a larger n and notice how R(x) and π(x) become almost indistinguishable as you zoom out!

A very cool approximation

The second Chebyshev function ψ(x) is a variant on the prime counting function. It counts not only primes, but prime powers. The function is:

ψ(x)=(∑_((p^k)≤ x))ln(p)=(∑_(p≤x))⌊(Subscript[log, p])(x)⌋ln(p)

The first sum above is over all prime powers not exceeding x; the second sum is over all primes not exceeding x. We will define the function for Mathematica and make a plot:

ψ[x_]:=Sum[ If[PrimeQ[p],Floor[Log[x]/Log[p]]Log[p],0],{p,2,x}];
n=50;
psiPlot=Plot[ψ[x],{x,0,n},PlotStyle->Orange]

Notice that the second Chebyshev function is not continuous. However, it can be approximated by a continuous function that involves the nontrivial zeros of the Riemann zeta function! The approximation function is:

(Subscript[ψ, 0])(x)=x-ln(2π)-(∑_ρ)((x^ρ)/ρ)-(1/2)ln(1-(x^(-2)))

Here, the sum is over all nontrivial zeros ρ of the Riemann zeta function. Since we can’t sum over infinitely many zeros, we will define (Subscript[ψ, 0]) in Mathematica using a finite sum, with a parameter m that determines how many zeros we use. Note that we are using ZetaZero to obtain values of the zeros.

ψ0[x_,m_]:= x-Sum[2*Re[(x^ZetaZero[k])/ZetaZero[k]],{k,1,m}]-Log[2Pi]-Log[1-x^(-2)]/2

Here is a plot, with (Subscript[ψ, 0]) evaluated using 20 zeros of the Riemann zeta function:

Plot[ψ0[x,20],{x,0,50},PlotStyle->Purple]

The function (Subscript[ψ, 0]) converges remarkably to ψ as we increase the number of terms in the sum. Here is an interactive window with a slider that controls the number of terms in the sum. (Unfortunately the response time when moving the slider might be slow because plotting our function (Subscript[ψ, 0]) is computationally intensive!)

Manipulate[ Show[psiPlot, Plot[ψ0[x,m],{x,0,50},PlotStyle->Purple]], {m,0,60,1}]

Move the m slider to the right and watch the approximation (in purple) get closer to the second Chebyshev function ψ (in orange). Incredible! As we include more and more zeros of the Riemann zeta function, the continuous function (Subscript[ψ, 0]) converges to the prime-counting function variant ψ!

Consequences of the Riemann Hypothesis

Mathematicians have produced hundreds of propositions that depend on the Riemann hypothesis. If the Riemann hypothesis is true, then all of these propositions are true as well. These propositions have to do with the error term in the prime number theorem, gaps between primes, counting primes mod k, and much more.

For example, if the Riemann hypothesis is true, then π(x) and li(x) satisfy:

|π(x)-li(x)|<(1/(8π))(Sqrt[x])ln(x),    for all x≥ 2657.

Wikipedia has a list of some consequences of the Riemann hypothesis here.

One intriguing result

Let’s turn again to the prime-counting function π(x), which gives the number of primes less than or equal to x. We also observed that π(x) is approximated quite well by the logarithmic integral function Li(x). Here is another plot that shows this:

Plot[{PrimePi[x],LogIntegral[x]},{x,1,100},PlotLegends->{"π(x)", "Li(x)"}]

From the graph above we see that π(x)<Li(x) when 0<x<100. In fact, it is known that π(x)<Li(x) for x up to (10^23). However, in 1914, Littlewood proved that the difference π(x)-Li(x) changes sign infinitely many times as x increases!

Littlewood’s proof involves two cases: he proved that the result is true assuming that the Riemann hypothesis is true, and he also proved that it is true assuming that the Riemann hypothesis is false! Thus, Littlewood’s theorem is true, regardless of the whether the Riemann hypothesis is true or false.

Interestingly, Littlewood’s proof does not provide a specific number x such that π(x) > Li(x). In 1933, Skewes proved that if the Riemann hypothesis is true, there exists a number x such that π(x)>Li(x) with

x<(10^(10^(10^34))).

The number (10^(10^(10^34)))absolutely dwarfs any other number we have considered so far in this course!

In 1955, Skewes proved that, without assuming the Riemann hypothesis, there exists an x such that that π(x)>Li(x) with

x<(10^(10^(10^964))).

More recent work has shown that π(x)>Li(x) for some x less than 1.39717×(10^316). Still, there is no explicit value of x for which it is known that π(x)>Li(x), despite the existence of infinitely many such values!

Exercise 5

Considering the content of this notebook and the prime counting notebook from last time, what have you learned about continuous approximations of the prime counting function? What do you find most interesting about this topic? What questions would you like to investigate further?

When you have finished these exercises, submit your notebook to the Riemann Zeta Assignment on Moodle.