Showing posts with label debugging. Show all posts
Showing posts with label debugging. Show all posts

Wednesday, March 28, 2012

Thinking Backwards

Most of us naturally think of time as an arrow that always points from the past to the future. This is why it might be so difficult for us to think backwards. But, you might ask, why do it? There are reasons, and some of them are not only compelling, but also fundamentally necessary to our way of life.

When I write code, bugs inevitably happen. Bugs are unforeseen problems that result in a crash or some other detectable error. And there I am, in the debugger, looking at the error. So I have to think backwards: given that this happened, what could have caused it? There are only so many possibilities. As we rule them out, whatever is left, however improbable, is the answer. This allows us to catch the problem before it happens, and then we can trace backwards from that problem using the same sequence of deduction. This proceeds backwards in causality until we find the source of the problem: generally the small wrong thing that snowballed into the error or the crash.

Imagine a homicide detective, presented with a dead body. Or a National Transportation Safety Board inspector at a plane crash site. What begins innocuously as debugging becomes a troubleshooting process that can apply to a much more dramatic and even fatal series of events. Events which must be traced back to their root cause so we can figure out how to prevent them from happening again and continue to believe that the world is safe.

But there are creative reasons to think backwards as well. And these are also more than simply exercises for our minds.

Distortion Filters

The filters in PhotoBooth and other Core Image applications often allow us to distort images in interesting ways, like a fun-house mirror.

Once you have learned analytic geometry and also exercise a bit of creativity, it is relatively easy to develop a function that can, for instance, create a bulge in an image.

A circular bulge like the one that makes my nose way too big is a piecewise mathematical function that conceptually takes a point in the source and transforms it into a point in the destination.

To do this, we envision a circle or radius R about the center O of the distortion. Point P may lay inside the circle, and we create a vector V from O to P (which is simply P - O). Note that the vector actually has two components, an x and a y component.

With this in mind, we can build up the distortion as a function based on these things. For instance, we can compute the length of V, and this we will call D. A function that goes from 0 at the origin O to 1 at radius R is simply evaluated by f = D/R. Actually we want f to be 1 outside the circle, so f = min(D/R, 1). And we want f to be a smooth function as well, so we might want f = 3*f*f - 2*f*f*f (in other words three f squared minus two f cubed, which is the smoothstep function).

To create a distortion, we must alter the scale of the image. To increase the size in the center, we want the scale to be greater than 1, and to make the distortion mesh with the undistorted image at the edge, we want the scale to be exactly 1 at radius R. If we call the bulge factor at the center B (B is 1.5 or so at the center of the distorted image above), then we can define the scale of the distortion to be s = B + (1-B)*f. This arranges the scale to be B at the center O and it will smoothly transition to 1 at radius R from O.

And the distortion itself becomes P' = O + s*V. In other words we are scaling the vector displacement from O by the transitioning scale factor s. Since s becomes 1 at radius R and beyond, the image is left undistorted outside the circle of effect.

But wait, we have made a huge error! It turns out that we are evaluating each point of the destination and we need to map back to the source! So we need to think backwards to get to the source point from a point in the destination.

Well, we don't actually need to do that, it turns out. We can fake it by simply making the scale less than one at the center to make the bulge get bigger, and correspondingly make the scale greater than one at the center to make the bulge a pinch instead.

You see, all distortion filters work this way: they must work backwards from a point in the destination to a point in the source. This makes it an exercise in thinking backwards.

Backwards Guitar

When writing the song Not Enough Time (listen to it on soundcloud.com), I decided to make the second round solo an exercise in backwards guitar (which is at 1:29 in the song). To construct this, I had to do several things backwards. First, I had to create a time-reversed version of the song. Then I had to listen to it backwards and jam to the appropriate section of it until I had a basic idea of what I wanted the solo to sound like. This had to mesh with the forwards version, and so I constrained the start and the end notes to what I wanted to hear in the forwards version.

Sounds easy so far, right? Well, continuing, I mapped out the chords of the round, which is repeated twice, and reversed them. I have to say that the chords do sound eerie backwards because cadences are not what we expect them to be.

In fact, listening to and jamming to a backwards song is very unsettling. You feel like you are in a different world while you are doing it.

I recorded three solos in all, and then I reversed them again back into forwards time. Each one was then played with the song in its normal form. One sounded best, so I kept it.

Whew! Thinking backwards takes a lot of preparation in this case, and it's not an easy thing to do.

This all goes to show that thinking backwards is actually more useful than it appears at first thought. And our world is immeasurably better because we can do it.