66 lines
6.7 KiB
HTML
66 lines
6.7 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="/static/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="/static/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 - 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.</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 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.</p>
|
|
<figure>
|
|
<img src="/static/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="/static/tamari/tamari_4.dot">Source file.</a></figcaption>
|
|
</figure>
|
|
<p>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.</p>
|
|
<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>
|
|
<img src="http://upload.wikimedia.org/wikipedia/commons/4/46/Tamari_lattice.svg">
|
|
<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="/static/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="/static/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="/static/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="/static/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="/static/tamari/tamari_7.png" alt="Tamari lattice for a seven-element tree.">
|
|
<figcaption>Oh dear. <a class="source" href="/static/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="/static/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> |