Category Archives: Good Math

The Surprises Never Eend: The Ulam Spiral of Primes

One of the things that’s endlessly fascinating to me about math and
science is the way that, no matter how much we know, we’re constantly
discovering more things that we don’t know. Even in simple, fundamental
areas, there’s always a surprise waiting just around the corner.

A great example of this is something called the Ulam spiral,
named after Stanislaw Ulam, who first noticed it. Take a sheet of graph paper.
Put “1” in some square. Then, spiral out from there, putting one number in
each square. Then circle each of the prime numbers. Like the following:

ulam.png

If you do that for a while – and zoom out, so that you can’t see the numbers,
but just dots for each circled number, what you’ll get will look something like
this:

ulam200.png

That’s the Ulam spiral filling a 200×200 grid. Look at how many diagonal
line segments you get! And look how many diagonal line segments occur along
the same lines! Why do the prime numbers tend to occur in clusters
along the diagonals of this spiral? I don’t have a clue. Nor, to my knowledge,
does anyone else!

And it gets even a bit more surprising: you don’t need to start
the spiral with one. You can start it with one hundred, or seventeen thousand. If
you draw the spiral, you’ll find primes along diagonals.

Intuitions about it are almost certainly wrong. For example, when I first
thought about it, I tried to find a numerical pattern around the diagonals.
There are lots of patterns. For example, one of the simplest ones is
that an awful lot of primes occur along the set of lines
f(n) = 4n2+n+c, for a variety of values of b and c. But what does
that tell you? Alas, not much. Why do so many primes occur along
those families of lines?

You can make the effect even more prominent by making the spiral
a bit more regular. Instead of graph paper, draw an archimedean spiral – that
is, the classic circular spiral path. Each revolution around the circle, evenly
distribute the numbers up to the next perfect square. So the first spiral will have 2, 3, 4;
the next will have 5, 6, 7, 8, 9. And so on. What you’ll wind up with is
called the Sack’s spiral, which looks like this:

Sacks spiral.png

This has been cited by some religious folks as being a proof of the
existence of God. Personally, I think that that’s silly; my personal
belief is that even a deity can’t change the way the numbers work: the
nature of the numbers and how they behave in inescapable. Even a deity who
could create the universe couldn’t make 4 a prime number.

Even just working with simple integers, and as simple a concept of
the prime numbers, there are still surprises waiting for us.

Finger Trees Done Right (I hope)

A while ago, I wrote a couple of posts that claimed to talk about finger trees. Unfortunately, I really botched it. I’d read a bunch of data structure papers, and managed to get myself thoroughly scrambled. What I wrote about was distantly related to finger trees, and it was useful to help understand how fingertrees work – but it was not, in any way, shape, or form, actually a description of fingertrees. Since then, I’ve been meaning to write a proper post explaining finger trees – but with the work on my book, and with chaos at work, I just haven’t had the time. This time, in order to do my damnedest to make sure that I don’t screw it up again, I’m basically go to describe finger trees over a couple of posts by walking through the best finger-tree paper that I could find. The paper is “Finger Trees: a simple general-purpose data structure”, by Ralf Hinze and Ross Patterson. This might by the paper that introduced the structure, but I’m not sure.

The point of finger trees is pretty simple. It’s very similar to the point of zippers. Programming in functional languages is terrific. As I’ve described before, there are a lot of advantages to writing functional code. But there are also a lot of places where a naive implementation of an algorithm using a functional data structure is dreadfully inefficient. Functional code may be prettier, more maintainable, and more reusable – but imperative code is frequently much more efficient. When you’re doing an operation that, conceptually, modifies a piece of a complex data structure, then functional code can really suck. Finger trees give you a way around that – for many common updatabale data structures, you can build finger-tree versions that are very close to or fully as good as imperative, updating structures.

Continue reading

Code in the Cloud: My Book Beta is Available!

As I’ve mentioned before, I’ve been spending a lot of time working on a book.
Initially, I was working on a book made up of a collection of material from blog posts;
along the way, I got diverted, and ended up writing a book about cloud computing using
Google’s AppEngine tools. The book isn’t finished, but my publisher, the Pragmatic Programmers,
have a program that they call beta books. Once a book is roughly 60% done, you
can buy it at a discount, and download drafts electronically immediately. As more sections
get done, you can download each new version. And when the book is finally finished, you
get a final copy.

We released the first beta version of the book today. You can look at
excerpts, or buy a copy, by going to
the books page
at Pragmatic’s website.

