# The Lumber Room

"Consign them to dust and damp by way of preserving them"

## How does Tupper’s self-referential formula work?

[I write this post with a certain degree of embarrassment, because in the end it turns out (1) to be more simple than I anticipated, and (2) already done before, as I could have found if I had internet access when I did this. :-)]

The so-called “Tupper’s self-referential formula” is the following, due to Jeff Tupper.

Graph the set of all points ${(x,y)}$ such that

$\displaystyle \frac12 < \left\lfloor \mathrm{mod} \left( \left\lfloor{\frac{y}{17}}\right\rfloor 2^{-17\lfloor x \rfloor - \mathrm{mod}(\lfloor y \rfloor, 17)}, 2 \right) \right\rfloor$

in the region

$\displaystyle 0 < x < 106$

$\displaystyle N < y < N+17$

where N is the following 544-digit integer:
48584506361897134235820959624942020445814005879832445494830930850619
34704708809928450644769865524364849997247024915119110411605739177407
85691975432657185544205721044573588368182982375413963433822519945219
16512843483329051311931999535024137587652392648746133949068701305622
95813219481113685339535565290850023875092856892694555974281546386510
73004910672305893358605254409666435126534936364395712556569593681518
43348576052669401612512669514215505395545191537854575257565907405401
57929001765967965480064427829131488548259914721248506352686630476300

The result is the following graph:

Figure 1: The graph of the formula, in some obscure region, is a picture of the formula itself.

Whoa. How does this work?

At first sight this is rather too incredible for words.

But after a few moments we can begin to guess what is going on, and see that—while clever—this is perhaps not so extraordinary after all. So let us calmly try to reverse-engineer this feat.

The first thing we notice is the size of N. As the “formula” is small and innocuous (just a few exponents, remainders and floors, no “unnatural” functions), and N is so disconcertingly huge, it is reasonable to guess that all the actual information that produces the graph is contained in N itself. This would mean that the formula is like a bare-bones “program”, and N is the “input” that somehow encodes the image that is the graph.

To understand the encoding, we must turn to the formula.

First, using the fact that ${\left\lfloor \frac{y}{17} \right\rfloor = \left\lfloor \frac{\lfloor y \rfloor}{17} \right\rfloor}$, we see that the formula (relation, more properly) depends on ${x}$ and ${y}$ only through ${\lfloor{x}\rfloor}$ and ${\lfloor{y}\rfloor}$. So the graph in each 1×1 square (with vertices having integer coordinates) is the same as at its bottom-left endpoint.

A part of Figure 1 enlarged, with grid turned on

(Just a sanity check at this point: this observation means that Figure 1 is essentially a 106×17 bitmap. 106×17=1802, and ${N}$ has about ${544\lg 10 \approx 1807}$ bits, which is roughly as many bits as the image. So we have another reason for our suspicion that N encodes the image.)

Accordingly, we can restrict our attention to integer values for ${x}$ and ${y}$. Further, ${\frac12 < \lfloor \alpha \rfloor}$ is the same as ${1 \le \alpha}$ (I wonder why the obfuscation was there?), so we can simplify the formula:

$\displaystyle 1 \le {\mathrm{mod}} \left( \left\lfloor{\frac{y}{17}}\right\rfloor 2^{-17x - \mathrm{mod}(y, 17)}, 2 \right)$

We also notice a dependence on the value of y mod 17, so let’s write ${y = 17q + r}$, where the remainder ${r}$ satisfies ${0 \le r < 17}$. So our graph is the set of all points ${(x, 17q+r)}$ for which

$\displaystyle 1 \le \mathrm{mod} \left(q 2^{-17x - r}, 2 \right) = \mathrm{mod} \left(\frac{q}{2^{17x+r}}, 2 \right)$

which is the same as saying that

$\displaystyle \left\lfloor \frac{q}{2^{17x+r}} \right\rfloor$

is an odd number.

Note that the region in which the plotting is supposed to be done has a range of only 17 integers for ${y}$, so ${q = \left\lfloor{\frac{y}{17}}\right\rfloor}$ remains the same for all ${y}$ (except possibly off by 1) while ${r}$ ranges from ${0}$ to ${16}$. For a fixed value of ${x}$, then, different values of ${y}$ correspond to different ${r}$.

