shooflenet/articles/tamari.article.html

71 lines
7.5 KiB
HTML

<article class="project">
<h1>Tamari Lattices!</h1>
<p>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!</p>
<figure>
<img src="/tamari/tamari_3.png" alt="The (trivial) Tamari lattice for a three-element tree.">
<figcaption>A (trivial) Tamari lattice, generated by the associations of three elements. <a class="source" href="/tamari/tamari_3.dot">Source file.</a></figcaption>
</figure>
<p>Oh - oh dear. How'd that get there? Okay, that's not a very good example.</p>
<p>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 - a way to use two things to make a new one. You want to combine a bunch. So long as you have three or more elements, there's more than one way to combine them - if you've got <code>a</code>, <code>b</code>, and <code>c</code>, you could combine <code>b</code> and <code>c</code>, and then combine the product of that with <code>a</code>, <em>or</em> you could combine <code>a</code> and <code>b</code>, and then combine that with <code>c</code>. We're going to pretend you can't combine <code>a</code> and <code>c</code> (although maybe that would produce more pictures...). The way we write combining two elements is like this: <code>(a, b)</code>. So that means that the first way of combing <code>a</code>, <code>b</code>, and <code>c</code> is written like so: <code>(a, (b, c))</code>. The second way would be <code>((a, b), c)</code>.</p>
<p>Okay, got it? Good.</p>
<p>The game we play is this: You're allowed to step from one way of combining the elements to another, but only by <i class="keyword">left-association</i>: turning <code>(a, (b, c))</code> into <code>((a, b), c)</code>.</p>
<p>The only other rule is that if you can step from one combination to another, the second one has to be drawn below the first one when you list them all out.</p>
<figure>
<img src="/tamari/tamari_4.png" alt="A Tamari lattice for a four-element tree.">
<figcaption>As above, but generated by a four-element tree. <a class="source" href="/tamari/tamari_4.dot">Source file.</a></figcaption>
</figure>
<span class="sidenote span4">You can also think about it in terms of <a href="http://wikipedia.org/wiki/Tree_rotation">tree rotations</a> - 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.</span>
<p>If you look at <a href="http://wikipedia.org/wiki/Tamari_lattice">the wikipedia article on Tamari lattices</a>, you'll see a very pretty image:</p>
<figure>
<img src="http://upload.wikimedia.org/wikipedia/commons/4/46/Tamari_lattice.svg">
<figcaption><a href="http://en.wikipedia.org/wiki/File:Tamari_lattice.svg">http://en.wikipedia.org/wiki/File:Tamari_lattice.svg</a></figcaption>
</figure>
<p>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 href="http://en.wikipedia.org/wiki/Associahedron">a 3D shape called an "associahedron"</a>, 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.</p>
<figure>
<img src="/tamari/tamari_5.png" alt="Tamari lattice for a five-element tree.">
<figcaption>Also the five-element lattice! Compare to the <a href="http://wikipedia.org/wiki/Tamari_lattice">example above, on wikipedia.</a>. <a class="source" href="/tamari/tamari_5.dot">Source file.</a></figcaption>
</figure>
<p>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 <code>.dot</code> file, parseable by <a href="http://www.graphviz.org/">graphviz</a>, that described the graph. It even labeled the nodes!</p>
<p><code>dot</code> happily converted them into the <code>png</code> 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 <code>.dot</code> source files for any of these, and play around with them in a graph-editing program (such as <a href="https://github.com/jrfonseca/xdot.py">XDot</a>)</p>
<figure>
<img src="/tamari/tamari_6.png" alt="Tamari lattice for a six-element tree.">
<figcaption>It's starting to get out of hand, I think. <a class="source" href="/tamari/tamari_6.dot">Source file.</a></figcaption>
</figure>
<p>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!</p>
<figure>
<img src="/tamari/tamari_7.png" alt="Tamari lattice for a seven-element tree.">
<figcaption>Oh dear. <a class="source" href="/tamari/tamari_7.dot">Source file.</a></figcaption>
</figure>
<p>My server was chugging along trying to generate <code>tamari_8.dot</code> 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!</p>
<p>You can look at the <a class="source" href="/tamari/tamari.py">python script</a> 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 <code>set</code>s and list comprehensions:</p>
<pre>
<code class="language-python">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")</code></pre>
<p>The full script can be used by running <code class="language-bash">python tamari.py --length 4 | dot -Tpng > output.png</code> to produce a graph. <code>tamari.py</code> will print out to a specified file if you also include a filename: <code class="language-bash">python tamari.py --length 5 output.dot</code></p>
</article>