The genetic algorithm was my favorite of the artificial life projects I did. Though the others were neat, they were more random and hit/miss for the input vs output, where genetic algorithms have a purpose. In my mind, also lend towards a more useful general programming technique. Though I feel that my code for this project is messy and way too long for a word doc, I’m still going to post it to help beginner artificial life programmers since that is what I am.
Also, I considered doing an explination of this genetic algorithm, but then I realized I would just be repeating what I had read online about the subject. So, I will just say check out the wikipedia entry and look up information on mutations, bias, genetic algorithms, and any other term you don’t understand as I go through this.
Genetic Algorithm Code
Now as you have seen, I use a DefaultActions function to call all the other functions. I do this simply so I can make one function call elsewhere and keep all the genetic algorithm code to itself.
Now the function of this genetic algorithm is to find the best solutions to the problem of “With X number of coins and a goal of X dollars, how many of each coin do you need?” So with 100 coins and a goal of $5, how many pennies, nickels, dimes, quarters, half-dollars, and dollars will you need?
First there are all the input functions, then one output function. All the input functions take their input and check to make sure it is a valid value, if it isn’t, I decided to simply insert a default value.
Now most of the input functions are fairly simple and similar. They ask for what they want with an example, “Input the number of coins (Ex: 100)”, take the input, check its value and replace it if needed. I’m going to explain the ones that I think need explination.
The bias function is fairly simple and easy to understand, but what is the bias? Well, the bias in the genetic algorithm is like selecting the best of the crop. This number tells us how much of the top percent do we want to use to select our parents. Do we take only the strongest by doing 10%, or do we widen our selection to 30%? Taking only the best will not always be the best option, since it is essentially limiting the gene pool.
The population size is the number of groups of coins we have in each generation. In the InputPopulation function, we get the population from the user, and then resize the coin arrays to that population. Then we call the InitializeCoins function which takes the arrays of CoinSets, our coin value holding struct, and sets all the values to 0. Then we call the RandomStart function. This function fills our coinArray with a random number of coins. I believe my comments in the RandomStart function explain what is going on, and if they don’t, let me know and I’ll try to do better.
In the inputCoins function, we get which coins are going to be used. The user has 6 options of coins to use or not use and inputs those values. I store the values in a string and parse through it right there in the function. If any values are present, we know we are using that type of coin, and set the boolean value to true.
Next we have a very important function which is used in the RandomStart function, which I skipped over, the CalculateScore function. This function is the most important because it lets us know if what we are doing is getting near or far from our end goal. It helps answer the question “Are the coins in our group closer or farther away from the goal of $5 with 100 coins?” Now, since we are using coins and the coins have set values (.05, .10, etc), it is really easy to get a score in this genetic algorithm example. If used elsewhere, it will be much harder to calculate a score or even have a correct end goal. Anyway, as I state in the functions comments, I do some extra work to try to make a more interesting looking score, but in the end it is just for show.
The output function does exactly that, outputs the coin group values for each generation. It checks to see if we have found a solution, if not, continues outputting and going with the next generations. One of the functions used here I will not discuss, the shellSort function, but if you do a Google search for ‘Shell Sort’, you can find information on it, but pretty much it sorts the array quickly. The next function, NextGeneration, does all the rest of the work.
The NextGeneration function takes the bias number and starts selecting parents from the previous generation to make the new generation of values. With each new generation, there is some mutation chance. If we do have a mutation, the Mutate function simply randomly changes the number of coins of each kind in the group.
I hope this explained more about the program and genetic algorithms in programming than added to the confusion.
Now, aside from the focused aspect of this example program, genetic algorithms can be used for decision in many programs. When you want some sort of random element, but still want control over it, you can use a genetic algorithm. Since the output will be determined by previous input, you can control the randomness to be within your previously set limits. An example could be a “Link of the Day” section on a website. Based on the health of the previous or other links on the site (health could be popularity, # of clicks, etc), the “Link of the Day” is chosen from that pool of links.
Since I enjoy games, I see more examples of where genetic algorithms could be used. It can be used in the normal biological sense, such as having mutations for enemies that have different colored skin, strength, skill level from their “parents” or previously encountered monsters of their kind. It could also be used in level development for random levels; taking criteria for openings, required edges, and importance. That way the levels are designed towards an optimal level, but still contain random elements to enjoy.