Main

September 9, 2008

motor sounds

Overheard on #haskell:

newsham: > let motor sounds = sounds "vroom! " in motor cycle

lambdabot: "vroom! vroom! vroom! vroom! vroom! vroom! vroom! vroom! vroom! vroom! vroo...

October 25, 2006

QuickCheck

Yesterday I had to prove that a certain algorithm (for a variation on lambda-lifting) was correct. I wasn't really sure that it was correct, so I took some time and coded it up in Haskell, then picked up enough knowledge of QuickCheck (the manual is more helpful than that raw interface file, but it uses HTML frames to crush your spirit) to write some randomized tests for the algorithm.

At first it caught some good bugs. Then it started succeeding on 100 random tests every time I ran it, so I feel reasonably certain that my algorithm is correct. I played around with the test-data generator to make sure it was generating terms that were deep enough and rich enough & to make sure that it never diverges, creating arbitrarily large terms. QuickCheck is reasonably nice this way.

So here's the Haskell code for my lambda-lifting algorithm, together with the QuickCheck tests (at the bottom). Note that there are some funny things in the syntax that aren't explained; they'll have to stay unexplained until I get done with the actual research I'm doing! Any day now...

February 15, 2006

3-body Problem in Haskell

So last week I implemented the n-body simulation in Erlang with message-passing, as an exploration of one-process-per-particle concurrency. Now I've got it up and running in Haskell, one version using STM and another using just MVars (individual atomic variables).

I found the shared-memory approach to be a more natural style than message-passing for this kind of physical model. My technique is simple: for each time step in simulation time, there is a shared vector of the states of the particles. Each process constantly tries to read the current moment values in sequence (blocking on those particles that are not filled in) and when it has read the whole thing, it performs its next-state computation on those states; it then writes its own next-state into the t+1 shared state vector. I want to reiterate that this technique works only because the processes necessarily work synchronously through simulation time.

Why MVars instead of STM? MVars implement a medium-power concurrency primitive—something like test-and-set—and it was plenty powerful enough to write this application without much fuss. Transactional memory is a significantly higher-level primitive, and its added flexibility wasn't necessary in this case. I'd like to make a loose argument that MVars are generally suffficient for the concurrency that's likely to be found in games.

The STM version works very similarly, but instead of just blocking on an unfilled particle-state, it retries. I believe that this is inefficient, because it's not necessary to repeat the reads that have already been performed at a given timestep: the variables in question are all single-assignment. Also, I suspect that the semantics of STM will lead to lots of retries, the threads tending to swarm around an unfilled variable and all of them retrying the whole transaction together. By contrast, the MVar implementation is efficient in the sense that when a state-variable is filled in, one waiting thread is woken, whose take/put action causes another waiting thread to be woken, etc.

Here's the code, for reference.

Continue reading "3-body Problem in Haskell" »

Crazy MacOS Header Values

For a while now, I've been getting horrible errors whenever I compile some package on my MacOS X machine. Some of the errors were of the form, MAC_OS_X_VERSION_MIN_REQUIRED must be <= MAC_OS_X_VERSION_MAX_ALLOWED. Others were complaining about some precompiled header being out of date.

It turned out that I had an environment variable, MACOSX_DEPLOYMENT_TARGET set to 10.3. I'd set this a long time ago because it alleviated problems that I seemed to have with every Perl module I tried to install.

I unset MACOSX_DEPLOYMENT_TARGET and ran the magical sudo fixprecomps. This fixed it.

December 6, 2005

Removing Duplicates From a Database

You've inserted multiple copies of the same data into a table. You want to get rid of all but one copy of each, and you want to keep the one with the lowest ID. You are using a DMBS with sub-selects, such as PostgreSQL.

You will do this:

select min(wine_id) as canonical from
        wine, (select distinct wine_name from wine) as names
        where wine.wine_name = names.wine_name
        group by names.wine_name;

If that looks right, you will proceed:

delete from wine where wine_id not in
    (select min(wine_id) as canonical from
        wine, (select distinct wine_name from wine) as names
        where wine.wine_name = names.wine_name
        group by names.wine_name);

More generally, if you have a table T with pkey T_ID and the desired data is unique on some column UNIQUE_COLUMN, it's:

select min(T_ID) as canonical from
        T, (select distinct UNIQUE_COLUMN from T) as equiv_classes
        where T.UNIQUE_COLUMN = equiv_classes.UNIQUE_COLUMN
        group by equiv_classes.UNIQUE_COLUMN;