In case you haven’t noticed yet,

$\displaystyle \left\lfloor \frac{q}{2^{17x+r}} \right\rfloor$

being odd is equivalent to the (17x+r)th bit of ${q}$ (counting from the rightmost bit as the 0th) being 1. So in the graph, the pixel at ${(x,r)}$ is 1 iff the bit at position (17x+r) in ${q}$ is 1: ${q}$ is merely a list of bits of the image! It’s a rather straightforward encoding after all: it just reads off the bits of the image, reading each column upwards, and going through the columns left-to-right.

In hindsight, we can see that this is in fact the natural encoding. If you were given a bitmap image ‘q’ got by concatenating each column (or row), and wanted to find a mathematical relation which for (x,r) was 1 iff the image had a bit at that point, this is more or less the relation you would come up with (for some orientation of the axes). Tupper’s further trick here is in folding the value of q into the value of y itself as y=17q+r.

## The “mistake”

Actually, the value of N that I included above is one I found myself. Every source I’ve seen (examples: MathWorld, Wikipedia, “Implementation” webpage (doesn’t work), blog with code, etc., etc.) instead mentions a different constant for N, namely the 543-digit integer (call it N’)
96093937991895888497167296212785275471500433966012930665150551927170
28023952664246896428421743507181212671537827706233559932372808741443
07891325963941337723487857735749823926629715517173716995165232890538
22161240323885586618401323558513604882869333790249145422928866708109
61844960917051834540678277315517054053816273809676025656250169814820
83418783163849115590225610003652351370343874461848378737238198224849
86346503315941005497470059313833922649724946175154572836670236974546
1014655997933798537483143786841806593422227898388722980000748404719.

Graphing the function on the range ${N' < y < N' + 17}$ gives the following figure:

What Tupper's formula as described in every source actually graphs

It is upside down. This is of course an entirely trivial goofup, probably based on the mathematical convention (the y-axis goes upwards) differing from computers’ screen convention (the y-axis goes downwards), but there’s something slightly comic about spending all this effort devising a very clever trick, but failing to ensure it’s not upside down. (‘The scene in Not the Nine O’clock News in which an elderly, exhausted monk unbent himself after years of illuminating the first page of the Bible, only to see that he had written, gloriously, “Benesis”’.) But that’s not a big deal, mistakes happen. What I find strange is that hundreds of people have been quoting and referencing this, without ever bothering to check it for themselves, and those who did bother and presumably noticed something amiss (e.g. here, Reddit, Hacker News,…) merely changed their code to “make it work” (a la voodoo programming) rather than confidently declaring that the constant was the wrong one, or at least specifying that the y-axis needs to go downwards. (Even the upside-down constant isn’t always consistently described: Stan Wagon’s nice list of favourite puzzles, mentioned as a source on MathWorld, calls it a 541-digit integer but prints all 543 digits, while the otherwise excellent book Experimental Mathematics in Action (by David H. Bailey, Jonathan M. Borwein, Neil J. Calkin, Roland Girgensohn, D. Russell Luke, and Victor H. Moll) calls it a 541-digit integer and actually cuts off the last two digits, which results in an image that looks like garbage.)

It’s remarkable that no one would check something so easy to check, even in these days when nearly any computer user has access to tools that make it easy. Maybe they are using the wrong tools? Something as simple as this will work:

