commit
3a04b74633
1
.gitignore
vendored
1
.gitignore
vendored
@ -33,3 +33,4 @@ node_modules/
|
||||
# https://github.com/thelmuth/program-synthesis-benchmark-datasets
|
||||
/data
|
||||
**/.DS_Store
|
||||
/.cpcache/
|
||||
|
7
deps.edn
Normal file
7
deps.edn
Normal file
@ -0,0 +1,7 @@
|
||||
{:paths ["src" "target/classes"],
|
||||
:deps
|
||||
{org.clojure/clojure #:mvn{:version "1.10.0"},
|
||||
org.clojure/clojurescript #:mvn{:version "1.9.946"},
|
||||
org.clojure/test.check #:mvn{:version "1.1.0"},
|
||||
net.clojars.schneau/psb2 #:mvn{:version "1.1.0"}},
|
||||
:mvn/repos {}}
|
@ -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)
|
||||
|
@ -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))))))))
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,10 @@
|
||||
; The "session" namespace is for trying things out interactively.
|
||||
; For example, you can use it to test a new Push instruction by running a program that uses it and seeing the result.
|
||||
; You might just want to do this interactively in the REPL, but the session file makes it a little easier since it alerady
|
||||
; requires most of the namespaces you'll want to refer to.
|
||||
; The commented-out stuff is a reminder of how to do some basic things.
|
||||
|
||||
|
||||
(ns propeller.session
|
||||
(:require [propeller.genome :as genome]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -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}))]
|
||||
|
@ -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))))
|
||||
|
@ -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)
|
||||
|
@ -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)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user