If you’re interested in what cloud computing is, and how to build cloud applications – or if
you just feel like doing something to support you friendly local math-blogger – please take
a look, and consider getting a copy. I’m not going to harp about the book a lot on the blog; you’re
not going to see a ton of posts that are thinly veiled advertisements, or updates tracking
sales, or anything like that. If there’s something that I would have written about anyway,
and it’s appropriate to mention the book, then I’ll feel free to mention it, but I won’t
waste your time hyping it.

In other news, here’s the main reason that things have been dead on this blog since
the weekend:

photo.jpeg

That’s the view from my driveway as of monday morning. Over the weekend,
we had one of the worst windstorms to hit New York in about thirty years. That
mess is two oak trees, each close to 2 meters in diameter, which came down on
our street on saturday. (If you look closely towards the right hand side, you
can see the remains of my neighbors car.) The telephone pole in the picture
was snapped not by getting hit by a tree, but simply by the wind. Since that
pole had our electrical transformer, and those trees took out the wiring that
fed that transformer, we are (obviously) without electricity, internet, or
(most importantly) heat.

Con-ed is promising to restore our electricity by friday. I’m not holding my
breath.

Anyway, back to the happy stuff. The book exists in electronic form! Buy
a copy for yourself, your friends, your neighbors, and your dog! We’ve got lots
of wonderful new expenses to deal with recovering from that storm! 🙂

Animal Experimentation and Simulation

In my post yesterday, I briefly mentioned the problem with simulations
as a replacement for animal testing. But I’ve gotten a couple of self-righteous
emails from people criticizing that: they’ve all argued that given the
quantity of computational resources available to us today, of course
we can do all of our research using simulations. I’ll quote a typical example
from the one person who actually posted a comment along these lines:

This doesn’t in any way reduce the importance of informing people about
the alternatives to animal testing. It strikes me as odd that the author of
the blogpost is a computer scientist, yet seems uninformed about the fact,
that the most interesting alternatives to animal testing are coming from that
field. Simulation of very complex systems is around the corner, especially
since computing power is becoming cheaper all the time.

That said, I also do think it’s OK to voice opposition to animal testing,
because there *are* alternatives. People who ignore the alternatives seem to
have other issues going on, for example a sort of pleasure at the idea of
power over others – also nonhumans.

I’ll briefly comment on the obnoxious self-righteousness of this idiot.
They started off their comment with the suggestion that the people who are
harassing Dr. Ringach’s children aren’t really animal rights
protestors; they’re people paid by opponents of the AR movement in order to
discredit it. And then goes on to claim that anyone who doesn’t see the
obvious alternatives to animal testing really do it because they
get their rocks off torturing poor defenseless animals.

Dumbass.

Anyway: my actual argument is below the fold.

Continue reading

The End of Defining Chaos: Mixing it all together

The last major property of a chaotic system is topological mixing. You can
think of mixing as being, in some sense, the opposite of the dense periodic
orbits property. Intuitively, the dense orbits tell you that things that are
arbitrarily close together for arbitrarily long periods of time can have
vastly different behaviors. Mixing means that things that are arbitrarily far
apart will eventually wind up looking nearly the same – if only for a little
while.

Let’s start with a formal definition.

As you can guess from the name, topological mixing is a property defined
using topology. In topology, we generally define things in terms of open sets
and neighborhoods. I don’t want to go too deep into detail – but an
open set captures the notion of a collection of points with a well-defined boundary
that is not part of the set. So, for example, in a simple 2-dimensional
euclidean space, the contents of a circle are one kind of open set; the boundary is
the circle itself.

Now, imagine that you’ve got a dynamical system whose phase space is
defined as a topological space. The system is defined by a recurrence
relation: sn+1 = f(sn). Now, suppose that in this
dynamical system, we can expand the state function so that it works as a
continous map over sets. So if we have an open set of points A, then we can
talk about the set of points that that open set will be mapped to by f. Speaking
informally, we can say that if B=f(A), B is the space of points that could be mapped
to by points in A.

The phase space is topologically mixing if, for any two open spaces A
and B, there is some integer N such that fN(A) ∩ B &neq; 0. That is, no matter where you start,
no matter how far away you are from some other point, eventually,
you’ll wind up arbitrarily close to that other point. (Note: I originally left out the quantification of N.)

Now, let’s put that together with the other basic properties of
a chaotic system. In informal terms, what it means is:

  1. Exactly where you start has a huge impact on where you’ll end up.
  2. No matter how close together two points are, no matter how long their
    trajectories are close together, at any time, they can
    suddenly go in completely different directions.
  3. No matter how far apart two points are, no matter how long
    their trajectories stay far apart, eventually, they’ll
    wind up in almost the same place.

All of this is a fancy and complicated way of saying that in a chaotic
system, you never know what the heck is going to happen. No matter how long
the system’s behavior appears to be perfectly stable and predictable, there’s
absolutely no guarantee that the behavior is actually in a periodic orbit. It
could, at any time, diverge into something totally unpredictable.

