Kanter’s Zeta Function – Part 2: an exploration with Python

Continuing from Part 1.

(note to the reader: this was posted without being proofread. I will proofread/check my work later because I am too tired right now. I might have also forgotten to include a few points) 

Who want’s to do some math?

Let’s pick up right where we left off. I’m not going to go over anything from Part 1, because honestly, for the sake of digestibility, this should not have even been broken up into 2 parts, and I will probably just repost it as a single, combined post later anyway.

Ok. We have our gamma, psi, and zeta functions from part 1. We’re going to want to graph some of that data with python, but in order to do that, we ought to modify a lot of that code from Part 1 in order to make the whole process go faster/smoother. First, we’ll want to quickly generate a file with all of the gamma values which we can reference to quickly get the psi values (this way we can cut out many steps of recursion).

def gfilemaker(n):
    glist = [0]
    gglist = str(glist)
    gfile = open('gammafile.txt','w')
    gfile.write(gglist)
    def gammaloader(s,k):
        d = len(glist)
        if s < d:
            return glist[s][k-1]
        elif k==1:
            return 1
        elif k==s:
            return 1
        else:
            y = 0
            for x in range(1,min(s-k+1,k+1)):
                y+=gammaloader(s-k,x)
            return y
    for a in range(1,n+1):
        alist = []
        for k in range(1,a+1):
            alist.append(gammaloader(a,k))
        glist.append(alist)
        aglist = str(alist)
        gfile.write('\n')
        gfile.write(aglist)
    gfile.close()
    return glist

gammalist = gfilemaker(100)

notice that the function gammaloader is basically our gamma function from part one, but modified to cut down on the amount of recursion we have to go through.

Now let’s make a similar function to quickly generate a file containing all of our zeta values. I won’t bother making a file with the psi values, because the psi values will be so easy to get (since psi(n) is just the sum of the list in the n+1-th row of gammafile.txt).

def zetalister(n):
    gammafile = open('gammafile.txt','r')
    lines = gammafile.readlines()
    def gline(a):
        gline=lines[a].replace('[','').replace(']','').replace(',','')
        gline = gline.split()
        for x in range(len(gline)):
            gline[x]=int(gline[x])
        return gline
    def quickpsi(num):
        guesses=primegenerator(num**0.5)
        def quickprimer(trial):
            primedict = {}
            def factor(p, s):
                if not(p in primedict):
                    primedict[p]=1
                else:
                    primedict[p]+=1
            for p in guesses:
                while trial % p == 0:
                    factor(p, trial)
                    trial = int(trial/p)
                if trial == 1:
                    return primedict
            if trial != 1:
                primedict[trial] = 1
            return primedict
        psifactlist=[0]
        for z in range(1,num+1):
            b=1
            for a in quickprimer(z):
                c = sum(gline(quickprimer(z)[a])) # here is psi
                b*=c # here is our zeta function
            psifactlist.append(b)
        return psifactlist
    zetafile = open('zetafile.txt','w')
    zetalist = quickpsi(n)
    zetatext = str(zetalist)
    gammafile.close()
    zetafile.write(zetatext)
    zetafile.close()
    return zetalist

zetalist = zetalister(1000000)

notice that quickpsi calls the primegenerator function from part 1. notice that quickprimer is essentially our primefactorizer function from part 1.  notice that our psi function is basically just expressed as c = sum(gline(quickprimer(z)[a])), and that our zeta function shows up in the line just below our psi function, ie, b*=c.

Now we have a file with the first million zeta values. I plotted out the data in multiple ways using matplotlib. I will spare you the details, since it was probably fairly routine, and not unique to this particular study. (If you really want, dear reader, I’m willing to share the code, I just assume you’d rather figure it out on your own). Take a look at the results below:

zetalinear
zeta(x) for x up to one million (x-axis is linear scale)

Um. yeah. let’s look at that with a logarithmic x-axis.

zetalog
zeta(x) for x up to one million (x-axis is logarithmic scale)

okay, so zeta(x) is kind of weird to look at. We see a much thicker blue closer to the bottom, because that’s where the majority of data points are. I think the logarithmic scale on the x-axis makes it a bit easier to take in the data. Okay, now let’s take a look at the arithmetic means of the partial sums of zeta(x), which we call sigma(x), that is:

