Well, since my previous posts about my various NetLogo models have been so popular, I thought I’d write another one about one my most unusual — and in-depth — NetLogo models thus far: one to simulate the evolution of behavior.
This particular simulation sprang from a desire I’ve harbored for a long time to create “digital organisms,” as Wikipedia calls them: organisms whose behavior is controlled by internal programming instructions, which evolve over time in a simulated environment. Of course, it’s notoriously difficult to both manipulate text and run it as program instructions within a programming language (at least for me), unless you’re willing to code a mini-compiler within your program, but nonetheless, I thought I’d give it a try.
As it turns out, NetLogo already comes with a built-in method called run. When called with a string as its argument, run interprets the string as it would any other stream of NetLogo commands. Given that, and the elegant modular simplicity of the NetLogo language, it seemed that even a merely casual programmer such as myself might have some chance of building a digital-organism simulator.
Thank goodness for one of NetLogo’s other commands, namely, carefully. Carefully has two arguments: an instruction to run, and a procedure to run if that instruction causes an error. With that in mind, and NetLogo’s modularity, I threw together a simple list containing a handful of symbols (such as “=”, “if”, and “+”), as well as the names of a few methods I’d pre-coded myself (methods that tell the organisms to do things like “eat” and “reproduce”). I had to do the latter because, the only way I could get around the errors that carefully would otherwise cause, at least for the time being, was to make any error-producing organism die immediately. After some fiddling to make the program-mutation procedure work properly, and to fix some other stupid little errors, I finally managed to get it to run. Here is a sample image from the result:
Those little labels you see hovering over each organism are the organisms’ programs. As you can see, they’re neither very varied or very complex. I had hoped to evolve the organisms into greater complexity (note: all of the methods you see here are not built-in to NetLogo, but are references to methods I coded myself. I did this for the sake of simplifying things a bit, and for “chunking” the program, so that it was less likely that a mutation would break the code, since the NetLogo language isn’t terribly mutation-tolerant, I discovered).
Over time, unfit programs died out, and the more fit ones reproduced. After a fairly short run-time, I got this:
Notice how the organisms all have essentially the same code. This is an unintended side-effect of the fact that I spawned so few organisms at the beginning of the run, for the sake of visual clarity. Although, I have noticed that a lot of my randomly-instantiated populations tend to do the same thing, in all of my evolution simulations: most of them will prove unfit, so the world will end up being populated by a group of genetically-similar descendants of the few highly-fit originals.
I let the model run for a little while longer, knowing full well (from other runs) that it wouldn’t do what I was hoping. Apparently, I didn’t make the environment complex enough, or the selection process harsh enough, to necessitate the evolution of interesting programs. The fact that interesting variations almost always die out — since even a misplaced parenthesis or bracket will cause a syntax error, which, as I said above, automatically results in the organism’s death — sort of selected against novel programs. What I was really hoping to see were some strange loophole exploits or programming workarounds (for example, an organism that, say, re-set its own energy level so that it wouldn’t have to trouble with actually eating food) of the kind that I talked about in my previous post “Unexpected Consequences”. What, instead, I ended up with, was this:
(For the sake of readability, I’ve only printed the program of a randomly-selected ten organisms.)
As you can see, every organism has essentially the same program. Oh well, I guess that’s a problem to be tackled in Version 2.
Here are some of my goals for the next rendition:
- Streamlining of the code: When there are more than about twenty-five organisms, the simulation slows waaay down. I don’t know if there’s a way to execute the organisms’ programs faster, but I’ m hoping that I can figure something out.
- Make the programs less fragile: The main roadblock to interesting programming variants is the fact that any “broken” code dies immediately, rather than, perhaps, getting repaired. Figuring out how to do that is going to be complicated, but it seems that every time I think I’m not going to be able to do something in NetLogo, I still manage.
- Make the environment more complex: as it is, the organisms are only competing for two things: energy, and, to a much lesser extent, space. I’d like to see if I can make the space-competition harsher, and perhaps introduce some new resources for them to compete over, such as mates (the current version uses asexual reproduction, since I didn’t want to bother with the nightmare of trying to prevent errors in sexually-combined programs).
More later, as events warrant.