Monthly Archives: May 2013

Evolutionary Computation, Evolvability, and Python

Funnily enough, an antievolutionist brought a recent article on evolvability to my attention. The paper, “Evolvability Is Inevitable: Increasing Evolvability without the Pressure to Adapt”, by Joel Lehman and Kenneth O. Stanley, is on PLOS One. Here’s their abstract:

Why evolvability appears to have increased over evolutionary time is an important unresolved biological question. Unlike most candidate explanations, this paper proposes that increasing evolvability can result without any pressure to adapt. The insight is that if evolvability is heritable, then an unbiased drifting process across genotypes can still create a distribution of phenotypes biased towards evolvability, because evolvable organisms diffuse more quickly through the space of possible phenotypes. Furthermore, because phenotypic divergence often correlates with founding niches, niche founders may on average be more evolvable, which through population growth provides a genotypic bias towards evolvability. Interestingly, the combination of these two mechanisms can lead to increasing evolvability without any pressure to out-compete other organisms, as demonstrated through experiments with a series of simulated models. Thus rather than from pressure to adapt, evolvability may inevitably result from any drift through genotypic space combined with evolution’s passive tendency to accumulate niches.

The first couple of their simulated models take a very conceptual approach to assessing genetic drift and evolvability. They instantiate organisms as having a genotype of two integer values and a heritable “evolvability”, which is simply the effective per-locus mutation rate. The two integer values are interpreted as points in a plane. (All of the Lehman and Stanley models in this research involve 2D planes.) Each organism chosen for reproduction produces two possibly-mutated offspring for the next generation. Each run begins with a single organism with a genotype of (0,0) and evolvability of 0.05. The population is capped at 40,000 organisms. Each run goes for 3,000 generations. A mutation at a locus causes the value to change by either -1 or +1. A mutation in evolvability occurs at a fixed 0.01 rate and causes a change in an amount drawn uniformly from the interval [-0.005 .. 0.005]. A “niche” is defined as a particular X,Y coordinate. The results from 50 runs are presented where the average evolvability over the population shows no significant change over time. If, though, one calculates the average evolvability per niche and then averages those values, the results show a significant difference toward greater evolvability, even though the simulation is completely premised on genetic drift.

A second version of the model restricts the carrying capacity of each “niche” to five organisms. It shows a more linear trend in upward shift of evolvability evaluated per niche.

As Lehman and Stanley point out, their results indicate that one can see apparent differences in evolvability even when the only evolutionary mechanism at work is genetic drift.

This is a sufficiently interesting result that I was motivated to replicate and extend Lehman and Stanley’s first model. I worked up a genetic algorithm in Python to handle things. I did, though, make the number of loci per organism generic, so I can explore dimensions beyond 2D. I thought this might be interesting, especially at the 2D versus 3D level, given the result that an infinite 2D random walk is expected to visit the origin an infinite number of times, but an infinite 3D random walk is not expected to do so. The dimensionality of real genomes is, of course, much larger than anything considered so far in these models, so at least stepping up from 2D seemed a good thing to address how the model responds to this aspect of scaling-up the problem. I’m currently running scenarios from 2D to 5D. The same sort of thing that Lehman and Stanley obtained for overall average evolvability and within-niche average evolvability comes out. The dimensionality makes a difference for amount of niche exploration that happens in a population under drift. Here is a plot of a set of ten runs for each dimensional scenario, so consider this preliminary while further runs are accumulated.

Speaking of runs, those first ten in each dimension were done using Python 2.7.3. Each run takes just about an hour, based on end-of-run data file timestamps. I had written analysis and comparison routines that used NumPy, Pandas, and matplolib. I got to thinking about that, and decided to try separating out the GA and analytical parts. Doing so gave me a GA in pure Python. I’m running the next block of runs using PyPy on the GA code. That is coming out at about 19 minutes per run for an easy 3x speedup in program execution. Not bad for a nearly painless alteration in my methods. I’m stress-loading a new box I built on an 8-core AMD CPU. I have five processes running PyPy and the GA. I’m getting runs done on that at about 13.4 minutes per run. If the CPU doesn’t melt, this set of runs should be complete by tomorrow.

I’m intending to also do the constrained population size per niche model. I have a thought about yet another variant that could be interesting, which is to start the unconstrained model with an “evolvability” of 0.0 in the first organism. This means that there will be no mutations at all until evolvability mutates to a non-zero value. Given that there is an “absorbing boundary” at 0.0, I expect that there will be a significant change from 0.0 in the general population as well as a significant difference from the population average evolvability in the within-niche evolvability.

Raspberry Pi: An Update on Sound

Life has been a bit demanding lately, so it has been a while since I last worked on the Raspberry Pis. I had a notion that I might dragoon the Pis into serving as compute engines for a simulation I wrote in Python, and that got me motivated to get new Raspbian images and set up two Pis as headless units. It did not take long to disabuse me of the notion that the Pis represented a good alternative to workstation compute time: my simulation on the Pi ran at about 1/20th the speed it did on the workstation. So the simulation is running in background on the workstation, and I had two Pis hooked into the network, up and running.

So I spent a part of the weekend working on steps toward using a Pi as an acoustic monitoring platform. I bought two real-time clock (RTC) modules some time ago, so each of the Pis had one of those onboard. The critical piece of information I was missing in getting those running was that the process of establishing the Linux device corresponding to the I2C device had to be accomplished not merely using “sudo” in front of the command, but in a root-owned shell process because of redirection within the command. I found a web page that offered good advice, including putting the following lines into /etc/rc.local:

modprobe i2c-bcm2708

echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device

modprobe rtc-ds1307

hwclock -s

When we last visited this topic, I had a USB sound device that could be recognized by the RasPi and that I could take recordings from. There was just one problem: the Pi would not stably reboot with the USB sound device plugged in. Given that my use case is going to be using the system as an instrument that will only be attended maybe every two weeks or so, that problem was a sufficient discouragement to have me doing other things for a few months.

It turns out that time helps. With the most recent Raspbian image, the reboot problem has gone away. Now, everything is not completely rosy. It turns out that I needed to restrict the USB ports to USB 1.1 speed in order to get a clean recording from the mic input. That likely would interfere with using either a USB keyboard or mouse, but I was already aiming at headless operation.

This clears the way for actually getting the system put together and readied for deployment. I need to write some code to handle periodic acoustic samples (cron launching a Python script seems good to me). Having code to connect to a server to upload status updates and/or data would be good; several of the platforms have some sort of Internet service. There’s a chunk to do for hardware. I need to find out exactly what the power supply situation is. I do already have a pair of 4A 5V UBECs. I need to do some testing, though, to make sure that the UBEC does not add a significant amount of noise to acoustic recordings. Since the UBEC is a switched power regulation device, it is quite possible that power-line noise could get into recorded signals. Some sort of housing is needed. And I need to fabricate the hydrophone (a piezo disk soldered to a coax cable with some waterproof potting to cover it) and pair it with an amplifier circuit. Whatever power the amplifier will need I’ll have to figure out, too. Some testing would be good. It would be ideal to find someone with a boat who thinks this sort of thing is cool. I think I have several weekends worth of project to keep me busy.