#!/usr/bin/env python
N = 96093937991895888497# Truncated, but you can paste the full constant here
H = 17
W = 106
import sys
for y in range(N+H-1, N-1, -1):
for x in range(W):
if 0.5 < ((y//H) // (2**(H*x + y%H))) % 2: sys.stdout.write('*')
else: sys.stdout.write(' ')
sys.stdout.write('\n')


producing

*** *                                                               ***  *** *                 ***
*   *                                                               *      * *                   *
*  *                                                                *  * * *  *                  *     ***
*  *      *                                                         *  * * *  *                  *       *
*  *     *                                                          * *  * *  *                  *      *
* *      *                                                          * *  * *   *                 *     *
* * ****                                                       **** * ** * *   * ***   **  * * * * *    **
* *    *                                                          * *      *   * *  * *  * * * * *  *
* *   *                                                          *  * **** *   * *  * *  * * * * *   * ***
* *  *     *       * *** *** *                   *** ***        *   *      *   * ***   **   * ** *  *
* * *  *   *      *  *     * *                   *     *       *  * *   *  *   * *               * *   ***
* *  **   *       *  *   * *  *                  *     *        **  *  *   *   * *               *      *
*  *      *   * *    *  *  *  * *** *** * * *    * * * *  * *       * * *  *  *                  *      *
*  *      *   * *    * * * *  * * * * * * * *    *  *  *  * *       * * *  *  *                  *      *
*  *      *  *  *    * * * *  * *** ***  **** ** * * * * *  * **    *      *  *                  *      **
*   *      * *  *    *     * *  *                *     * *  *       *      * *                   *
*   *      * ** *    *     * *  *                *     * ** *                *                   *


which (if you squint) you can see is the formula upside-down. (The appendix below contains a better version that uses matplotlib and was used to generate the images in the post.)

## Author, Background

Apparently Tupper included the formula in his 2001 SIGGRAPH paper on graphing methods, merely as an example of the kind of graphs his method can handle. (And he didn’t call it self-referential.) I’m pleased to discover that Tupper is the author of GrafEq which I remember trying some ten-odd years ago. It was at that time the best graphing software in certain respects (precision, correctness, etc.), and as far as I can tell, it still is. I hope its ideas get incorporated in all graphing programs in the future. In the paper, Tupper writes:

Many students currently studying mathematics are using automated graphing tools that produce incorrect graphs for some of the equations discussed in their curricula. I have written this paper in the hope that, in the future, more students will have access to graphing tools that work correctly.

The gallery page for GrafEq contains many other ingenious exploits that use implicit relations to get beautiful graphs. The one closest to the formula here is probably Decimal Squares, but many of the others are truly mind-boggling.

## Tupperware and beyond

### More bitmaps

Now that we see that graphing Tupper’s formula is just a “program” to decode a bitmap, it follows that the formula is also “universal”: for any bitmap image (of height at most 17 pixels), there exists an integer N such that graphing Tupper’s formula on the range 0 < x < width-of-image, N < y < N+17 produces the image. All possible images are contained in the graph of Tupper’s formula. For instance, N=6064344935827571835614778444061589919313891311 gives this:

N = 114461430485773228734207468860322536020810361768206377253515727288242
0531935654859544357377819147833060031564802551634741838422783909813925261
4970555108049338384907856705947495396329029490965408180552069582726103040 gives this, a different kind of “self-reference”:

And so on. The appendix below contains a program that can read (some) .bmp files and generate corresponding N.

### Self-reference

This also means that the formula is not self-referential at all (though one may argue it’s something better), any more than a program that prints all possible strings can be called a quine. So in the spirit of actual self-reference, here is

Exercise 1 (easy): Find N such that the graph of Tupper’s formula (in the range given by N) is a picture of N, or prove that it is impossible.

Exercise 2 (hard): Find N such that the graph of Tupper’s formula (in the range given by N) is a picture of $\lfloor\sqrt{N}\rfloor$, or prove that it is impossible.

### Pixellation

It is easy to get a similar formula with higher resolution. For instance, the formula

$\displaystyle \biggl\lfloor\left\lfloor\frac{y}{61}\right\rfloor2^{-61x-(y\bmod61)}\biggr\rfloor\bmod2=1$

graphed in the region ${0 < x < 375}$ and ${N < y < N+61}$ for ${N}$ a certain 6859-digit integer, produces the following graph:

More height means more resolution. (More care would avoid the bitmap artifacts.)

### Generalisation

What we have so far is limited to images of a fixed height. So finally,
Exercise 3 (not so hard!): Find a variant of Tupper’s formula whose graph contains all W×H images, for all W and H.

## Acknowledgments

I was going to mention Mohan’s post on Rubel’s Universal Differential Equation for inspiration (and his mentions of Tupper’s formula for provocation), but on finding it again, I notice that (1) it already mentions an earlier post by him on precisely this Tupper’s formula, and (2) its style is unmatchable, anyway. :p

## Appendix

• plot-tupper.py: Plots Tupper’s formula using matplotlib.
• plot-old-full.py: Older version that prints to terminal or file, if matplotlib is not available or desired
• bmp2tupper.py: Reads a bitmap file (works with 32-bpp BMP files, not all) and generates N.

Written by S

Tue, 2011-04-12 at 13:05:20

Posted in mathematics

Tagged with , , ,

### 43 Responses

1. […] Shreevatsa: How does Tupper’s self-referential formula work? […]

Sun, 2011-06-12 at 13:25:40

2. […] does it work, and intended to write a long post about it, but I see that it has already been done here much better than I could, so I’ll only give you the main idea: the graph of the formula […]

George Plays With Maple

Sat, 2011-06-18 at 13:29:20

3. It’s only “wrong” if you assume the y-axis goes upwards, which is conventional, but not essential.

Rahul

Sun, 2011-06-19 at 16:00:03

• Hi, thanks for the comment. Yes of course that’s right, and I will not (cannot) disagree strongly.

But the orientation of the axes is such a strong convention that if a source doesn’t mention otherwise, that’s what one would have to assume. If you look at the image on Wikipedia, it even has the y-axis labelled, and that’s indisputably wrong. I would find it hard to believe that all these sources (e.g. Tupper’s paper which has the y-axis upwards for most/all other images) actually checked the graph, found it flipped, decided it was ok, and also decided that it was ok to omit mentioning this. The more reasonable explanation is that they simply didn’t realise that it was upside down relative to what they and their readers expect: in other words, wrong. :-)

S

Sun, 2011-06-19 at 16:23:48

• Actually the coordinate system for drawing pixels on screen is typically positive y is down.

Anonymous

Sun, 2011-06-19 at 19:55:40

• I know that, but IMHO it’s not very relevant. Again: it’s a strong convention in mathematics that plotting the graph of a function means a certain thing, and if a source used something eise intentionally it would mention it, etc., etc.

OK: if you can find me another example on MathWorld where plotting a function means plotting it with the y-axis going downwards, and this is not mentioned on MathWorld, I will agree with you. :-)

