Genetic programming is a way of having the computer write programs for you!
Don't think "programs" like MS Word, think of "programs" as the following:
function(x){ return x*2; }
This function (or program), by itself, doesn't have a reason to exist. We are looking for solutions to problems. If you need to find the sum of two numbers, you just open the calculator and do the math. What if someone gave you the following table and asked you to figure out the relationship between result
and x
and y
:
x y result
99 1 (3.02)
79 88 2.01
21 62 5.01
84 52 (6.58)
12 70 5.54
67 18 0.73
This data is your "training" data. Your computer will use this data to generate some hypothesis, then you will test it against actual data.
Say you don't know statistics and decide this problem is too hard to figure out on your own, so you'll get the computer to figure it out for you.
Have the computer randomly generate wild guesses
You have the computer generate a million answers, and see if any of them stick (guess...a million times!). Following is an example of a couple of guesses:
function(x,y){ return x+y; } // wrong
function(x,y){ return x/1*1*1*1*1*1+y; } //wrong, silly
You may or may not know this, but functions or programs can also be represented as trees, for example, the second function would be:
(+ (/ x (* 1 (* 1 (* 1 (* 1 (* 1 1)))) y)
You can make it look more like a tree by indenting it like so (btw, look up reverse polish notation and lisp syntax...but you will understand why we represent programs like this shortly):
(+
(/ x
(* 1
(* 1
(* 1
(* 1
(* 1 1))))
y)
(+
is at the top with two "leaves" of /
and y
. /
itself has several children, etc.)
This is why you read so much about "trees" in genetic programming. In any case, we plug in the values of x
and y
into this function and it gives us the WRONG answer. Not surprising though since we randomly generated this.
You now decide to generate a million such solutions. All of them are wrong. However, you notice that some answers are closer to the right answer than others. In other words, some solutions are more "fit" than others. Note that the computer doesn't know what is "right" and "wrong" so you have to provide your own "fitness function." This function gets handed a potential solution, the training data, and is responsible for telling the GP system just how "fit" this solution is. As you can imagine, this function gets run millions upon millions of times.
What makes GP different
Here is what makes genetic programming different from wild guesses. You decide to do another round of million guesses; however, you do it a little more intelligently. You take the top 10% of the guesses (the ones that were closes to the actual values) and make them part of the second generation. You also take many of these solutions (perhaps the same 10%...i don't remember) and decide to "mix them up."
You randomly pick two solutions, randomly pick sub-trees and start swapping them. So part of solution A ends up under solution B and vice versa -- you just "crossed" them. You also take some solutions and simply "mutate" them...take some subtree and 'screw it up' a bit (hey, if the solution is terrible, 'screwing with it for no reason' might actually improve it).
A good way of thinking of this is the following: your mom and dad have certain attributes--hair color, height, likelihood of disease, etc. You, as a child inherit different attributes from both of your parents. If both of your parents were olympic athletes, you will also be a super athlete, right? Well, biologists, sociologists and even historians might take issue with this idea, but computer scientists are not concerned with the morality of eugenics here. They just saw a "system" doing a pretty good job providing solutions, so they decided to model it in software.
If it doesn't actually match biology, but still provides good answers... many computer scientists collectively say "whatever dude, and thanks for the terminology." Also note that all your brothers and sisters and not EXACTLY the same... even through they have same parents. Each person has genes which mutate for whatever reason (please don't show this to a biologist, the point is to understand the motivation behind much of the terminology).
So now we are getting the computer to generate millions of programs and measuring their fitness. The best solutions survive into the next generation. We also "mutate" and do cross-over on the "population" (notice how language of genetics and biology is being used). Once the second generation is created, fitness is again measured. Since this generation has the best solutions from the previous generation AND we crossed over and mutated the best solutions (along with mediocre population -- to keep up diversity), this generation should be at least a little better than the previous generation.
We continue this for a very large number of generations. Each generation (hopefully) provides better and better solutions, until we get the right answer. For example:
(+ (- 2.2 (/ x 11) (* 7 (cos y))))
Well look at this, this is correct!
(I copied this from http://en.wikipedia.org/wiki/Genetic_programming, which also has a graphic representation of this tree)
Odds and Ends
There are some important issues, like how do you decide which "terminals" (+, -, *, /, cos, sin, tan
) are available to your GP system, how do you write the fitness function and how does the system handle non-sensical programs such as (1 + cos)
or (2 / "hello")
(among many others).
It is pretty boring to evolve equations. It gets more interesting if your terminal set looks like the following: (fire, sense enemy, move, ...) and your fitness function measures your health and the number of dead bodies of martial monsters.
I wrote most of this from memory but this is the basic idea. I did some GP in my college years. You should definitely play around with it. Don't worry about understanding all the terminology, just download some free GP systems, run through a few examples to get a feel for it and make up your own interesting examples (find relationships between different data sets, try to hook it up to game APIs, etc.)