Anyway – I’ve spent more than enough time on the definition; I think I’ve
pretty well driven this into the ground. But I hope that in doing so, I’ve
gotten across the degree of unpredictability of a chaotic system. There’s a
reason that chaotic systems are considered to be a nightmare for numerical
analysis of dynamical systems. It means that the most miniscule errors
in any aspect of anything will produce drastic divergence.

So when you build a model of a chaotic system, you know that it’s going to
break down. No matter how careful you are, even if you had impossibly perfect measurements,
just the nature of numerical computation – the limited precision and roundoff
errors of numerical representations – mean that your model is going to break.

From here, I’m going to move from defining things to analyzing things. Chaotic
systems are a nightmare for modeling. But there are ways of recognizing when
a systems behavior is going to become chaotic. What I’m going to do next is look
at how we can describe and analyze systems in order to recognize and predict
when they’ll become chaotic.

More about Dense Periodic Orbits

Based on a recommendation from a commenter, I’ve gotten another book on Chaos theory, and it’s frankly vastly better than the two I was using before.

Anyway, I want to first return to dense periodic orbits in chaotic systems, which is what I discussed in the previous chaos theory post. There’s a glaring hole in that post. I didn’t so much get it wrong as I did miss the fundamental point.

If you recall, the basic definition of a chaotic system is a dynamic system with a specific set of properties:

  1. Sensitivity to initial conditions,
  2. Dense periodic orbits, and
  3. topological mixing

The property that we want to focus on right now is the
dense periodic orbits.

In a dynamical system, an orbit isn’t what we typically think of as orbits. If you look at all of the paths through the phase space of a system, you can divide it into partitions. If the system enters a state in any partition, then every state that it ever goes through will be part of the same partition. Each of those partitions is called an orbit. What makes this so different from our intuitive notion of orbits is that the intuitive orbit repeats. In a dynamical system, an orbit is just a set of points, paths through the phase space of the system. It may never do anything remotely close to repeating – but it’s an orbit. For example, if I describe a system which is the state of an object floating down a river, the path that it takes is an orbit. But it obviously can’t repeat – the object isn’t going to go back up to the beginning of the river.

An orbit that repeats is called a periodic orbit. So our intuitive notion of orbits is really about periodic orbits.

Periodic orbits are tightly connected to chaotic systems. In a chaotic system, one of the basic properties is a particular kind of unpredictability. Sensitivity to initial conditions is what most people think of – but the orbital property is actually more interesting.

A chaotic system has dense periodic orbits. Now, what does that mean? I explained it once before, but I managed to miss one of the most interesting bits of it.

The points of a chaotic system are dense around the periodic orbits. In mathematical terms, that means that every point in the attractor for the chaotic system is arbitrarily close to some point on a periodic orbit. Pick a point in the chaotic attractor, and pick a distance greater than zero. No matter how small that distance is, there’s a periodic orbit within that distance of the point in the attractor.

The last property of the chaotic system – the one which makes the dense periodic orbits so interesting – is topological mixing. I’m not going to go into detail about it here – that’s for the next post. But what happens when you combine topological mixing with the density around the periodic orbits is that you get an amazing kind of unpredictability.

You can find stable states of the system, where everything just cycles through an orbit. And you can find an instance of the system that appears to be in that stable state. But in fact, virtually all of the time, you’ll be wrong. The most minuscule deviation, any unmeasurably small difference between the theoretical stable state and the actual state of the system – and at some point, your behavior will diverge. You could stay close to the stable state for a very long time – and then, whammo! the system will do something that appears to be completely insane.

What the density around periodic orbits means is that even though most of the points in the phase space aren’t part of periodic orbits, you can’t possibly distinguish them from the ones that are. A point that appears to be stable probably isn’t. And the difference between real stability and apparent stability is unmeasurably, indistinguishably small. It’s not just the initial conditions of the system that are sensitive. The entire system is sensitive. Even if you managed to get it into a stable state, the slightest perturbation, the tiniest change, could cause a drastic change at some unpredictable time in the future.

This is the real butterfly effect. A butterfly flaps its wings – and the tiny movement of air caused by that pushes the weather system that tiny bit off of a stable orbit, and winds up causing the diversion that leads to a hurricane. The tiniest change at any time can completely blow up.

It also gives us a handle on another property of chaotic systems as models of real phenomena: we can’t reverse them. Knowing the measured state of a chaotic system, we cannot tell how it got there. Even if it appears to be in a stable state, if it’s part of a chaotic system, it could have just “swung in” the chaotic state from something very different. Or it could have been in what appeared to be a stable state for a long time, and then suddenly diverge. Density effectively means that we can’t distinguish the stable case from either of the two chaotic cases.

