added docstrings

more comments in genome, gp, selection, simplification, utils, variation
This commit is contained in:
Ashley Bao 2023-01-11 21:37:37 -05:00
parent 962dd5a55b
commit 84f2e6a88d
7 changed files with 40 additions and 18 deletions

View File

@ -3,7 +3,7 @@
[propeller.utils :as utils]))
(defn make-random-plushy
"Creates and returns a new plushy."
"Creates and returns a new plushy made of random instructions and of a maximum size of max-initial-plushy-size."
[instructions max-initial-plushy-size]
(repeatedly
(rand-int max-initial-plushy-size)

View File

@ -46,15 +46,15 @@
(loop [generation 0
population (mapper
(fn [_] {:plushy (genome/make-random-plushy instructions max-initial-plushy-size)})
(range population-size))]
(range population-size))] ;creates population of random plushys
(let [evaluated-pop (sort-by :total-error
(mapper
(partial error-function argmap (:training-data argmap))
population))
population)) ;population sorted by :total-error
best-individual (first evaluated-pop)
argmap (if (= (:parent-selection argmap) :epsilon-lexicase)
(assoc argmap :epsilons (selection/epsilon-list evaluated-pop))
argmap)]
argmap)] ;adds :epsilons if using epsilon-lexicase
(if (:custom-report argmap)
((:custom-report argmap) evaluated-pop generation argmap)
(report evaluated-pop generation argmap))
@ -75,6 +75,6 @@
(if (:elitism argmap)
(conj (repeatedly (dec population-size)
#(variation/new-individual evaluated-pop argmap))
(first evaluated-pop))
(first evaluated-pop)) ;elitism maintains the most-fit individual
(repeatedly population-size
#(variation/new-individual evaluated-pop argmap))))))))

View File

@ -2,14 +2,18 @@
(:require [propeller.tools.math :as math-tools]))
(defn tournament-selection
"Selects an individual from the population using a tournament."
"Selects an individual from the population using tournaments of
tournament-size by taking the individual in the tournament with the lowest :total-error. "
[pop argmap]
(let [tournament-size (:tournament-size argmap)
tournament-set (take tournament-size (shuffle pop))]
(apply min-key :total-error tournament-set)))
(defn lexicase-selection
"Selects an individual from the population using lexicase selection."
"Selects an individual from the population using lexicase selection.
Lexicase parent selection filters the population by considering one random training case at a time,
eliminating any individuals with errors for the current case that are worse than the best error in the selection pool,
until a single individual remains."
[pop argmap]
(loop [survivors (map rand-nth (vals (group-by :errors pop)))
cases (shuffle (range (count (:errors (first pop)))))]
@ -23,6 +27,7 @@
(rest cases))))))
(defn epsilon-list
"List of epsilons for each training case based on median absolute deviation of errors."
[pop]
(let [error-list (map :errors pop)
length (count (:errors (first pop)))]
@ -35,7 +40,9 @@
(inc i))))))
(defn epsilon-lexicase-selection
"Selects an individual from the population using epsilon-lexicase selection."
"Selects an individual from the population using epsilon-lexicase selection.
Epsilon lexicase selection follows the same process as lexicase selection except,
for a test case, only individuals with an error outside of a predefined epsilon are filtered."
[pop argmap]
(let [epsilons (:epsilons argmap)]
(loop [survivors pop

View File

@ -6,6 +6,7 @@
))
(defn choose-random-k
"Takes k random indices"
[k indices]
(take k (shuffle indices)))
@ -16,11 +17,12 @@
(keep-indexed #(when (not (some #{%1} sorted-indices)) %2) plushy)))
(defn delete-k-random
"Deletes k random instructions from the plushy"
[k plushy]
(delete-at-indices (choose-random-k k (range (count plushy))) plushy))
(defn auto-simplify-plushy
"naive auto-simplification"
"simplifies plushy by deleting instructions that have no impact on errors. naive auto-simplification"
[plushy error-function {:keys [simplification-steps training-data simplification-k simplification-verbose?] :as argmap}]
(when simplification-verbose? (prn {:start-plushy-length (count plushy) :k simplification-k}))
(let [initial-errors (:errors (error-function argmap training-data {:plushy plushy}))]

View File

@ -6,14 +6,18 @@
(defonce E #?(:clj Math/E
:cljs js/Math.PI))
(defn mean [coll]
(defn mean
"Returns the mean."
[coll]
(let [sum (apply + coll)
count (count coll)]
(if (pos? count)
(/ sum (float count))
0.0)))
(defn median [coll]
(defn median
"Returns the median."
[coll]
(let [sorted (sort coll)
cnt (count sorted)
halfway (quot cnt 2.0)]
@ -25,6 +29,7 @@
(mean [bottom-val top-val])))))
(defn median-absolute-deviation
"Returns the median absolute deviation."
[coll]
(let [median-val (median coll)]
(median (map #(Math/abs (- % median-val)) coll))))

View File

@ -21,7 +21,7 @@
lst))
(defn ensure-list
"Returns a non-lazy list if passed a seq argument. Othwrwise, returns a list
"Returns a non-lazy list if passed a seq argument. Otherwise, returns a list
containing the argument."
[thing]
(if (seq? thing)

View File

@ -3,7 +3,8 @@
[propeller.utils :as utils]))
(defn crossover
"Crosses over two individuals using uniform crossover. Pads shorter one."
"Crosses over two individuals using uniform crossover, one Push instruction at a time.
Pads shorter one from the end of the list of instructions."
[plushy-a plushy-b]
(let [shorter (min-key count plushy-a plushy-b)
longer (if (= shorter plushy-a)
@ -17,7 +18,8 @@
longer))))
(defn tail-aligned-crossover
"Crosses over two individuals using uniform crossover. Pads shorter one on the left."
"Crosses over two individuals using uniform crossover, one Push instruction at a time.
Pads shorter one from the beginning of the list of instructions."
[plushy-a plushy-b]
(let [shorter (min-key count plushy-a plushy-b)
longer (if (= shorter plushy-a)
@ -31,7 +33,8 @@
longer))))
(defn diploid-crossover
"Crosses over two individuals using uniform crossover. Pads shorter one."
"Crosses over two individuals using uniform crossover with pairs of Push instructions.
Pads shorter one from the end of the list of instructions."
[plushy-a plushy-b]
(let [plushy-a (partition 2 plushy-a)
plushy-b (partition 2 plushy-b)
@ -47,7 +50,8 @@
longer)))))
(defn tail-aligned-diploid-crossover
"Crosses over two individuals using uniform crossover. Pads shorter one on the left."
"Crosses over two individuals using uniform crossover with pairs of Push instructions.
Pads shorter one from the beginning of the list of instructions."
[plushy-a plushy-b]
(let [plushy-a (partition 2 plushy-a)
plushy-b (partition 2 plushy-b)
@ -156,7 +160,10 @@
(-> (:plushy (selection/select-parent pop argmap))
(uniform-addition (:instructions argmap) (:umad-rate argmap))
(uniform-deletion (:umad-rate argmap)))
;
; uniform mutation by addition and deletion is a uniform mutation operator which
;first adds genes with some probability before or after every existing gene and then
;deletes random genes from the resulting genome
:rumad
(let [parent-genome (:plushy (selection/select-parent pop argmap))
after-addition (uniform-addition parent-genome
@ -166,7 +173,8 @@
(count parent-genome))
(count parent-genome))]
(uniform-deletion after-addition effective-addition-rate))
;
; Adds and deletes instructions in the parent genome with the same rate
:uniform-addition
(-> (:plushy (selection/select-parent pop argmap))
(uniform-addition (:instructions argmap) (:umad-rate argmap)))