Everyone “knows” what a computer is, and has some sense of what it means to carry out a computation. Making this notion precise was left to Alonzo Church and Alan Turing, who in 1936 and 1937 independently developed a rigorous logical definition of what it meant for something to be “computable”. Although their constructions were very different (Turing’s a simple machine, Church’s a calculus of functions), they capture precisely the same notion, and anything expressible in one can be expressed in the other.

Today, I’d like to give an intuitive sense of just how universal the idea of computation is, and separate it from the physical machines you’re using to read this post. To do this, I’m going to explore a way of computing that may seem strange or impossible or, at the very least, impractical at first: I’ll show that you can compute anything a Turing machine can by taking simple, four-colored tiles (called Wang Tiles, after logician Hao Wang) and placing them on a board according to the rule that whenever two tiles touch, the touching sides must be the same color.

To get started, here’s what a single tile might look like:

It’s easy to see how we could place other tiles nearby. Here are 3 more tiles, placed so that their edge colors match.

When Hao Wang originally devised these tiles in 1961, he was concerned with the question of whether or not it was possible to decide if a given set of tiles could fill up an infinite two-dimensional plane while obeying the color-matching rule. It may come as a surprise that, in general, it is impossible to devise a procedure for deciding whether a tiling is possible — but we will see that this fact arises quite naturally from the tiles’ ability to perform computations.

So how do we actually compute using them? It turns out that by picking the right set of tiles, we can simulate the behavior of a Turing machine just by following the tile placement rules. To make sense of this, let’s recall what a Turing Machine is: a finite state machine, combined with an infinite, bidirectional tape, divided into discrete cells, that is initially blank. The machine also has a read/write head, which is what reads the symbol on the current cell, consults the state machine to see what to do next, and then writes a new symbol and moves the tape head left or right. This process continues until the machine reaches its halt state.

To make this more concrete, let’s look at a simple machine: the 3 state, 2 symbol Busy Beaver (I assure you I did not make this name up). The Busy Beaver is notable not because it has great practical use, but because it represents a kind of “maximally busy” machine — of all possible 3 state Turing machines, it writes the most “1” symbols to the tape before finally halting. Although I won’t get into them here, determining the Busy Beavers for various numbers of states has some interesting and deep philosophical and mathematical implications. Anyway, here’s Busy Beaver 3,2:

In this diagram, each arrow represents a rule for moving from one state to the next. The arrow going from A to B labelled “0:1,R”, for example, means “when there’s a 0 on the tape and you’re in state A, write a 1, move right, and go to state B”. If you like, you can carry out the computation starting with a blank tape (which in this case means filled with all zeroes). Here’s a full run of Busy Beaver (3,2), with the shaded cell indicating the position of the head.

Tape State Step 0 0 0 0 0 0 0 0 A 0 0 0 1 0 0 0 0 0 B 1 0 0 1 0 0 0 0 0 C 2 0 0 1 0 1 0 0 0 C 3 0 0 1 1 1 0 0 0 C 4 0 0 1 1 1 0 0 0 A 5 0 1 1 1 1 0 0 0 B 6 0 1 1 1 1 0 0 0 B 7 0 1 1 1 1 0 0 0 B 8 0 1 1 1 1 0 0 0 B 9 0 1 1 1 1 0 0 0 C 10 0 1 1 1 1 0 1 0 C 11 0 1 1 1 1 1 1 0 C 12 0 1 1 1 1 1 1 0 A 13 0 1 1 1 1 1 1 0 H 14

So how would we go about making a set of tiles that could carry out this computation, when placed correctly? A clue is given by looking at the table above. By showing the tape at each stage of the computation, we’ve taken a one-dimensional tape that evolves over time and transformed it into a static two-dimensional object. Our Wang tiling will work the same way: each row in the tiling will represent the state of the machine at a single point in time, and the colors will be chosen so that the only legal placement for the next row will represent the next stage of the computation.

For the details, I’m going to use a construction found in this paper; you can look there for more details if you’re interested. The only change I’ve made is to make the computation run from left to right rather than bottom to top; thus, the columns in our diagrams will represent the machine’s tape. Their construction uses three main kinds of tiles for the computation, as well as a handful of “special” tiles that are only used for the first step, to get things started. First, we have the alphabet tiles. There’s one of these for each symbol that the machine uses, and they’re responsible for simply propagating the content of a cell forward one column when the tape head is not reading or writing anything in that portion of the tape. They look like:

Using the same “X” color for the top and bottom of these tiles allows them to be placed above one another in the columns; meanwhile, because they differ in color on their left and right edges, they cannot be placed side by side — so we don’t have to worry about zeroes spontaneously changing into ones!

If these were our only tiles, we couldn’t do much except have a tape with some initial state, unchanging, extend off into infinity. To actually compute, we need to simulate the read-write head and state machine. We can accomplish this by making two new classes of tile that will work together to represent the idea that the machine’s head is at a particular place on the tape, and is moving from one state to another. First, we have the action tiles. Each of these represents one of the transition rules depicted in the state diagram above. So if we have a rule that states: “in state A, with 0 on the tape, write a 1, move right, and go into state B“, we’ll end up with a tile that looks like this:

On the top, we have the familiar “X”, which allows us to place it below an existing tape cell, whether it’s a “0” or a “1”. The left side is given a unique color that represents the combination of state “A” and symbol “0“. The bottom of the tile is given a unique color that represents the state the head is moving to, “B”; it’s on the bottom in this tile because the head is moving right (tilt your head 90° to the right if this doesn’t make sense 😉 ). Finally, the symbol being written is at the right; its color matches the left side of our “1” alphabet tile, which will allow us to correctly place a “1” on the tape in the next column.

Action tiles only do half the job of representing the tape head, however. To finish the job, we need tiles that can take an alphabet tile like 0 on the left and a state like B above and propagate the head forward into the state (B,0). This is accomplished with merging tiles, like the following:

We can see how this tile works with the action tile to transfer the state of the head into a new place on the tape. The top color, which represents the state B, pairs with the bottom color of the action tile we just saw, and the left color will pair with the “0” alphabet tile.

With these tiles in hand, we are almost ready to begin our computation, but we’re still missing a way to set up the initial state of the tape, and a way to signal that the computation has halted. First let’s consider how to set up the initial tape state. We need a tile that holds the initial state (A) of the tape head, positioned over a 0 cell, and then, throughout the rest of the column, tiles that represent blanks and can match up with “0” alphabet tiles.

Let’s look at the tape head first. We have to be a bit careful to construct a head that can only be placed once, or we may end up with a multi-headed Turing machine!

To guarantee that we only get one tape head, I’ve used a unique bottom color (“v“) and a unique top color (“^“); the initial blank tiles will use these colors to ensure that the tape head can only be placed once. These initial-“0” tiles will be constructed so that it’s impossible for them to be used anywhere else except at the beginning, by making their left side an “X” — a color that no tile has on its right. They will come in two flavors: those meant to be placed above the tape head, and those that will be placed below:

We can see that due to the unique colors used for the tops and bottoms of these tiles, the tape head can only appear on the board once.

A final technicality is how we get the machine to halt. This is fairly easy: we know that in the final column of computation there will be a motion tile whose right side is either (H,0) or (H,1). So to halt the machine, we just need tiles with matching colors on the left, and either “0” or “1” on the right. This will mean that all the remaining columns are simply copies of the tape’s state when the computation ended. The halt tile looks like:

The key difference between the halt tile and a regular action tile is that its top and bottom are both “X“, which means that only alphabet tiles can be placed next to it. And so in the following columns, the only legal placement of tiles will be alphabet tiles that propagate the final state of the tape forward.

Putting these all together, we get this set of tiles for the 3 state, 2 symbol Busy Beaver:

And, the full computation, in all its glorious 14 steps:

Using this construction, we can use tiles to compute anything that can be computed by a Turing machine. For example, here’s a machine that counts upward toward infinity in binary, starting at 3141592653 (an arbitrarily chosen number 😉 ): the board, the legend. The resulting diagrams look pretty cool, and I ended up making a poster for my wall showing an incrementer and two Busy Beavers.

This all seemed very counter-intuitive to me when I first encountered it. You can easily write a program to figure out a way to arrange a set of tiles, and it will know absolutely nothing about Turing machines or computation (in fact, that’s how these diagrams were generated). But by repeated application of a simple rule (match the colors), all the complexity of universal computation emerges. And yet, the computations done on your laptop are essentially no different: the transistors in your processor and the electrons that flow through them know nothing of computation, but by following physical laws down paths of least resistance they perform incredible feats of computation.

I’ll close by taking this hitherto theoretical and abstract exercise into the real world. An exciting area of research in the past 20 years has been DNA Computing, which attempts to perform massively parallel calculations just by using the molecular action of DNA molecules. As it turns out, it is possible to create DNA molecules with different kinds of “sticky ends”, that will bond only to matching ends — precisely what’s needed to create a molecular Wang Tile. Although this strategy for self-assembling computation has been superseded by DNA Origami, simple Wang Tile-based computations such as XOR have been demonstrated in the laboratory. Science fiction writer Greg Egan even took this concept further, envisioning immense sheets of such molecules, computing simulations of complex ecosystems and even intelligent life.

Hopefully this post has given you a taste of just how many forms computation can take. It doesn’t end here, though. Long before Turing, German mathematician Gottfried Leibniz imagined performing computation using marbles rolling down a specially designed track, using gravity to guide them into computing arithmetic and solving algebraic equations. Turing machines have been simulated within Conway’s Game of Life. And a certain webcomic artist considered the possibility of one person, in the desert, moving rocks to simulate a universe. So next time you use your smartphone to throw some birds at pigs, stop to consider the miraculous nature of computation that makes it possible (I can’t wait for someone to show that you can simulate a Turing machine within Angry Birds).

Addendum: You can obtain the programs used to generate these images here (wangtiles.tar.gz); Python and either Cairo or Pygame+PIL are required (depending on which renderer you use).

Correction: An earlier version of this article used a different construction to ensure a unique tape head. Reddit user dmwit noted that it was not sufficient to guarantee uniqueness, and suggested a replacement, which has been incorporated into the article.