def sigma(x):
    b=0
    for a in range(1,x+1):
        b+=zeta(a)
    return b/float(x)

I didn’t actually write the code like this. I used the zetafile.txt which I generated. I just wanted it to be easier for you to read.

REMEMBER: Our main goal is to determine whether or not sigma(x) is Cesàro Summable. In other words, we want to know whether or not sigma(x) approaches some finite number y as x approaches infinity. Alright, let’s take a look at sigma(x) plotted out with linear x-axis and logarithmic x-axis.

sigmalinear
sigma(x) for x up to one million with linear x-axis
sigmalog
sigma(x) for x up to one million with logarithmic x-axis

Take a look at the graph with logarithmic x-axis. Notice how the data points seem to show up in clusters. Now count the number of data points in each of the first few clusters. 4, 8, 16…notice the pattern? Isn’t it obvious why we see clusters in increasing powers of 2? It’s because zeta(2n) is going to be substantially higher than zeta(x) for any x less than 2n. At least, this is the case for all x up to one million. This is because 2 is the smallest prime, so 2n will be the smallest number to “experience” psi(n). Consequentially, zeta(2n) pushes sigma higher than the other numbers around it do.

Here’s another observation: when we graph sigma with the logarithmic x-axis, the graph resembles something that looks “less than” a linear curve on a graph with a linear x-axis. This would lead us to believe that sigma is possibly “less than” logarithmic. Maybe it is. That doesn’t really help us much though, because even a logarithmic function is unbounded, so sigma still might not have a limit. The problem only becomes more pronounced when we chop the first 999 data points off the graph and zoom in accordingly:

sigmalog1000
sigma(x) for 1000 ≤ x ≤ 1000000 with logarithmic x-axis

Is it just me or is it starting to look almost linear toward the right end of that graph? Crap. No doubt this is a slow-moving function, but it looks like it’s getting harder to prove convergence (if it indeed converges). There’s another issue too. I plotted out the psi(x) for x up to 100. Take a look:

psilinear
psi(x) for x up to 100 with linear y-axis

Is that approximately exponential? Sure looks like it. Let’s take another look, this time with a logarithmic y-axis.

psilog
psi(x) for x up to 100 with logarithmic y-axis

Well this is weird. It kind of looks like it might be exponential, but when we look at it with a logarithmic y-axis, we would expect to see something a bit more linear. It’s close, but not quite. Seems maybe a bit “less than” that. Maybe if we had more data-points we would be able to see something more clearly. This is getting kind of difficult, but here’s the worst part. I don’t think we have enough data in our list of zeta values to see the full “long-term” behavior of the function. I’d be much more comfortable with a few more dozen orders of magnitude of data. I mean, I’d like to get to at least 280. But really, I’d like to get to x80 for some high enough prime x, because we need to know what happens when the prime factorization contains multiple primes, and zeta is the product of a bunch of psi values of sufficiently high exponents. But do we really? One really important step would be to figure out whether or not psi actually is approximately exponential, and if so, then we really want to know the base of the exponent. Because that could probably tell us about how zeta behaves in the long run, and therefore how sigma behaves as well. Here’s yet one more issue: are we going to have to relate this back to the prime number theorem? I don’t think so, because as we observed earlier (with the clusters of powers of 2), powers of small primes are going to be more important in driving sigma since they are easier to come by. And this difference in “importance” only becomes more pronounced as the exponents increase. In fact, if I wasn’t so damn sleepy right now, I might be up for some kind of make-shift proof of something using algebra. But I am very sleepy, so any kind of rigorous examination of this problem will have to wait until next time. I never expected to prove anything with all of this graphing, I just wanted to point myself in the right direction, and I think I have. For now let me leave you with this beautiful gif of our gamma values plotted in 3D, which i created using matplotlib, mplot3d, and ffmpeg (sorry for the bad rendering on the top part of the background of the graph. not sure what that’s all about).

animation.gif
gamma(k,n) for n up to 100. So pretty.

Here, I pause. If you wish to walk no farther with me, reader, I cannot blame you. It is no easy road.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s