As an aside, I find it somewhat telling about our nature that with so much text in the post, everyone (including myself) wants to comment on the somewhat silly section that claims something is a mistake.

S

Sun, 2011-06-19 at 23:27:11

4. Hi I have seen your page and it inspired me to create truly self-referential formula.
It is here: http://jtra.cz/stuff/essays/math-self-reference/index.html

jtra

Thu, 2011-06-23 at 11:05:55

• Wow, that is brilliant! I have no words. Very clever, and please do write the article explaining it. Thanks also for the comments so far on the Reddit thread. I did not imagine that someone could actually achieve this! :-)

S

Thu, 2011-06-23 at 12:24:30

• If you want a formula with bigger constants, try http://www.peda.com/selfplot/selfplot3big.png

Anonymous

Mon, 2012-01-23 at 14:25:04

• Wow, that is certainly big; it took me a while to realise that the tiny black line near the top of the screen was the actual image! :-)

It still seems to require passing N separately, though… am I right? So it’s “(formula + N) gives (image of formula)”, so the image by itself is not sufficient to regenerate the formula. Still, impressive.

S

Mon, 2012-01-23 at 20:07:57

• N is part of the formula. Since Tupper hasn’t made his bignum GrafEq publicly available, I tried it using Maple and it seemed to work fine. The copy of the email I got included a bunch of links to files in http://www.peda.com/selfplot … which is where I got the constant.

Anonymous

Tue, 2012-01-24 at 11:10:58

5. It’s pretty hilarious that the authors of a book called “Experimental Mathematics in Action” would make an error like this.

Thank you, S, for actually thinking about it for yourself.

Bo

Thu, 2011-06-23 at 11:25:44

• Well, it actually looks like a pretty good book. I’ve read other works by some of the authors, and they’re great. But well… mistakes happen everywhere. :-)

S

Thu, 2011-06-23 at 12:21:26

6. Excellent analysis on the topic.

rpk

Thu, 2011-07-14 at 11:12:46

7. […] There’s a mathematical formula, that when graphed, can visually reproduce itself. […]

8. […] el número K, puedes obtener un dibujo diferente cada vez. Lo que quieras. Por ejemplo, como explican aquí, si K (o N, da igual cómo lo llames) fuera este […]

