I have a new garden

I have a new garden. You can visit it at my “homepage” (how long since I’ve used that word!) on http://dealmeida.net/. And when visiting the page you will plant a flower.

The garden is actually inspired in an old project I did back in 2004, when I moved to Holland. I was impressed by the weather in Utrecht, so I wrote a Python script that grabbed the local temperature and used it to evolve a garden of cellular automata flowers:

A screenshot of my old garden

The idea was based on James Lovelock’s Daisyworld model, and it had two interesting consequences: first that it acted as a fuzzy thermometers, since darker flowers would dominate in cold weather, and lighter flowers would prevail in warmer weather; second, it had the emergent property of acting like a greenhouse, stabilizing the temperature so that it was warmer in the garden in winter, and colder during summer.

This week I created a new garden for my homepage. Instead of using Python I create a page-sized canvas element, and I draw the flowers using Javascript. The flowers are stored in a JSONStore database, which stores the flowers' DNA and their location on the canvas. The DNA has 7 genes, stored as 8 bytes, that describe each flower’s shape and color.

When a person visits the page a new flower is added. The new flower is created by randomly selecting two parents, weighting the selection by the efficiency of each flower. The efficiency is a function of the temperature and humidity at Cachoeira Paulista, where I live. As in my old model, darker flowers do better in colder weather, while the opposite is true for lighter flowers. This time I also use humidity: drier weather favors “spikier” flowers, inspired by how leaves tend to become pointier in drier regions in order to avoid losing too much water. I’m not sure of how scientific this is, but it gives more variability to the evolution of the garden.

The new flower is drawn first with a white outline, so you can see it. It should stay there for a while; flowers are only killed when their efficiency is below zero, which happens for temperatures outside the range of 5 and 40 degrees C. There’s also a limit of 200 flowers. When the limit is exceeded flowers are randomly removed based on their efficiency. This means your flower should stay for a while.

Back from PythonBrasil [7]

PythonBrasil [7]

I just left São Paulo today, after 3 days at the PythonBrasil [7] meeting (which should really be called PythonBrasil [6], since it's the seventh event!). The meeting was great, as always — I met good friends, made some new ones, talked to *very* smart people, showed my JSONStore module and even made a presentation of the Spanish Inquisition sketch! =D

I also wanted to visit the Garoa Hacker Club, but today I had lunch with my formed PhD advisor, Rein, and his wife Claudia. After that I got a ride to Ubatuba, where we start a Summer School Continent–Ocean interaction tomorrow.

Marrrrrrkov!

This is a solution to this problem:

A drunken sailor returns to his ship via a plank 15 paces long and 7 paces wide. With each step he has an equal chance of stepping forward, left, right, or standing still. What is the probability that he returns safely to his ship?

The article shows two different solutions, one using a Monte Carlo approach and the other, Markov chains. The Monte Carlo approach is pretty trivial; here’s how I did it using Python:

def walk():
    pos = array([4, 0])
    while 1:
        if pos[1] == 16:
            return True
        elif not 0 < pos[0] < 8:
            return False

        pos += choice([
                array([ 0, 1]),  # forward
                array([ 1, 0]),  # right
                array([-1, 0]),  # left
                array([ 0, 0]),  # still
                ])

This is our random walk. We keep updating the position of the sailor until he either reaches the ship of falls into water. We can estimate the chance that the sailor will reach the boat by running this function several times and counting the percentage that returns True:

REALIZATIONS = 10000
successes = 0
for i in range(REALIZATIONS):
    if walk(): successes += 1
print float(successes)/REALIZATIONS

For 10 thousand realizations I get a probability of 12% that the sailor can cross the plank. But I’m more interested in the Markov chain solution. The idea behind this solution is to create a matrix of the probabilities of going from a place A to a point B. In order to do this I create an array of shape (7+2, 15+1, 7+2, 15+1). This array includes two additional side points, for water, and one additional point along the plank, representing the boat. In this array, the value at the position (i0, j0, i1, j1) represents the probability of a person at point (i0, j0) going to the position (i1, j1). We start with an empty arrays of zeros:

WIDTH = 7
LENGTH = 15
markov = zeros((WIDTH+2, LENGTH+1, WIDTH+2, LENGTH+1), 'f')

Now let’s set the probabilities for the plank:

for i in range(1, WIDTH+1):
    for j in range(LENGTH):
        markov[i, j, i, j+1] = 0.25  # forward
        markov[i, j, i+1, j] = 0.25  # right
        markov[i, j, i-1, j] = 0.25  # left
        markov[i, j, i, j]   = 0.25  # still

So, if the sailor is in the point (i, j) inside the plank it has a 25% chance of moving to point (i+1, j), ie, to the right. We also set the probabilities for when the sailor is on the water; in this case, he will stay there:

# when in water, stay
for j in range(LENGTH+1):
    markov[0, j, 0, j] = 1
    markov[WIDTH+1, j, WIDTH+1, j] = 1

And we do the same when he reaches the boat:

# when in the ship, stay
for i in range(WIDTH+2):
    markov[i, LENGTH, i, LENGTH] = 1

We also reshape our array, making it 2D. It will still keep the probabilistic correspondence between point A and B, but now our space dimension has been turned into 1D:

markov.shape = ((WIDTH+2)*(LENGTH+1), (WIDTH+2)*(LENGTH+1))

The rest now is easy. The transition matrix we just built has the nice property that it represents the chance of going from one point to the other, and if we keep multiplying it by itself n times we have the chance of reaching point B after n steps from point A. So we just need to convert our array into a matrix (there’s a difference in Numpy) and take the power to a resonable number of steps:

MAXSTEPS = 200
result = matrix(markov)**MAXSTEPS
result = array(result).reshape(WIDTH+2, LENGTH+1, WIDTH+2, LENGTH+1)

What we want is the chance of a sailor leaving from point (4, 0) to reach the boat at any point in (i, 15). We can get this easily:

print sum(result[4, 0, :, 15])

And the result is 15%. Pretty cool.