[Cs254f11] a complete genetic algorithm

Lee Spector lspector at hampshire.edu
Sun Oct 9 22:55:21 EDT 2011


I think that it would be useful at this point for me to provide code for a complete, simple genetic algorithm in Clojure.

This just evolves a number as the sum of a vector of zeros and ones, so it's not solving a very interesting problem or using a very interesting representation. But it shows one way of making all of the pieces of an evolutionary algorithm (a GA, not a GP system because the individuals here aren't executed), and in particular one way of making the main evolutionary loop. I think it's pretty concise and readable, and you should feel free to adapt it to your own purposes. 

What follows is executable code.

 -Lee

(ns evolvesum) ;; Lee Spector (lspector at hampshire.edu) 20111009

;; We evolve a vector of 100 zeros and ones that sums to a particular number.

;; An individual is a vector of 100 random bits.

(defn new-individual 
  []
  (vec (repeatedly 100 #(rand-int 2))))

;; An individual is mutated by flipping a random bit.

(defn mutate
  [individual]
  (assoc individual (rand-int 100) (rand-int 2)))

;; The error of an individual is the difference between the sum of the bits
;; and the goal, which we hardcode here.

(defn error 
  [individual]
  (Math/abs (- (reduce + individual) 73)))

;; An individual is better than another if it has lower error.

(defn better
  [i1 i2]
  (< (error i1) (error i2)))

;; We evolve a solution by starting with a random population and repeatedly
;; sorting, checking for a solution, and producing a new population.
;; We produce the new population by selecting and mutating the better half
;; of the current population.

(defn evolve
  [popsize]
  (loop [population (sort better (repeatedly popsize new-individual))]
    (let [best (first population)]
      (println "Best error:" (error best))
      (if (zero? (error best))
        (println "Success:" best)
        (let [better-half (take (int (/ popsize 2)) population)]
          (recur 
            (sort better (map mutate 
                              (concat better-half better-half)))))))))

;; Run it with a population of 100:

(evolve 100)

;; Exercises:
;; - Create variables or parameters for the various hardcoded values.
;; - Avoid recomputing errors by making individuals pairs of [error genome].
;; - Print more information about the population each generation.
;; - Select parents via tournaments.
;; - Add crossover.
;; - Use a more interesting genome representation, for a more interesting
;;   problem.



--
Lee Spector, Professor of Computer Science
Cognitive Science, Hampshire College
893 West Street, Amherst, MA 01002-3359
lspector at hampshire.edu, http://hampshire.edu/lspector/
Phone: 413-559-5352, Fax: 413-559-5438



More information about the Cs254f11 mailing list