More from Chris Grossack's Blog
Earlier today I gave a talk in the graduate student seminar titled “Counting is Hard. Complex Analysis is Easy.” based in part on my recent blog post about analytic combinatorics and based in part on Varilly’s notes on Dirichlet’s Theorem, showing how to count the number of trees of a certain shape and the number of “primes of a certain shape” by doing complex analysis. While prepping for this talk, I realized there’s a very pretty geometric way to see what’s going on when counting rooted ordered ternary trees! I don’t usually write blog posts about my local seminar talks anymore, but I think this is more than worthy of an exception! For instance, I think this could serve as a great visiual example of branches and mild singularities in complex analysis. So, let’s remember the problem! We want to count the number of rooted ordered ternary trees with $n$ nodes. Call this number $t_n$. We note that every such tree is either a root node a root with one child a root with two children a root with three children where each child is recursively a rooted ordered ternary tree. If we define $T(z) = \sum_n t_n z^n$ to be the (ordinary) generating function for the $t_n$ we see from this recurrence relation that it must satisfy the functional equation That is, if $P(z,w) = -w + z + zw + zw^2 + zw^3$ then $P(z,T(z)) = 0$. If we draw (the real locus of) $P$ it looks like and the implicit function theorem says that we can find functions $f(z)$ so that $P(z,f(z)) = 0$ through any starting point $P(z_0,f_0)$ on the curve for as long as $\frac{\partial P}{\partial w} \neq 0$. In particular, we know that our $T(0) = t_0 = 0$ since there are no trees with zero vertices, so that our $T(z)$ takes $z$ to the unique part of this curve passing through the origin, for as long as this is defined. Here we’ll plot our curve $P$ in blue, and the implicit function $T(z)$ in orange. Note we have to stop at $z \approx 0.27695$ since here $\frac{\partial P}{\partial w} = 0$ so that the slope is infinite and we can’t continue. Said another way, we bend backwards and if we tried to continue we would fail the vertical line test. But since we have to stop here, we see that $0.27695$ is the radius of convergence for $T$, and is the dominant singularity! Next, can we find a good approximation for $T$ near this singularity? In the main post we used puiseux series for this, but it’s instructive to do it by hand! Note that $\frac{\partial P}{\partial z} \neq 0$ at $(0.27695, 0.65730)$ so there’s nothing stopping us from approximating $z$ as a function of $w$ at this point (then inverting it). Indeed, we can solve for $z = \frac{w}{1+w+w^2+w^3}$ and then just taylor expand this at our point of interest: Of course, we chose this point because $\frac{\mathrm{d}z}{\mathrm{d}w} = \frac{- \frac{\partial P}{\partial w}}{\frac{\partial P}{\partial z}}$ is $0$ here. So we know this $2.97 \times 10^{-8}$ is a rounding error and our leading order expansion is Here’s a graph zoomed into near the singularity. The actual graph of $P$ is shown in blue, and our approximating parabola is shown in orange: But of course if $z - 0.27695 \approx -.34680 (w - 0.6573)^2$ then we can solve for and if we want this to agree with our $w = T(z)$ branch through the origin we obviously have to choose the negative square root (since we want the lower half of this sideways parabola1). Here we draw our $T(z)$ in blue, and we draw the approximation $0.6573 - 0.8936 \sqrt{1 - \frac{z}{0.27695}}$ in orange so you can see how well they line up! But now from here we can run exactly the same argument as in the previous post! We compute $t_n = \frac{1}{2\pi i} \oint \frac{T}{z^{n+1}} \ \mathrm{d}z$, along a keyhole contour around the singular point $z=0.27695$ with a branch cut along the real axis. The brunt of this integral comes from the cutout near the singular point, where $T$ is well approximated by $0.6573 - 0.8936 \sqrt{1 - \frac{z}{0.27695}}$ so that Again, for more details about exactly what this keyhole contour is and how you estimate this integral along it, see the main post. Let’s go ahead and call it here! My actual talk was slightly longer than this, since I also sketched a proof of Dirichlet’s Theorem following Varilly’s notes on the subject, but there’s no sense in me writing that up since those notes are already so good! Plus it’s getting late and I want to go to bed, haha. As always, here’s a copy of my title and abstract. Unfortunately I don’t have any slides or recordings today, but I’m giving another talk at WiSCons in Madison next week and I should have slides for that. I’m also hoping to finish a sister blog post for that talk where I do more example computations in more detail than I could possibly do in a 20 minute talk. Lots of writing to do this week! Take care all, stay safe, and I can’t wait to talk soon ^_^ Counting is Hard. Complex Analysis is Easy. Don’t you miss being a kid, when your mom would ask you to count how many of your alphabet fridge magnets were both red and vowels? When you saw the answer was “2”, you felt such accomplishment…. But counting has only gotten harder since then, and now if you want to count how many objects satisfy some properties (say, being both red and vowels) it can be borderline impossible! In this talk we’ll show how you can solve counting problems by doing complex analysis instead. First we’ll count the number of trees of a certain shape, then (given time) we’ll count how many prime numbers are of a (different) certain shape. In the main post we used puiseux series for this, and we had to essentially guess which branch was correct. Now we see how the geometry of the situation tells us that we have to choose the negative branch of the square root! After all, this is the one that locally agrees with the rest of the graph of $T$! ↩
Another day, another blog post that starts with “I was on mse the other day…”. This time, someone asked an interesting question amounting to “how many unordered rooted ternary trees with $n$ nodes are there, up to isomorphism?”. I’m a sucker for these kinds of combinatorial problems, and after finding a generating function solution I wanted to push myself to get an asymptotic approximation using Flajolet–Sedgewick style analytic combinatorics! I’ve never actually done this before, so I learned a lot, and I want to share some of the things I learned – especially how to do this stuff in sage! Now, you might be thinking – didn’t you write a very similar blog post three years ago? Yes. Yes I did. Did I also completely forget what was in that post? Yes. Yes I did, haha. For some reason I was getting it mixed up with this other post from even more years ago, which isn’t nearly as relevant. Thankfully it didn’t matter much, since I’m fairly sure what I wanted to do wouldn’t work in the framework of that post anyways, and now I have a better idea of what this machinery is actually doing which is really exciting (since I’ve been wanting to understand this stuff for years). Let’s start with a warmup problem! How might we count the number of rooted ordered ternary trees with $n$ nodes? These are the kinds of “ternary trees” that you might remember from a first class on algorithms and data structures. Such a tree is either a leaf or an internal node with 1,2, or 3 children. Crucially these children come with an order, because the datatype keeps track of which child is on the left/right (in the case of 2 children) or on the left/middle/right (in the case of 3 children). After all, from a CS perspective, we need to remember this in order to traverse the tree! This means that the following two trees are distinct for our purposes, even though they’re isomorphic as graphs: In a functional programming language, you might describe this datatype by T z = Leaf z | Unary z (T z) | Binary z (T z) (T z) | Ternary z (T z) (T z) (T z) and this translates immediately to give a functional equation for the generating function of $t_n$, which counts the number of rooted ordered ternary trees with $n$ nodes: We can rearrange this as so that we can compute the power series expansion of $T$ by lagrange inversion: = QQbar[[]] # power series ring T = (z/(1 + z + z^2 + z^3)).reverse() show(T.O(10)) Incredibly, this agrees with A036765, which is the “number of ordered rooted trees with n non-root nodes and all outdegrees <= three”, as we hoped! You might reasonably ask if there’s a closed form for these numbers, and this is too much to ask for (indeed, it’s already too much to ask for a closed form for fibonacci numbers, and this is more complicated). But like the fibonacci numbers, we can come up with an excellent approximation: where $C = \frac{(0.8936\ldots)}{2 \sqrt{\pi}}$ is a constant. Indeed, this gives fantastic results! Let’s plot the ratio of this approximation to the true value so we can see just how good this approximation gets as $n$ gets large. Note that it respects the promised big-oh error bound too! = PowerSeriesRing(QQbar, default_prec=N) T = (z/(1 + z + z^2 + z^3)).reverse() return T.coefficients()[n-1:] def approx(n,N): # very very magic C = 0.8936373911078061 / (2 * sqrt(pi)) w = 3.610718613276040 return [(C * w^k * (1/k^1.5)).n() for k in range(n,N+1)] show(html("Plot the error ratios in the range [n,N]")) @interact def _(n=input_box(100, width=20, label="$n$"), N=input_box(120, width=20, label="$N$"), auto_update=False): actuals = actual(n,N) approxs = approx(n,N) ratios = [(actuals[i]/approxs[i]) for i in range(N+1-n)] show(html("ratio at n={}: {}".format(n, ratios[0]))) show(html("ratio at N={}: {}".format(N, ratios[-1]))) text_options = {'horizontal_alignment': 'right', 'vertical_alignment': 'bottom', 'fontsize': 'large'} G = Graphics() G += scatter_plot([(n+i,r) for (i,r) in enumerate(ratios)]) G += plot(1, (x,n,N)) G += plot(1-1/x, (x,n,N)) G += text('$y = 1$', (N, 1), **text_options) G += text('$y = 1-1/x$', (N, 1-1/N), **text_options) G.show() This is extremely cool, but where the hell did this approximation come from? The answer is called Singularity Analysis, and can be found in Chapter 2 Section 3 of Melczer’s excellent An Invitation to Analytic Combinatorics, or Chapters VI and VII of Flajolet and Sedgewick’s tome. See especially Theorem VII.3 on pg 468. Like seemingly every theorem in complex analysis, this is basically an application of the Residue Theorem. I won’t say too much about why it works, but I’ll at least gesture at a proof. You can read the above references if you want something more precise. First, we recall where $C$ is any contour containing the origin inside a region where $T$ is holomorphic. Then we draw the most important picture in complex analysis: Here the obvious marked point is our singularity $\omega$, and we’ve chosen a branch cut for $T$ (shown in blue1) so that $T$ is holomorphic in the region where the pink curve lives. We’ll estimate the value of this integral by estimating the contribution from the big circle, the little circle, and the two horizontal pieces2. It turns out that the two horizontal pieces basically contribute $O(1)$ amount to our integral, so we ignore them. Since the big circle is compact, $T$ will attain a maximal value on it, say $M$. Then the integral along the big circle (of radius $\omega + \epsilon$, say) is bounded by $2 \pi (\omega + \epsilon) \frac{M}{(\omega + \epsilon)^{n+1}} = O((\omega+\epsilon)^{-n})$ To estimate the integral around the little circle, it would be really helpful to have a series expansion at $\omega$ since we’re staying really close to it… Unfortunately, $\omega$ is a singular point so we don’t have a taylor series, but fortunately there’s another tool for exactly this job: a Puiseux Series! I won’t say much about what these are, especially since Richard Borcherds already put out such a great video on the topic. What matters is is that Sage can compute them for us3, so we can actually get our hands on the approximation! We compute the integral around the little circle to be roughly: In step $(1)$ we approximate $T$ by the first term of its puiseux series, in step $(2)$ we apply the generalized binomial theorem, so that in step $(3)$ we can apply the residue theorem to realize this integral as the coefficient of $z^{-1}$ in our laurent expansion. This gives us something which grows like $\widetilde{O}(\omega^{-n})$, dominating the contribution $O((\omega + \epsilon)^{-n})$ from the big circle, so that asymptotically this is the only term that matters. If we were more careful to keep track of the big-oh error for the puiseux series for $T$ we could easily sharpen this bound4 to see This looks a bit weird with the $(-1)^n$, but remember that $\binom{\alpha}{n}$ also alternates sign. Indeed, asymptotics for $\binom{\alpha}{n}$ are well known so that we can rewrite this as Which finally shows us where our magic numbers came from! Sage happily tells us that the dominant singularity for $T$ is at $\omega = (0.2769\ldots)$ and that a puiseux expansion for $T$ at $\omega$ is so that for us $\alpha = 1/2$, and $C_{1/2} = -(0.8936\ldots)$. Finally, since $\Gamma(-1/2) = -2 \sqrt{\pi}$ and $(0.2769\ldots)^{-1} = (3.6107\ldots)$ we see as promised! Indeed, here’s how you could actually get sage to do all this for you! = QQbar[] S. = R[] # our defining polynomial. # we want to solve for T as a function of z P = z*T^3 + z*T^2 + (z-1)*T + z # following Example 2.12 in Melczer, # we compute the dominant singularity w. w = min([r for (r,_) in P.discriminant().roots() if r != 0], key=lambda r: r.abs()) # to work with abelfunctions we need P # to be a polynomial in two variables R. = QQbar[] P = R(P) # compute the puiseux expansion for T at w. # I know from trial and error that the correct # branch to pick is entry [1] in the list. You # just need to check which one gives you # positive real coefficients for T at 0. s = abelfunctions.puiseux(P,w)[1] c = -sqrt(-s.x0/s.xcoefficient) As a fun exercise, you might modify this code (using s.add_term()) to compute a longer puiseux series and get asymptotics valid up to a multiplicative error of $O \left ( \frac{1}{n^2} \right )$ for the number of rooted ternary trees. Try modifying the previous code block to see that our current approximation is not accurate to $O \left ( \frac{1}{n^2} \right )$, and then check that your approximation is! Ok, now that we understand the warmup, let’s get to the actual problem! How many unordered rooted ternary trees are there, up to isomorphism? Now we’re counting up to graph isomorphism, so that our two trees are now considered isomorphic. It’s actually much less obvious how one might pin down a generating function for something like this, but the answer, serendipitously, comes from Pólya-Redfield counting! If this is new to you, you might be interested in my recent blog post where I talk a bit about one of its corollaries. Today, though, we’ll be using it in a much more sophisticated way. Say you have a structure $X$ acted on by a group $G$ and a collection $C$ of “colors”. How can we count the number of ways to give each $x \in X$ a color from $C$, up to the action of $G$? We start by building the cycle index polynomial of the action $G \curvearrowright X$, which we call $P_G(x_1, \ldots, x_n)$. Then we can plug all sorts of things into the variables $x_i$ in order to solve various counting problems. For example, if $C$ is literally just a finite set of colors, we can plug in $x_1 = x_2 = \ldots = x_n = |C|$ to recover the expression from my recent blog post. But we can also do much more! Say that $C$ is a possibly infinite family of allowable “colors”, each of a fixed “weight”. (For us, our “colors” will be trees, and the “weight” will be the number of nodes). Then we can arrange them into a generating function $F(t) = \sum c_i t^i$, where $c_i$ counts the number of colors of weight $i$5. Then an easy argument (given in full on the wikipedia page) shows that $P_G(F(t), F(t^2), \ldots, F(t^n))$ is a generating function counting the number of ways to color $X$ by colors from $C$, counted up to the $G$ action, and sorted by their total weight6. Check out the wikipedia page for a bunch of great examples! For us, we realize an unordered rooted ternary tree is either empty, or a root with 3 recursive children7. In the recursive case we also want to count up to the obvious $\mathfrak{S}_3$ action permuting the children, so by the previous discussion we learn that where \(P_{\mathfrak{S}_3}(x_1, x_2, x_3) = \frac{1}{6}(x_1^3 + 3x_1 x_2 + 2 x_3)\) is the cycle index polynomial for the symmetric group on three letters. Plugging this in we see Now, how might we get asymptotics for $t_n$ using this functional equation? First let’s think about how our solution to the warmup worked. We wrote $F(z,T)=0$ for a polynomial $F$, used the implicit function theorem to get a taylor series for $T$ at the origin, then got a puiseux series near the dominant singularity $\omega$ which let us accurately estimate the taylor coefficients $t_n$8. We’re going to play the same game here, except we’ll assume that $F$ is merely holomorphic rather than a polynomial. Because we’re no longer working with a polynomial, this really seems to require an infinite amount of data, so I’m not sure how one might get an exact solution for the relevant constants… But following Section VII.5 in Flajolet and Sedgewick we can get as precise a numerical solution as we like! We’ll assume that the functions $T(z^2)$ and $T(z^3)$ are already known analytic functions, so that we can write $F(z,w) = -w + 1 + \frac{z}{6} \left ( w^3 + 3 T(z^2) w + 2 T(z^3) \right )$. This is an analytic function satisfying $F(z,T) = 0$. Now for a touch of magic. Say we can find a pair $(r,s)$ with both $F(r,s)=0$ and $\left . \frac{\partial F}{\partial w} \right |_{(r,s)} = 0$… Then $F$ is singular in the $w$ direction at $(r,s)$ so this is a branch point for $T$. Since both $F$ and $F_w = \frac{\partial F}{\partial w}$ vanish at $(r,s)$ the taylor series for $F$ at $(r,s)$ starts Since we know $F(z,T)$ vanishes, we estimate up to smaller order terms so that a puiseux series for $T$ at $(r,s)$ begins If we write $\gamma = \sqrt{\frac{2r F_z(r,s)}{F_{ww}(r,s)}}$ and are slightly more careful with our error terms, the same technique from the warmup shows See Flajolet and Sedgewick Theorem VII.3 on page 468 for a more careful proof of this theorem. Now how do we use this? We can approximate $T$ by its taylor series at the origin, then numerically solve for the unique9 positive real solution to the system $F(r,s) = F_w(r,s) = 0$ using this approximation: = B[[]] # cycle index polynnomials S. = QQ[] P3 = (x1^3 + 3*x1*x2 + 2*x3)/6 # to start, the taylor coefficients of T are variables T = sum([t[i] * z^i for i in range(n)]) + O(z^n) lhs = T rhs = 1 + z*P3.subs(x1=T(z), x2=T(z^2), x3=T(z^3)) # formally expand out the rhs and set the coefficients # equal to each other. This gives a recurrence relation # for t[n] in terms of the t[i] for i If we run this code locally with $N=20$, we get the approximation so that we expect and indeed this seems to work really well! Our taylor expansion for $T$ agrees with A000598, as we expected, and comparing our approximation to our taylor expansion gives: = B[[]] S. = QQ[] P3 = (x1^3 + 3*x1*x2 + 2*x3)/6 T = sum([t[i] * z^i for i in range(N)]) + O(z^N) lhs = T rhs = 1 + z*P3.subs(x1=T(z), x2=T(z^2), x3=T(z^3)) I = B.ideal([lhs.coefficients()[i] - rhs.coefficients()[i] for i in range(N)]) return [I.reduce(t[i]) for i in range(n,N)] show(html("Plot the error ratios in the range [n,N]")) show(html("This is likely to time out if you make N too large online,")) show(html("so you might want to play around with it locally instead!")) @interact def _(n=input_box(10, width=20, label="$n$"), N=input_box(30, width=20, label="$N$"), auto_update=False): actuals = actualList(n,N) approxs = approxList(n,N) ratios = [actuals[i]/approxs[i] for i in range(N-n)] show(html("ratio at n={}: {}".format(n, ratios[0].n()))) show(html("ratio at N={}: {}".format(N, ratios[-1].n()))) text_options = {'horizontal_alignment': 'right', 'vertical_alignment': 'bottom', 'fontsize': 'large'} G = Graphics() G += scatter_plot([(n+i,r) for (i,r) in enumerate(ratios)]) G += plot(1, (x,n,N)) G += plot(1-1/x, (x,n,N)) G += text('$y = 1$', (N, 1), **text_options) G += text('$y = 1-1/x$', (N, 1-1/N), **text_options) G.show() I’m pretty proud of this approximation, so I think this is a good place to stop ^_^. As a fun exercise, can you write a program that outputs the number of cyclic rooted ternary trees on $n$ vertices? For these we consider two trees the same if they’re related by cyclicly permuting their children. Compare your solution to A000625 For bonus points, can you check that the number of such trees is, asymptotically, Wow! It’s been super nice to be writing up so many posts lately! Like I said in one of my other recent posts, I’ve had a lot of time to think about more bite sized problems and mse stuff while waiting for my DOI generating code to run, so I’ve had more things that felt quick to write up on my mind. My research is actually going quite well too! I have a few interesting directions to explore, and at least one project that might be wrapping up soon. Of course when that happens I’ll be sure to talk about it here, and I’m still planning out a series on fukaya categories, hall algebras, skein algebras, and more! That’s a pretty long one, though, so it’s easy for me to deprioritize, haha. It’s already heating up in Riverside, consistently in the 80s (Fahrenheit), so I can really feel the summer coming. I’m enjoying the sunny days, though, and it’s been nice to spend time working outside and under trees. Thanks for hanging out, all! Take care of each other, and I can’t wait to chat soon ^_^. Just like $w = \sqrt{z}$, a solution to $w^2 = z$ has branches, so too does $T$, a solution to $T = z + zT + zT^2 + zT^3$. ↩ Really these are circles with a little arc cut out, say by integrating from $\epsilon$ to $2 \pi - \epsilon$… But we’ll end up taking $\epsilon \to 0$ and we’re all friends here, so let’s not worry about it. ↩ Though at time of writing you need the abelfunctions package to do it. There is a builtin implementation of puiseux series, but it won’t actually compute a series expansion for you. ↩ Of course, it’s easy to see how to extend this technique to get better asypmtotics. The first approach is to just keep more terms of the puiseux series of $T$ at $\omega$. Then apply the generalized binomial formula multiple times for each term you kept. You can also do better by keeping track of more of the singularities. Build a contour with multiple keyholes in order to get sharper lower order asymptotics: Of course, you can also combine these approaches to keep track of both more singularities and more puiseux coefficients at each singularity. ↩ In fact we can push things even farther and work with multivariate generating functions, but we won’t need that here. ↩ This is why we plug $F(t^k)$ into $x_k$. Because $x_k$ is responsible for $k$-cycles, so we choose a single color for each $k$ cycle, but we have to count it $k$-many times towards our total weight. See the proof on the wikipedia page for more information! ↩ This actually isn’t the version of the recurrence I used in my mse answer. There I used the convention that a rooted tree had to be nonempty, since… you know… it has a root. But allowing possibly empty trees makes the recurrence much simpler, which in turn allows for much easier to analyze asymptotics. Hilariously this exact example is on the wikipedia page for the Pólya-Redfield theorem, which could have saved me a lot of time writing up that answer. I was a bit worried at first about doing these asymptotics by myself, since this was my first serious attempt at using analytic combinatorics, but serendipitously this exact example was also worked out in Flajolet and Sedgewick VII.5, though slightly more tersely than I would have liked, haha. ↩ Officially we have to check that the choice of puiseux series matches up with our choice of taylor series (since there’s multiple branches to our function). But this is easy to arrange for us by choosing the branch of the puisuex series that leads to all our coefficients being positive reals. If you want to do this purely analytically you need to solve a “connection problem”. See figure VII.9 in Flajolet and Sedgewick, as well as the surrounding text. ↩ Under mild technical conditions this pair $(r,s)$ is unique. See Flajolet and Sedgewick Theorem VII.3. ↩
This will be a really quick one! Over the last two weeks I’ve been finishing up a big project to make DOIs for all the papers published in TAC, and my code takes a while to run. So while testing I would hit “go” and have like 10 minutes to kill… which means it’s time to start answering questions on mse again! I haven’t been very active recently because I’ve been spending a lot of time on research and music, but it’s been nice to get back into it. I’m especially proud of a few recent answers, so I think I might quickly turn them into blog posts like I did in the old days! In this post, we’ll try to understand the Capping Algorithm which turns a graph embedded in a surface into a particularly nice embedding where the graph cuts the surface into disks. I drew some pretty pictures to explain what’s going on, and I’m really pleased with how they turned out! So, to start, what’s this “capping algorithm” all about? Say you have a (finite) graph $G$ and you want to know what surfaces it embeds into. For instance planar graphs are those which embed in $\mathbb{R}^2$ (equivalently $S^2$), and owners of this novelty mug know that even the famously nonplanar $K_{3,3}$ embeds in a torus1: Obviously every graph embeds into some high genus surface – just add an extra handle for every edge of the graph, and the edges can’t possibly cross each other! Also once you can embed in some surface you can obviously embed in higher genus surfaces by just adding handles you don’t use. This leads to two obvious “extremal” questions: What is the smallest genus surface which $G$ embeds into? What is the largest genus surface which $G$ embeds into where all the handles are necessary? Note we can check if a handle is “necessary” or not by cutting our surface along the edges of our graph. If the handle doesn’t get cut apart then our graph $G$ must not have used it! This leads to the precise definition: Defn: A $2$-Cell Embedding of $G$ in a surface $S$ is an embedding so that all the conected components of $S \setminus G$ are 2-cells (read: homeomorphic to disks). Then the “largest genus surface where all the handles are necessary” amounts to looking for the largest genus surface where $G$ admits a 2-cell embedding! But in fact, we can restrict attention to 2-cell embeddings in the smallest genus case too, since if we randomly embed $G$ into a surface, there’s an algorithm which only ever decreases the genus and outputs a 2-cell embedding! So if $S$ is the minimal genus surface that $G$ embeds in, we can run this algorithm to get a 2-cell embedding of $G$ in $S$. And what is that algorithm? It’s called Capping, see for instance Minimal Embeddings and the Genus of a Graph by J.W.T. Youngs. The idea is to cut your surface along $G$, look for anything that isn’t a disk, and “cap it off” to make it a disk. Then you repeat until everything in a disk, and you stop. The other day somebody on mse asked about this algorithm, and I had a lot of fun drawing some pictures to show what’s going on2! This post basically exists because I was really proud of how these drawings turned out, and wanted to share them somewhere more permanent, haha. Anyways, on with the show! We’ll start with an embedding of a graph 𝐺 (shown in purple) in a genus 2 surface: we’ll cut it into pieces along $G$, and choose one of our non-disk pieces (call it $S$) to futz with: Now we choose3 a big submanifold $T \subseteq S$ which leaves behind cylinders when we remove it. Pay attention to the boundary components of $T$, called $J_1$ and $J_2$ below, since that’s where we’ll attach a disk to “cap off” where $T$ used to be We glue all our pieces back together, but remove the interior of $T$ and then, as promised “cap off” the boundary components $J_1$ and $J_2$ with disks. Note that the genus decreased when we did this! It used to be genus 2, and now we’re genus 1! Note also that $G$ still embeds into our new surface: Let’s squish it around to a homeomorphic picture, then do the same process a second time! But faster now that we know what’s going on: At this point, we can try to do it again, but we’ll find that removing $G$ cuts our surface into disks: This tells us the algorithm is done, since we’ve successfully produced a 2-cell embedding of $G$ ^_^. Wow that was a really quick one today! Start to finish in under an hour, but it makes sense since I’d already drawn the pictures and spent some time doing research for my answer the other day. Maybe I’ll go play flute for a bit. Thanks for hanging out, all! Stay safe, and see you soon ^_^ This photo of a solution was taken from games4life.co.uk ↩ You know it’s funny, even over the course of drawing just these pictures the other day I feel like I improved a lot… I have half a mind to redraw all these pictures even better, but that would defeat the point of a quick post, so I’ll stay strong! ↩ It’s possible there’s a unique “best” choice of $T$ and I’m just inexperienced with this algorithm. I hadn’t heard of it until I wrote this answer, so there’s a lot of details that I’m fuzzy on. If you happen to know a lot about this stuff, definitely let me know more! ↩
Every few weeks recently I’ve been putting a new fun problem on one of the whiteboards in the first year office. These are often inspired by something I saw on MSE, and I’m usually choosing problems that force you to understand something fundamental really well. Then I usually have a “challenge” bonus problem that uses the same ideas, but requires you to do some independent research to finish the puzzle! I’ve just decided what the next problem is going to be, and I’m going to post about it here because I think it’s too cute to not share more widely! This is also going to serve as a nice excuse to talk about some important reasons to care about yoneda and representability that I don’t think we often tell beginners! Before we start, though, some quick life updates: I’m still waiting to hear back positively from postdocs, but there’s still plenty of departments where I’d be very happy. I’m trying to not stress out until the end of april. What’s more stressful is my actual dissertation – because we had to move everything up a year, I didn’t have as much time as I expected to solve my main problem, and while I solved some very simple thing that’s needed along the way… It’s really not a very good thesis, haha. So I’m trying really hard to finish the whole problem in the time I have, and we’ll see how I manage. My mental health has been pretty hit or miss with the *gestures at the state of the world*, but I’m doing what I can where I can to help, and that’s been good for what would otherwise be an overwhelming sense of helplessness. I know everyone is feeling some amount of this, especially in the queer and trans community, and I encourage everyone to find something actionable to do on a local level – it helps the community, and it really does help keep the feelings manageable. BUT, enough about all that! I haven’t been writing much because I’ve been so focused on research, and I’ve really missed posting here. The quicker I am the more likely I’ll find time to do it again, so let’s get to the fun part! I’m going to assume that most people reading my blog have at least heard of the Yoneda Lemma. But it’s possible that some people reading this are confused as to why you might care about it. Like, what does it buy you? How does it help prove theorems? One answer is that it’s foundational for thinking about the functor of points approach to lots of subjects, which tells you how to study things like stacks, etc. Said in a different way, it’s an extremely useful perspective for studying certain moduli problems – you can see my old blog post about this here if you’re interested. But that’s all quite high powered. Is there a more concrete reason to care about yoneda? The answer here is inspired by one of Terry Tao’s old blog posts – the yoneda lemma tells you how to understand polymorphic transformations between two constructions (which are a priori complicated) by just studying regular old functions between representing objects! For one version of this, say you want to understand cohomology operations. That is, say you want to understand when there’s a map on cohomology $H^p(X,G_1) \to H^q(X,G_2)$ which is “polymorphic in $X$” or “uniform in $X$” in the sense that the same map works no matter which $X$ you choose1. Just as in analysis where uniformity allows you to prove lots of ~bonus results~, requiring uniformity here gives us access to many additional theorems – such as the yoneda lemma. Here this “uniformity” is usually called naturality of the transformation, and the precise relationship to polymorphism will be well understood by anyone who learned category theory via functional programming2, and is well explained in some of Bartosz Milewski’s old blog posts here and here. Now we know that $H^p(-,G)$ is represented by a space called $K(G,p)$, so asking for one of these “cohomology operations” is asking for a natural transformation Which, by representability, is a natural transformation but now we finally get to use yoneda! These natural transformations are exactly the same thing as ordinary continuous functions (up to homotopy) This means if we can understand all continuous functions between these fixed spaces, that’s enough to understand all cohomology operations $H^p(X,G_1) \to H^q(X,G_2)$ for every space $X$ simultaneously! The ability to work with the representing objects directly is a huge reduction in complexity, and one of the main reasons people work with objects like “stacks” and “spectra” is because they want more things to be representable so that they can play exactly this game3. That’s well and good…. But surely that can’t be the “down to earth” example, right? Cohomology operations are interesting, and might eventually feel down to earth, but objectively most people would laugh at that idea. This, finally, brings us to the problem I’ll be writing on the first year’s whiteboard later today: Let $R$ be a (commutative, unital) ring. Classify all “polymorphic” functions $R^n \to R$. That is, all (set) functions $R^n \to R$ that can be defined uniformly for all rings $R$ simultaneously. (Hint: yoneda) If $G$ is a finite group, define a “$G$-torsion collection” in $R$ to be a group homomorphism $G \to R^\times$ from $G$ to the units of $R$. For example, a “$C_n$-torsion collection” is an element $x \in R$ so that $x^n = 1$, and a “$\mathfrak{S}_3$-torsion collection” is determined by elements $x,y \in R$ with $x^2 = 1$, $y^3 = 1$, and $xyx = y^2$ (because $\langle x, y \mid x^2=1, \ y^3=1, \ xyx=y^2 \rangle$ is a presentation for $\mathfrak{S}_3$) (Challenge) Classify all “polymorphic” (set) functions \(\Big \{\mathfrak{S}_3\text{-torsion collections in $R$} \Big \} \to \Big \{C_2\text{-torsion collections in $R$} \Big \}\) I’m about to spoil both of these problems, so if you want to think about them (and I really encourage you to think about them! At least the first problem!) now is your last chance to be unbiased by my explanation… Ok, so. Inspired by the rest of this post you’ll want to think about how to represent the constructions above. For the first problem, where we want set functions $R^n \to R$, that means we want to represent4 the functor sending a ring $R$ to the underlying set of $R^n$ the functor sending a ring $R$ to its underlying set The second one isn’t so hard to do – a moment’s thought shows that ring homs $\mathbb{Z}[x_1] \to R$ are in bijection with elements of $R$ (we just have to choose where to send $x_1$). Once you’ve figured this out it’s not such a big jump to see that ring homs $\mathbb{Z}[x_1, \ldots, x_n] \to R$ are in bijection with elements of $R^n$ (we just have to choose where to send each of the $x_i$ separately). So classifying “polymorphic” transformations $R^n \to R$ is classifying natural transformations which, by yoneda, is asking to classifying good old fashioned ring homs and, as before, we just need to decide where $y$ goes! So this is in bijection with the underlying set of $\mathbb{Z}[x_1, \ldots, x_n]$. That is, with integer-coefficient polynomials in $n$ variables. It’s not hard to see that any such polynomial gives you such a natural map! Indeed, for a concrete example take $p = x_1^2 + 2 x_1 x_2 - 3$. Then we get a function $R^2 \to R$ sending $(r_1, r_2) \mapsto r_1^2 + 2 r_1 r_2 - 3$, where an integer like $-3$ is interpreted in $R$ as $0_R - 1_R - 1_R - 1_R$. If one thought about this problem without knowing category theory, I think it would be pretty easy to conjecture that integer polynomials are the only polymorphic maps $R^n \to R$… But I’m not sure how you would prove it without basically rediscovering this special case of yoneda! Now… what about the challenge problem? We want to classify “polymorphic” maps Again we have a natural5 conjecture, since if we have a group homomorphism $\mathfrak{S}_3 \to R^\times$ we get some obvious group homomorphisms $C_2 \to R^\times$ too (namely the images of $(1 \ 2)$, $(2 \ 3)$ and $(1 \ 3)$, the 2-torsion elements in $\mathfrak{S}_3$)… Could this be all of them? Well, a “$G$-torsion collection” in $R$ is a group homomoprhism $G \to R^\times$, and these are in bijection with ring maps $\mathbb{Z}G \to R$! So the same idea as before shows that classifying natural transformations is the same as classifying natural transformations which, by yoneda, means classifying ring maps and thus means classifying $C_2$-torsion collections in $\mathbb{Z}\mathfrak{S}_3$. So we want to understand the group of units in $\mathbb{Z}\mathfrak{S}_3$, and in particular we want to classify the $2$-torsion elements in this group! Now is where the independent research comes in. You might naively guess that the group of units in $\mathbb{Z}G$ is just $G$ again… But you would be wrong! Of course if $g \in G$ then both $+g$ and $-g$ are units in $\mathbb{Z}G$, but even this isn’t enough! Understanding the units in group rings turns out to be a subtle and interesting problem, and I think it’s extra cute that this little puzzle helps people learn about this surprisingly rich subject6. We want to understand the group of units in $\mathbb{Z}\mathfrak{S}_3$, and searching for things related to this will quickly turn up the paper The Group of Units of the Integral Group Ring $\mathbb{Z}S_3$ by Hughes and Pearson, which certainly seems related! This paper is only 6 pages long, and is a very polite read7. Part (2) of their Theorem 1 is exactly what we’re looking for: (2) … there are $2$ conjugacy classes of elements of order $2$, with generic elements $(12)$ and $t=(12) + 3(13) - 3(23) - 3(123) + 3(132)$ respectively. What does this mean for us? Their Part (1) to this same theorem gives an isomorphism of \((\mathbb{Z}\mathfrak{S}_3)^\times\) with a certain $2 \times 2$ matrix group, so it’s easy to compute conjugation. So knowing this and knowing both conjugacy representatives we have a classification of all order 2 elements in $\mathbb{Z}\mathfrak{S}_3$, and by extension (crucially using yoneda and representability!) a classification of all natural transformations Indeed from this we’ve learned that our naive conjecture was wrong! This element $t$ is not one of the 2-torsion elements we were expecting, and it gives us a new and unexpected natural transformation! If $f : \mathfrak{S}_3 \to R^\times$ is a $\mathfrak{S}_3$-torsion collection in $R$, then of course we have $C_2$-torsion elements $f(1 \ 2)$, $f(2\ 3)$ and $f(1 \ 3)$. But it turns out we also have a secret, special $C_2$-torsion element Or, said another way, if $x,y \in R^\times$ with $x^2 = 1$, $y^3 = 1$, and $xyx = y^2$ determine a $\mathfrak{S}_3$-torsion collection in $R$, then is a (probably surprising!) $C_2$-torsion element in $R$. Of course, as with the last problem, I’m not sure how you would even begin to approach this classification problem without rediscovering the relevant version of the yoneda lemma! Thanks again for hanging out, everyone! I’m working on a lot of really fun stuff and I can’t wait to have time to talk about it. I think I want a quick outro today – I’ve had the sniffles all weekend, probably because I didn’t dress well before hanging out in the cold with one of my best friends who visited me last week! We made creme brulee for the first time (since I recently bought a blowtorch), and it was surprisingly easy and turned out delicious! I already make a lot of lava cakes when I want a decadent and fancy dessert, but I’ll have to add creme brulee into the rotation! Talk soon, everyone! Stay warm 💖 This “polymorphism” (which, of course, corresponds to naturality) is because we want an operation that’s really coming from the cohomology rather than being an “accidental” operation that comes from structure on $X$. ↩ Like I did… about a decade ago… I realized when writing this post that I remember waiting for many of these Bartosz Milewski posts to be published! But these posts have been done since 2017. Wild. ↩ I was so close to making “spectra” in this sentence link to spectra instead, which I think would be hilarious, but I decided against it. ↩ Some pedants might prefer I say corepresent. This footnote is purely to indicate that I do know better, I just don’t care, haha. ↩ Pun very much intended ↩ I forget exactly when I learned that the units in $\mathbb{Z}G$ might be bigger than just $\pm G$… But I remember being extremely surprised at the time! I’ll mention, though, that this maybe shouldn’t be that surprising. Indeed the group ring and group of units constructions are adjoint, so the unit of the adjunction gives a (natural) map and there’s no reason to suspect this unit is an isomorphism! Most units aren’t, haha. ↩ Though you have to get over the “function application on the right” notation, which goes totally unmentioned and confused me for a second when I read it. Functions on the right is absolutely objectively the better notation, and unfortunately it’s just confusing enough when you aren’t used to it to make it so that it’s unlikely to ever really catch on. ↩
More in science
The physicist Sidney Nagel delights in solving mysteries of the universe that are hiding in plain sight. The post Finding Beauty and Truth in Mundane Occurrences first appeared on Quanta Magazine
Federal enforcement of environmental laws has slowed significantly under President Trump. Read more on E360 →
Earlier today I gave a talk in the graduate student seminar titled “Counting is Hard. Complex Analysis is Easy.” based in part on my recent blog post about analytic combinatorics and based in part on Varilly’s notes on Dirichlet’s Theorem, showing how to count the number of trees of a certain shape and the number of “primes of a certain shape” by doing complex analysis. While prepping for this talk, I realized there’s a very pretty geometric way to see what’s going on when counting rooted ordered ternary trees! I don’t usually write blog posts about my local seminar talks anymore, but I think this is more than worthy of an exception! For instance, I think this could serve as a great visiual example of branches and mild singularities in complex analysis. So, let’s remember the problem! We want to count the number of rooted ordered ternary trees with $n$ nodes. Call this number $t_n$. We note that every such tree is either a root node a root with one child a root with two children a root with three children where each child is recursively a rooted ordered ternary tree. If we define $T(z) = \sum_n t_n z^n$ to be the (ordinary) generating function for the $t_n$ we see from this recurrence relation that it must satisfy the functional equation That is, if $P(z,w) = -w + z + zw + zw^2 + zw^3$ then $P(z,T(z)) = 0$. If we draw (the real locus of) $P$ it looks like and the implicit function theorem says that we can find functions $f(z)$ so that $P(z,f(z)) = 0$ through any starting point $P(z_0,f_0)$ on the curve for as long as $\frac{\partial P}{\partial w} \neq 0$. In particular, we know that our $T(0) = t_0 = 0$ since there are no trees with zero vertices, so that our $T(z)$ takes $z$ to the unique part of this curve passing through the origin, for as long as this is defined. Here we’ll plot our curve $P$ in blue, and the implicit function $T(z)$ in orange. Note we have to stop at $z \approx 0.27695$ since here $\frac{\partial P}{\partial w} = 0$ so that the slope is infinite and we can’t continue. Said another way, we bend backwards and if we tried to continue we would fail the vertical line test. But since we have to stop here, we see that $0.27695$ is the radius of convergence for $T$, and is the dominant singularity! Next, can we find a good approximation for $T$ near this singularity? In the main post we used puiseux series for this, but it’s instructive to do it by hand! Note that $\frac{\partial P}{\partial z} \neq 0$ at $(0.27695, 0.65730)$ so there’s nothing stopping us from approximating $z$ as a function of $w$ at this point (then inverting it). Indeed, we can solve for $z = \frac{w}{1+w+w^2+w^3}$ and then just taylor expand this at our point of interest: Of course, we chose this point because $\frac{\mathrm{d}z}{\mathrm{d}w} = \frac{- \frac{\partial P}{\partial w}}{\frac{\partial P}{\partial z}}$ is $0$ here. So we know this $2.97 \times 10^{-8}$ is a rounding error and our leading order expansion is Here’s a graph zoomed into near the singularity. The actual graph of $P$ is shown in blue, and our approximating parabola is shown in orange: But of course if $z - 0.27695 \approx -.34680 (w - 0.6573)^2$ then we can solve for and if we want this to agree with our $w = T(z)$ branch through the origin we obviously have to choose the negative square root (since we want the lower half of this sideways parabola1). Here we draw our $T(z)$ in blue, and we draw the approximation $0.6573 - 0.8936 \sqrt{1 - \frac{z}{0.27695}}$ in orange so you can see how well they line up! But now from here we can run exactly the same argument as in the previous post! We compute $t_n = \frac{1}{2\pi i} \oint \frac{T}{z^{n+1}} \ \mathrm{d}z$, along a keyhole contour around the singular point $z=0.27695$ with a branch cut along the real axis. The brunt of this integral comes from the cutout near the singular point, where $T$ is well approximated by $0.6573 - 0.8936 \sqrt{1 - \frac{z}{0.27695}}$ so that Again, for more details about exactly what this keyhole contour is and how you estimate this integral along it, see the main post. Let’s go ahead and call it here! My actual talk was slightly longer than this, since I also sketched a proof of Dirichlet’s Theorem following Varilly’s notes on the subject, but there’s no sense in me writing that up since those notes are already so good! Plus it’s getting late and I want to go to bed, haha. As always, here’s a copy of my title and abstract. Unfortunately I don’t have any slides or recordings today, but I’m giving another talk at WiSCons in Madison next week and I should have slides for that. I’m also hoping to finish a sister blog post for that talk where I do more example computations in more detail than I could possibly do in a 20 minute talk. Lots of writing to do this week! Take care all, stay safe, and I can’t wait to talk soon ^_^ Counting is Hard. Complex Analysis is Easy. Don’t you miss being a kid, when your mom would ask you to count how many of your alphabet fridge magnets were both red and vowels? When you saw the answer was “2”, you felt such accomplishment…. But counting has only gotten harder since then, and now if you want to count how many objects satisfy some properties (say, being both red and vowels) it can be borderline impossible! In this talk we’ll show how you can solve counting problems by doing complex analysis instead. First we’ll count the number of trees of a certain shape, then (given time) we’ll count how many prime numbers are of a (different) certain shape. In the main post we used puiseux series for this, and we had to essentially guess which branch was correct. Now we see how the geometry of the situation tells us that we have to choose the negative branch of the square root! After all, this is the one that locally agrees with the rest of the graph of $T$! ↩
Are GLP-1 drugs causing excess muscle loss compared to non-pharmacological weight loss?