9. Hy, I downloaded Anaconda. Can someone please explain me how to enter that appendix? I’m not so good at programming but I really want to see how this formula works.

dario333

Fri, 2015-04-17 at 04:15:21

• Where does it create these files and does it save them automatically or do I have to do something? So I just open Python, copy the text from plot-tupper.py and open the picture? Sorry I’m being a boring noob but I only worked in QB64 and I don’t know anything about Python. Just try to explain it as you would to a baby :)

dario333

Mon, 2015-04-20 at 12:08:12

• Hmm, looks like I’ve not written it in a very user-friendly way. :-(

You can try the following:
If you know what a “command-line” (“terminal”) is, then you just type the command:
python plot-tupper.py
(from the directory/folder that contains plot-tupper.py), and (when prompted) enter the numbers 106 (the width) and 0 (for default N) respectively. Then you’ll find two files called out.png and out.svg respectively, created in the same directory.

Else, you can try opening the Anaconda IDE (I think it’s called Spyder), open the file plot-tupper.py, and find something somewhere in the menu called “Run” or “Execute” or something like that. Then you should be able to similarly enter the input and find the files created.

With the terminal / command-line method, this is what it looks like on my computer (I saved plot-tupper.py in a directory called /tmp/test — you can use any directory):

S

Mon, 2015-04-20 at 14:57:03

• Just one more question: how can you convert a picture in to N? I thought the squares would represent the binary number N, but they obviously don’t.

dario333

Thu, 2015-04-23 at 02:05:11

• To go from number to image, use plot-tupper.py.
To go from image to number, use bmp2tupper.py (it takes an image in .bmp format). That’s how I generated the N for the various images in this post; you can run it with
python image.bmp
at the command line.

By the way, how the formula works is already explained in the post; is something not clear enough?

S

Thu, 2015-04-23 at 07:55:39

• And how exactly can I create my own .bmp image? When I asked you I thought you would explain how I could do it mathematically. And no, I didn’t understand it because I’m only 15 years old and English is not my mouther tongue so I don’t understand some mathematical terms.

dario333

Thu, 2015-04-23 at 10:42:22

• Great to see your interest; good luck to you!

I’ll edit the post to add some simpler examples, and reply again here when I’m done. (Might be a few days as I expect to be without a laptop for a while.)

You can create .bmp images with an image editor — on Windows, “MS Paint” (which comes installed by default) can do this, and I used something similar on either Mac or Linux for the images in the post.

Mathematically, going from a bitmap to N is very simple — as the post says, “q is merely a list of bits of the image … reading each column upwards, and going through the columns left-to-right.” (It has 0 if the square is blank, and 1 if the square is filled.) And N = 17q.

For example, the “empty” graph (all 0s) corresponds to q = 0 and so N = 17×0 = 0, and the filled graph (all 1s) corresponds to $q = 2^{17 \times 106} - 1$ and $N = 17q$ again.

S

Thu, 2015-04-23 at 17:39:03

• I understand now how to calculate N and I succeeded in making a couple of images (it took me a while until I figured out that my calculator can’t calculate so large numbers). But when I tried to get N from a picture I made in Paint and saved as .bmp cmd wrote:
SyntaxError: Non-ASCII character ‘\x8e’ in file untitled.bmp on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details.

dario333

Tue, 2015-04-28 at 07:26:29

• Great progress! About the error, just a guess: you’re running “python untitled.bmp” instead of running “python bmp2tupper.py untitled.bmp”

S

Tue, 2015-04-28 at 08:13:29

• Ah, OK. Now it says that it can’t handle 24 bpp pictures. I noticed when saving that I only have the 24 bpp option. Do you know some other program that can save 32 bpp pics?

dario333

Tue, 2015-04-28 at 08:25:34

• I’ve modified the program to handle 24-bpp pictures too: could you give it a try: http://pastebin.com/mVD1D4fQ (not tested)

S

Tue, 2015-04-28 at 09:50:25

• Nope, it doesn’t work. Here’s the paint image and out:

dario333

Tue, 2015-04-28 at 11:13:40

• As the output says, “Height is larger than 17, so Tupper’s formula must be modified.” The height of your untitled.bmp is 610 pixels.

Try it with an image whose height is 17 pixels or less. That means a *really* small image.

Else, you can do the following too: run
python plot-tupper.py 610
and as input give it the height (1316 for your image) and N (which has over 1200 digits). Note that your terminal may have trouble inputting such a large input for N.

S

Tue, 2015-04-28 at 12:30:54

• I cropped the picture to the required height, but it created this weird crooked image with a line in front:
I think that it still has too many pixels because it seems too high-quality, but than why does it say that it’s the correct height? And how could I fix it?

dario333

Tue, 2015-04-28 at 15:21:59

• I don’t think anything’s changed: the Untitled.bmp in your new link is identical to the old one, and is still 1316 x 610.

Let’s continue this discussion over email — I’ll email you. Also try a non-blank image. (I made a poor choice of letting “0” mean the default N for Tupper’s original formula, instead of actually meaning 0.)

S

Tue, 2015-04-28 at 16:19:33

• i can actually make this alot simpler if you would like. so if you look at these images in their pixelized form, so that each coordinate is a pixel, you first have to make a binary. starting from the bottom left, going up, then the bottom of the next row and go up, and so on and so on. wherever there is a blank space, punch in a zero, whenever the coordinate is marked plug in a one. after this, you should get a large binary number, bring this number from base 2 into base 10, and then multiply by 17. the result is your N value. if this results in any error, or for some reason the graph didnt appear correctly, reply to this comment, and i can always help you some more. i know i made it sound complex, but once you understand it, it will seem really simple. i currently have many mathematically stable “N” values, but not a program to graph them on, and am still searching for a program i could use, but i know for a FACT that this is how to find the “N” value of whatever image you would like.

looy99

Thu, 2015-04-23 at 20:24:42

• this was meant to be in response to dario in order to help him understand, my apologies, i will put this under his comment now, again sorry.

looy99

Thu, 2015-04-23 at 20:27:09

• now i feel extra stupid, because i now believe this did respond to him. it is really late now in my local time zone, so i got confused, again sorry

looy99

Thu, 2015-04-23 at 20:28:38

• OK. Thank you very much. Can’t believe how fast you answered :)

