Tamari Lattices!

Tamari lattices are graphs (in the mathematical sense - a set of nodes with connections between them) describing a particular set of operations. I like them because they're pretty!

The (trivial) Tamari lattice for a three-element tree.
A (trivial) Tamari lattice, generated by the associations of three elements. Source file.

Oh - oh dear. How'd that get there? Okay, that's not a very good example.

There are many ways to generate and think of a Tamari lattice. The way I prefer to think of it is this: Consider some binary operation - you take two elements to produce a new one. You want to combine several of these elements. So long as you have three or more elements, there are multiple ways to combine them.

The game we play is this: You're allowed to step from one way of combining the elements to another, but only by left-association: turning (a, (b, c)) into ((a, b), c).

The only remaining rule is that if you can step from one combination to another, the second one has to appear below the first one when you draw it.

A Tamari lattice for a four-element tree.
As above, but generated by a four-element tree. Source file.

You can also think about it in terms of tree rotations - but remember that that's a different tree than the one we're building as the Tamari lattice. Tree rotations are just another way to think of left-association and right-association.

If you look at the wikipedia article on Tamari lattices, you'll see a very pretty image:

There are a lot of ways to reorganize a Tamari lattice, and it takes some artistic work to make one that really looks good. You can even visualize the same graph as a 3D shape called an "associahedron", but I like it in the simple gridded lattice form above. It reminds me how much beauty there can be in regularity - you can see the grid, but it doesn't look constrained by it. I might get a tattoo of the five-element Tamari lattice someday.

Tamari lattice for a five-element tree.
Also the five-element lattice! Compare to the example above, on wikipedia.. Source file.

All these graphs with the ovals and the curvy lines were generated by yours truly! I made some python that would take a string representation of an association of a number of elements and convert it into an easily-manipulated memory representation. Then, a few tree rotations spit out all the possible results of left-associating on it, and it was relatively simple to print out a .dot file, parseable by graphviz, that described the graph. It even labeled the nodes!

dot happily converted them into the png files you're looking at. Of course, they don't have the human touch, so they're not organized into beautiful grid lines and 45° angles - but it can be fun to try to mentally reorganize them into a nicer shape. If you want, you can download the .dot source files for any of these, and play around with them in a graph-editing program (such as XDot)

Tamari lattice for a six-element tree.
It's starting to get out of hand, I think.Source file.

Unfortunately, at a certain point I think it's going to get difficult to make these pretty. It turns out there are a lot of ways to associate a larger number of elements! Starting with a six-element tree or string, there are 42 elements (above). With seven, there are 132! Wowie!

Tamari lattice for a seven-element tree.
Oh dear. Source file.

My server was chugging along trying to generate tamari_8.dot but I started getting messages from linode about going over my CPU quotas, so I canceled it - after it ran for an hour or so, without finishing. I think the seven-element one is messy-looking enough!

You can look at the python script I used to make this, but it's not particularly pretty - I was bored one day and decided I was going to figure out how to generate these... It's not exactly meant to be extensible. It's got a basic binary tree node class I threw together for working the association rules and a handful of (really ugly) helper functions. I just went through and rewrote it a bit to be nicer - the final output loop may please you if you enjoy sets and list comprehensions:

current_generation = set()
next_generation = {RootOfAllEvil}
edges = set()
labels = set()

while next_generation: # While there are trees to examine.
	# Move to look at the next generation.
	current_generation = next_generation

	# Clear out the next gen to fill it with the children of this generation.
	next_generation = set()

	# Ensure there are labels for this generation.
	labels = labels | set(label_from_node(parent) for parent in current_generation)

	for parent in current_generation:
		children = generate_children(parent)

		labels = labels | set(label_from_node(child) for child in children)
		edges = edges | set(str(parent) + " -> " + str(child) + ";" for child in children)
		next_generation = next_generation | children

# Output a dot-formatted stream!
args.output.write(u"digraph tamari {\n")
args.output.write(u"\n".join(labels) + "\n")
args.output.write(u"\n".join(edges))
args.output.write(u"\n}\n")

The full script can be used by running python tamari.py --length 4 | dot -Tpng > output.png to produce a graph. tamari.py will print out to a specified file if you also include a filename: python tamari.py --length 5 output.dot