Zippers: Making Functional "Updates" Efficient

In the Haskell stuff, I was planning on moving on to some monad-related
stuff. But I had a reader write in, and ask me to write another
post on data structures, focusing on a structured called a
zipper.

A zipper is a remarkably clever idea. It’s not really a single data
structure, but rather a way of building data structures in functional
languages. The first mention of the structure seems to be a paper
by Gerard Huet in 1997
, but as he says in the paper, it’s likely that this was
used before his paper in functional code — but no one thought to formalize it
and write it up. (In the original version of this post, I said the name of the guy who first wrote about zippers was “Carl Huet”. I have absolutely no idea where that came from – I literally had his paper on my lap as I wrote this post, and I still managed to screwed up his name. My apologies!)

It also happens that zippers are one of the rare cases of data structures
where I think it’s not necessarily clearer to show code. The concept of
a zipper is very simple and elegant – but when you see a zippered tree
written out as a sequence of type constructors, it’s confusing, rather
than clarifying.

Continue reading

What is math?

File:Braque.woman.400pix.jpeg

I’ve got a bunch of stuff queued up to be posted over the next couple of days. It’s
been the sort of week where I’ve gotten lots of interesting links from
readers, but I haven’t had time to finish anything!

I thought I’d start off with something short but positive. A reader sent
me a link to a post on Reddit, with the following question:

Throughout elementary and high school, I got awful marks in math. I always
assumed I was just stupid in that way, which is perfectly possible. I also
hated my teacher, so that didn’t help. A friend of mine got his PhD in math
from Harvard before he was 25 (he is in his 40’s now) I was surprised the
other week when I learned he isn’t particularly good at basic arithmetic etc.
He said that’s not really what math is about. So my question is really for
math fans/pros. What is math, really? I hear people throwing around phrases
like “elegant” and “artistic” regarding math. I don’t understand how this can
be. To me, math is add, subtract, etc. It is purely functional. Is there
something you can compare it to so that I can understand?

This hits on one of my personal pet peeves. Math really is a beautiful
thing, but the way that math is taught turns it into something
mechanistic, difficult, and boring. The person who posted this question
is a typical example of a victim of lousy math education.

So what is math? It’s really a great question, and not particularly
an easy one to answer.

Continue reading

Advanced Haskell Data Structures: Red-Black Trees

unbalanced-trees.jpg

So, we’ve built up some pretty nifty binary trees – we can use the binary tree both as the basis of an implementation of a set, or as an implementation of a dictionary. But our implementation has had one major problem: it’s got absolutely no way to maintain balance.

What that means is that depending on the order in which things are inserted to the tree, we might have excellent performance, or we might be no better than a linear list. For example, look at these trees. As you can see, a tree with the same values can wind up quite different. In a good insert order, you can wind up with a nicely balanced tree: the minimum distance from root to leaf is 3; the maximum is 4. On the other hand, take the same values, and insert them in a different order and you get a rotten tree; the minimum distance from root to leaf is 1, and the maximum is 7. So depending on luck, you can get a tree that gives you good performance, or one that ends up giving you no better than a plain old list. Playing with a bit of randomization can often give you reasonably good performance on average – but if you’re using a tree, it’s probably because O(n) complexity is just too high. You want the O(lg n) complexity that you’ll get from a binary tree – and not just sometimes.

To fix that, you need to change the structure a bit, so that as you insert things, the tree stays balanced. There are several different approaches to how you can do this. The one that we’re going to look at is based on labeling nodes in ways that allow you to very easily detect when a serious imbalance is developing, and then re-arrange the tree to re-balance it. There are two major version of this, called the AVL tree, and the red-black tree. We’re going to look at the red-black. Building a red-black tree is as much a lesson in data structures as it is in Haskell, but along with learning about the structure, we’ll see a lot about how to write code in Haskell, and particularly about how to use pattern-matching for complex structures.

Continue reading

Creating User-Defined Types in Haskell

  • (This is an edited repost of one of the posts from the earlier
    version of my Haskell tutorial.)
  • (This file is a literate haskell script. If you save it
    as a file whose name ends in “.lhs”, it’s actually loadable and
    runnable in GHCI or Hugs.)

Like any other modern programming language, Haskell has excellent support
for building user-defined data types. In fact, even though Haskell is very
much not object-oriented, most Haskell programs end up being centered
around the design and implementation of data structures, using constructions
called classes and instances.

In this post, we’re going to start looking at how you implement data types
in Haskell. What I’m going to do is start by showing you how to implement a
simple binary search tree. I’ll start with a very simple version, and then
build up from there.

Continue reading