dario333

Wed, 2015-04-22 at 01:29:59

• If you have Python installed on your system, you can run this Python script like any other script — it will create two image files called “out.png” and “out.svg”, and you can view those images.

S

Fri, 2015-04-17 at 12:28:31

10. Now, time for my own comment before i head off to bed. does anyone know of any free windows programs i could use in order to graph these. as i said before, i have different “N” values for many images, and havent been able to graph them

looy99

Thu, 2015-04-23 at 20:30:03

• Thanks for your other comments. The GrafEq mentioned in the post (by Jeff Tupper himself) is not free, but I think a “trial” version is available, and I’d be very surprised if it cannot graph these.

S

Fri, 2015-04-24 at 07:56:54

11. I did not check ALL the pages where you think they give the wrong “N”. But I did try to use the N from Wikipedia and they give the correct graph. If you LOOK at the GRAPH on wiki, the x-axis is plotted in the REVERSE order. That IS what you are expected to do when plotting such graph, I think.

casperyc

Fri, 2015-07-10 at 14:00:31

• That is almost exactly what I said: the constant 9609…4719 only works if you reverse both axes, else the graph comes out upside-down. But most sources have not bothered to specify that, and they have instead simply flipped the axes (either in their code or in their image) thinking “maybe that is what you are supposed to do”, as you just did. :-) Flipping both x- and y- axes from the standard definition of graph/plot is not something you do silently.

Wikipedia currently mentions “note that the axes in this plot have been reversed, otherwise the picture comes out upside-down”, but at the time I wrote this post (2011 April) it did not: that comment was added by Anders Kaseorg in 2013 August 14.

S

Sat, 2015-07-11 at 12:58:29

• Well, that’s fair enough. I guess it would only come to us when we actually bother to check them. :) But to be fair, at the university, we are always told NOT to trust things on wiki, as anyone can edit wiki pages. So it’s only a starting point, but it should NEVER be referenced. As far as some other online posts, those are posted by “amateurs”, so we can’t be too hash on them either.

casperyc

Sat, 2015-07-11 at 14:24:16

12. […] is post is motivated by a question on Mathematica Stackexchange and the interesting link posted in the question. My previous post had subtle errors. This allowed me to play with the higher […]