You can buy high-quality prints from Imagekind. (If you order soon you should have them before Christmas! =) I’m really quite happy with imagekind, the print quality is fantastic and the prices seem reasonable. You can choose among different sizes—I suggest 32"x20" ($26 on the default matte paper, + shipping), but the next smaller size (24"x15", $17) is probably OK too.
If you have ideas for variant posters you’d like to see, let me know (though I probably won’t be able to do anything until after the new year).
Note that Jeremy also has a variety of factorization diagram posters for sale.
For more information, including links to the source code, a high-resolution PNG, and other things, see this factorization diagrams page.
“But”, I hear you protest, “Pi Day was ages ago!” Ah, but I didn’t say Pi Day, I said PIE Day. To clarify:
(Actually, I’m only going to begin explaining it today; it’s getting too long for a single blog post!) In any case, the overall goal is to finish up my long-languishing series on a combinatorial proof of a curious identity (though this post is self-contained so there’s no need to go back and reread that stuff yet). The biggest missing piece of the pie is… well, PIE! I’ve been having trouble figuring out a good way to explain it in sufficient generality—it’s one of those deceptively simple-seeming things which actually hides a lot of depth. Like a puddle which turns out to be a giant pothole. (Except more fun.)
In a previous post (now long ago) I asked for some advice and got a lot of great comments—if my explanation doesn’t make sense you can try reading some of those!
So, what’s the Principle of Inclusion-Exclusion all about? The basic purpose is to compute the total size of some overlapping sets.
To start out, here is a diagram representing some non-overlapping sets.
Each set is represented by a colored circle and labelled with the number of elements it contains. In this case, there are 25 people who like bobsledding (the red circle), six people who like doing laundry (the blue circle), and 99 people who like math (the green circle). The circles do not overlap at all, meaning that none of the people who like math also like laundry or bobsledding; none of the people who like doing laundry also like bobsledding or math; and so on. So, how many people are there in total? Well, that’s easy—just add the three numbers! In this case we get 130.
Now, consider this Venn diagram which shows three overlapping sets.
Again, I’ve labelled each region with the number of elements it contains. So there are two people who like bobsledding but not math or laundry; there are three people who like bobsledding and math but not laundry; there is one person who likes all three; and so on. It’s still easy to count the total number of elements: just add up all the numbers again (I get 14).
So what’s the catch?
The catch is that in many situations, we do not know the number of elements in each region! More typically, we know something like:
The total number of elements in each set. Say, we might know that there are 7 people who like bobsledding in total, but have no idea how many of those 7 like math or laundry; and similarly for the other two sets.
The total number of elements in each combination of sets. For example, we might know there are two people who like bobsledding and laundry—but we don’t know whether either of them likes math.
This is illustrated below for another instance of our ongoing example. The top row shows that there are sixteen people who like bobsledding in total, eleven who like laundry in total, and eighteen who like math—but again, these are total counts which tell us nothing about the overlap between the sets. (I’ve put each diagram in a box to emphasize that they are now independent—unlike in the first diagram in this post, having three separate circles does not imply that the circles are necessarily disjoint.) So is probably too many because we would be counting some people multiple times. The next row shows all the intersections of two sets: there are three people who like bobsledding and laundry (who may or may not like math), eight people who like bobsledding and math; and six people who like laundry and math. Finally, there is one person who likes all three.
The question is, how can we deduce the total number of people, starting from this information?
Well, give it a try yourself! Once you have figured that out, think about what would happen if we added a fourth category (say, people who like gelato), or a fifth, or… In a future post I will explain more about the general principle.
The deadline for submitting a paper has passed, but the Workshop on Functional Art, Music, Modeling and Design (FARM 2013) is currently seeking proposals for 10-20 minute demonstrations to be given during the workshop. For example, a demonstration could consist of a short tutorial, an exhibition of some work, or even a livecoding performance. Slots for demonstrations will be shorter than slots for accepted papers, and will not be published as part of the formal proceedings, but can be a great way to show off interesting work and get feedback from other workshop participants. A demonstration slot could be a particularly good way to get feedback on work-in-progress.
A demo proposal should consist of a 1 page abstract, in PDF format, explaining the proposed content of the demonstration and why it would be of interest to the attendees of FARM. Proposals will be judged on interest and relevance to the stated goals and themes of the workshop.
Submissions can be made via EasyChair.
For today though, just a link (I don’t remember where I first saw it):
This is a super-fun game with a very simple interface, where you are challenged to construct various things (polygons, circle packings, etc.) using only straightedge and compass, in the finest tradition of the ancient Greeks. It’s like eighth grade geometry class all over again, except fun. I’ve completed 26 of the 40 challenges so far — how many can you do?
How about these? (Same points, different lines.)
Or these?
Here are some more. The first three groups in the grid below correspond to the pictures already shown above.
Can you figure out what’s going on? The source code for the animation is here; I was inspired by Jason Davies’ visualization which was in turn inspired by this.
A few weeks ago, Paul Salomon posted a really beautiful work of mathematical art on his blog, Lost In Recursion:
Stars of the Mind’s Sky, by Paul Salomon
He included a precise mathematical description of the image, and I naturally wondered how difficult it would be to replicate using the diagrams framework which I wrote about previously.
The answer: not hard! All told it is only about 30 lines of code, give or take. So I decided to exhibit it here, both as a way of explaining the cool math behind Paul’s image, and as a way of showing off the power of diagrams to do this sort of visualization and mathematical art.
This post is literate Haskell—you should be able to copy and paste the contents of this post into a file with an .lhs
extension, and run and play around with it yourself. First, some requisite imports and such:
> {-# LANGUAGE NoMonomorphismRestriction #-}
>
> module SOTMS where
>
> import Control.Arrow ((***))
> import Data.Colour.SRGB
> import Data.Colour.RGBSpace
> import Data.Colour.RGBSpace.HSV
> import Diagrams.Backend.Cairo.CmdLine
> import Diagrams.Prelude
The image is primarily composed of a bunch of star polygons, the figures you get when you take points evenly spaced around a circle and connect every th point. For example, here’s what we get when we pick and :
I’ve numbered the vertices to make it easier to see how vertex is always connected to vertex (modulo 12) by a line segment. Vertex is connected to , which is connected to , which is connected to , and so on.
In this example, we get one continuous polygonal path which cycles through all the vertices. But sometimes we get several disjoint paths. For example, below is what we get with and . I’ve used distinct colors to make it easy to see the three separate squares:
If you connect every third point out of twelve, you come back to where you started after hitting only four points, so three separate square paths are needed to connect all the points. Given values for and , can you say in general how many distinct paths result? Here are a few more examples to fuel your investigations:
In fact, the number of separate paths needed to draw a given star polygon is how Paul chooses the color: red for star polygons that are one continuous path, yellow for two paths, blue for a lot (that is, 24), and shading gradually from yellow to green to blue for numbers in between. (Now that you know this, you might want to go back and study the image again, looking for patterns!)
There’s one thing left: what about ? This is a sort of “degenerate” star polygon where we don’t connect any of the points. Paul chose to draw those using just dots for the vertices, like this:
In Paul’s image you can see these going in a straight line from the center to the top, though it’s a little hard to see what’s going on since they all overlap with each other.
So, let’s see some code already! First, a simple function to generate the kind of regular polygons we want:
> -- Make a regular polygon with n sides and radius r, oriented with
> -- one vertex pointing in the positive y direction.
> regP n r = polygon with { polyType = PolyRegular n r
> , polyOrient = NoOrient
> }
> # rotateBy (1/4)
Now, we define a function mkStar
which takes and as inputs and draws a -star polygon, coloring it according to Paul’s color scheme:
> -- If q = 0, draw a bunch of dots at the vertices of a regular polygon
> mkStar n 0 = decoratePath (regP n 1) (repeat (circle 0.1 # lw 0))
> # fc (colorByNumber n)
>
> -- Otherwise draw a star polygon
> mkStar n skip = let p = star (StarSkip skip) (regP n 1)
> numPaths = length . pathTrails $ p
> in
> p # stroke # lw 0.08 # lc (colorByNumber numPaths)
Incidentally, the coloring scheme was the only part that wasn’t specified in Paul’s post, so I hacked something together using trial and error and the “eyedropper” tool in GIMP. I also have to go to a bit of trouble to blend from yellow to blue in HSV space, so it looks like this:
and not in RGB space, which looks like this:
You need not pay too much attention to this code, but I’m including it here for completeness. (I plan to soon include some extra tools in diagrams for helping manipulate colors, which would make this a lot easier to accomplish.)
> paulRed = sRGB24 0xDA 0x22 0x22
> paulBlue = sRGB24 0x4C 0x89 0xC0
> paulYellow = sRGB24 0xD1 0xB3 0x41
>
> colorByNumber 1 = paulRed
> colorByNumber c = hsvBlend (min 1 ((fromIntegral c - 2)/10))
> paulBlue paulYellow
>
> hsvBlend t c1 c2 = uncurryRGB sRGB . hsv3 $ lerp h2 h1 t
> where
> [h1, h2] = map (hsvView . toSRGB) [c1,c2]
> fst3 (x,_,_) = x
> hsv3 (h,s,v) = hsv h s v
The final colors don’t look exactly like Paul’s original image but they’re close enough.
Now that we can generate individual star polygons we have to put them together into “orbits”. All the star polygons in a particular “orbit” (that is, at a particular distance from the center) have the same value of (that is, the same number of vertices). The star with is at the top, and then the stars for other values of progress in order around the orbit. (Quick quiz: does the value of increase going clockwise, or counterclockwise?)
Making the stars around a particular orbit is easy: we create all the stars (map (mkStar n) [0..]
will make one star for each value of ), and then place them at the vertices of a radius- regular -gon using decoratePath
.
> stars n = decoratePath
> (regP n (fromIntegral n - 1))
> (map (mkStar n) [0..])
For example, here are the outputs for stars 6
and stars 7
:
Finally, each orbit is shown with a faint circle, so we make an orbit
function which returns the stars and associated circle together:
> orbit n = ( stars n
> , circle (fromIntegral n - 1)
> # lc (blend 0.95 white black)
> # lw 0.08
> )
Finally, we generate the orbits from to and draw them all! Note that we have to draw all the orbit circles first and then the stars, because we don’t want any of the orbit circles getting drawn on top of the stars. This is what the funny business with unzip
, uncurry atop
, etc. is doing.
> starsOfTheMindsSky = uncurry atop
> . (mconcat***mconcat)
> . unzip
> . reverse
> . map orbit
> $ [2..24]
>
> main = defaultMain (starsOfTheMindsSky # centerXY # pad 1.1)
And here’s Paul’s original version for comparison. Pretty close!
I love all the different patterns you can see in this work of art—close inspection and thinking really pays off as you discover more and more interesting structure. For example, this could really make a wonderful activity for a class—you could buy a print from Paul, put it up, and see what the students find!
Incidentally, I have also really been enjoying Paul’s “imbalance problems”, here, here, and here—go check them out!
Guesstimation 2.0: Solving Today’s Problems on the Back of a Napkin
Lawrence Weinstein
I got a review copy of this book, and initially decided I wasn’t going to review it—I hate those sorts of consulting-company-interview estimation problems, you know, like “what percentage of all the shampoo bottles in the world are in an airplane at this moment” or “how much poop does the San Diego Zoo produce per year” or whatever.
But I picked it up in an idle moment and found myself spending far longer reading it than I had intended. Weinstein is clearly a master estimator, and anyone actually interested in estimation will find a wealth of information here. In addition to working out the solutions to many estimation problems, it also includes lots of advice about estimation in general. But what I enjoyed most is his fun writing style and his quirky choice of questions, like “how much fuel would airlines save if they required all passengers to urinate before boarding?” (as, apparently, Nippon Airways began doing in 2009, though I imagine not actually for fuel efficiency reasons), or “how many bullets does it take to cut down a tree?”, or “which has more mass, the air or the brains in a movie theater?” (Answers: not much, about ten thousand, and the air by a factor of ten.) He is also able to leverage physics to estimate answers to lots of interesting questions that would never show up in an interview, because they’re so difficult to get a handle on otherwise, like “how far away can you detect a candle on a clear, dark night?” So even though I probably won’t end up using any of the techniques myself, it ended up being a fun book nonetheless.
My library is called diagrams (a rather generic but nicely descriptive name). As I hope to show you—and as I hope you can see from the above list of posts—it’s really nice for doing all sorts of visualization, for mathematical exploration, and even for creating art with a mathematical bent. It’s not a program for creating images (like Illustrator or Inkscape), but actually a language for describing what you want your images to look like. What makes it really powerful is that it is actually “embedded” in the Haskell programming language—that is, diagrams programs are Haskell programs, written using stuff provided by the diagrams library. To do simple things with diagrams doesn’t actually require knowing much (if any) Haskell, but the full power of Haskell is available to do more sophisticated things.
So, what can it do? Of course, you can make simple shapes like circles, squares, triangles, pentagons, and so on:
> dia = circle 1
You can also make crazier shapes like stars:
> dia = stroke $ star (StarSkip 2) (pentagon 1)
You can specify attributes like fill and line color, line width, or line dashing:
> dia = myStar # lw 0.05 # lc purple # fc yellow # dashing [0.1,0.05] 0
>
> myStar = stroke $ star (StarSkip 2) (pentagon 1)
Note in the above example how you can make arbitrary definitions and then reuse them.
You can apply transformations like translation, rotation, scaling, and reflection:
> dia = myStar # scale 2
> ||| myStar # rotateBy (1/19)
> ||| myStar # reflectY # translateY 0.5
>
> myStar = stroke $ star (StarSkip 2) (pentagon 1)
You can compose multiple diagrams into one by putting them on top of each other or next to each other:
> dia = (circle 1 <> circle 2 <> circle 3) ||| (square 2 === triangle 2)
You can already create some cool pictures just using the above features—and you don’t really have to know any Haskell! But bringing the power of Haskell into the picture lets us accomplish much more. I’ve written about Haskell several times before; if you want to learn more about it, check out Learn You a Haskell. To whet your appetite, here are a few simple examples.
Haskell has a built-in notion of lists. We can create lists of diagrams and lay them out using operations like hcat
:
> dia = hcat [ circle n # fc blue | n <- [1 .. 5] ]
We can also create shapes from arbitrary paths described using lists of points or vectors, or use paths to position other diagrams:
> myPath = fromVertices [ 0 & 0, 0 & 2, 0.5 & 0.5, 2 & 0 ]
>
> dart = myPath # close # stroke # rotateBy (-1/6)
>
> circles = decoratePath myPath (repeat (circle 0.2))
>
> dia = dart ||| strutX 2 ||| circles # centerXY
We can write recursive functions to generate diagrams:
> sierpinski 1 = triangle 1 # fc black
> sierpinski n = s === (centerX (s ||| s))
> where s = sierpinski (n-1)
>
> dia = sierpinski 6
There are also a ton of existing Haskell libraries available on http://hackage.haskell.org/, and we can seamlessly integrate any of them with diagrams—though I don’t have a good example off the top of my head.
If you’d like to play around with it, here’s what to do. The first step is to install the Haskell Platform. Once you have that installed, open a terminal/command line, and type
cabal install diagrams
then go get a snack because you might have to wait for a while. But after it finishes you should have diagrams installed! Now take a look at the tutorial and the gallery of examples, and start playing!
After you have finished the tutorial (which really only scratches the surface), there is also an extensive user manual which covers (almost) everything you could want to know about diagrams. If you have questions, there is a mailing list and an IRC channel (#diagrams
on freenode). You’re also welcome to leave questions as comments on this post.
Last but not least, if you’re interested in seeing how it’s all implemented, or even contributing to the project, the source code is all available on github.