Merge edited version of Mahran-Yousef:master pull request

This commit is contained in:
Lee Spector 2020-06-20 00:15:40 -04:00
commit c6f9b58556
8 changed files with 71 additions and 62 deletions

View File

@ -5,8 +5,8 @@
<output-test url="file://$MODULE_DIR$/target/classes" /> <output-test url="file://$MODULE_DIR$/target/classes" />
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" /> <sourceFolder url="file://C:\Users\user\Documents\GitHub\propeller\dev-resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/dev-resources" isTestSource="false" /> <sourceFolder url="file://C:\Users\user\Documents\GitHub\propeller\resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />

View File

@ -9,11 +9,14 @@
(gp (update-in (merge {:instructions default-instructions (gp (update-in (merge {:instructions default-instructions
:error-function regression-error-function :error-function regression-error-function
:max-generations 500 :max-generations 500
:population-size 200 :population-size 500
:max-initial-plushy-size 50 :max-initial-plushy-size 50
:step-limit 100 :step-limit 100
:parent-selection :tournament :parent-selection :lexicase
:tournament-size 5} :tournament-size 5
:UMADRate 0.1
:variation {:UMAD 0.5 :crossover 0.5}
:elitism false}
(apply hash-map (apply hash-map
(map read-string args))) (map read-string args)))
[:error-function] [:error-function]

View File

@ -4,16 +4,16 @@
(defn push-from-plushy (defn push-from-plushy
"Returns the Push program expressed by the given plushy representation." "Returns the Push program expressed by the given plushy representation."
[plushy] [plushy]
(let [opener? #(and (vector? %) (= (first %) 'open))] ;; [open <n>] marks opens (let [opener? #(and (vector? %) (= (first %) 'open))] ;; [open <n>] marks opens
(loop [push () ;; iteratively build the Push program from the plushy (loop [push () ;; iteratively build the Push program from the plushy
plushy (mapcat #(if-let [n (get opens %)] [% ['open n]] [%]) plushy)] plushy (mapcat #(if-let [n (get opens %)] [% ['open n]] [%]) plushy)]
(if (empty? plushy) ;; maybe we're done? (if (empty? plushy) ;; maybe we're done?
(if (some opener? push) ;; done with plushy, but unclosed open (if (some opener? push) ;; done with plushy, but unclosed open
(recur push '(close)) ;; recur with one more close (recur push '(close)) ;; recur with one more close
push) ;; otherwise, really done, return push push) ;; otherwise, really done, return push
(let [i (first plushy)] (let [i (first plushy)]
(if (= i 'close) (if (= i 'close)
(if (some opener? push) ;; process a close when there's an open (if (some opener? push) ;; process a close when there's an open
(recur (let [post-open (reverse (take-while (comp not opener?) (recur (let [post-open (reverse (take-while (comp not opener?)
(reverse push))) (reverse push)))
open-index (- (count push) (count post-open) 1) open-index (- (count push) (count post-open) 1)
@ -23,8 +23,8 @@
(concat pre-open [post-open]) (concat pre-open [post-open])
(concat pre-open [post-open ['open (dec num-open)]]))) (concat pre-open [post-open ['open (dec num-open)]])))
(rest plushy)) (rest plushy))
(recur push (rest plushy))) ;; unmatched close, ignore (recur push (rest plushy))) ;; unmatched close, ignore
(recur (concat push [i]) (rest plushy)))))))) ;; anything else (recur (concat push [i]) (rest plushy)))))))) ;; anything else
(defn make-random-plushy (defn make-random-plushy
"Creates and returns a new plushy." "Creates and returns a new plushy."

View File

@ -22,7 +22,7 @@
"Main GP loop." "Main GP loop."
[{:keys [population-size max-generations error-function instructions [{:keys [population-size max-generations error-function instructions
max-initial-plushy-size] max-initial-plushy-size]
:as argmap}] :as argmap}]
(println "Starting GP with args:" argmap) (println "Starting GP with args:" argmap)
(loop [generation 0 (loop [generation 0
population (repeatedly population (repeatedly
@ -38,5 +38,9 @@
(zero? (:total-error (first evaluated-pop))) (println "SUCCESS") (zero? (:total-error (first evaluated-pop))) (println "SUCCESS")
(>= generation max-generations) nil (>= generation max-generations) nil
:else (recur (inc generation) :else (recur (inc generation)
(repeatedly population-size (if (:elitism argmap)
#(new-individual evaluated-pop argmap))))))) (conj (repeatedly (dec population-size)
#(new-individual evaluated-pop argmap))
(first evaluated-pop))
(repeatedly population-size
#(new-individual evaluated-pop argmap))))))))

View File

@ -38,9 +38,9 @@
"G" "G"
"T")) "T"))
(def opens ; number of blocks opened by instructions (default = 0) (def opens ; number of blocks opened by instructions (default = 0)
{'exec_dup 1 {'exec_dup 1
'exec_if 2}) 'exec_if 2})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; actual instructions ;; actual instructions

View File

@ -2,17 +2,17 @@
(:use [propeller util])) (:use [propeller util]))
(def example-push-state (def example-push-state
{:exec '() {:exec '()
:integer '(1 2 3 4 5 6 7) :integer '(1 2 3 4 5 6 7)
:string '("abc") :string '("abc")
:input {:in1 4}}) :input {:in1 4}})
(def empty-push-state (def empty-push-state
{:exec '() {:exec '()
:integer '() :integer '()
:string '() :string '()
:boolean '() :boolean '()
:input {}}) :input {}})
(defn push-to-stack (defn push-to-stack
"Pushes item onto stack in state" "Pushes item onto stack in state"

View File

@ -5,37 +5,37 @@
#_(interpret-program '(1 2 integer_+) empty-push-state 1000) #_(interpret-program '(1 2 integer_+) empty-push-state 1000)
#_(interpret-program '(3 5 integer_= exec_if (1 "yes") (2 "no")) #_(interpret-program '(3 5 integer_= exec_if (1 "yes") (2 "no"))
empty-push-state empty-push-state
1000) 1000)
#_(interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if #_(interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if
(in1 " I am asking." string_concat) (in1 " I am asking." string_concat)
(in1 " I am saying." string_concat)) (in1 " I am saying." string_concat))
(assoc empty-push-state :input {:in1 "Can you hear me?"}) (assoc empty-push-state :input {:in1 "Can you hear me?"})
1000) 1000)
#_(interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if #_(interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if
(in1 " I am asking." string_concat) (in1 " I am asking." string_concat)
(in1 " I am saying." string_concat)) (in1 " I am saying." string_concat))
(assoc empty-push-state :input {:in1 "I can hear you."}) (assoc empty-push-state :input {:in1 "I can hear you."})
1000) 1000)
#_(push-from-plushy (make-random-plushy default-instructions 20)) #_(push-from-plushy (make-random-plushy default-instructions 20))
#_(interpret-program (push-from-plushy (make-random-plushy default-instructions 20)) #_(interpret-program (push-from-plushy (make-random-plushy default-instructions 20))
(assoc empty-push-state :input {:in1 "I can hear you."}) (assoc empty-push-state :input {:in1 "I can hear you."})
1000) 1000)
;; Target function: f(x) = x^3 + x + 3 ;; Target function: f(x) = x^3 + x + 3
#_(gp {:instructions default-instructions #_(gp {:instructions default-instructions
:error-function regression-error-function :error-function regression-error-function
:max-generations 50 :max-generations 50
:population-size 200 :population-size 200
:max-initial-plushy-size 50 :max-initial-plushy-size 50
:step-limit 100 :step-limit 100
:parent-selection :tournament :parent-selection :tournament
:tournament-size 5}) :tournament-size 5})
#_(gp {:instructions default-instructions #_(gp {:instructions default-instructions
:error-function string-classification-error-function :error-function string-classification-error-function

View File

@ -16,22 +16,19 @@
longer)))) longer))))
(defn uniform-addition (defn uniform-addition
"Randomly adds new instructions before every instruction (and at the end of "Returns plushy with new instructions possibly added before or after each existing instruction."
the plushy) with some probability." [plushy instructions UMADRate]
[plushy instructions] (apply concat
(let [rand-code (repeatedly (inc (count plushy)) (map #(if (< (rand) UMADRate)
(fn [] (shuffle [% (rand-nth instructions)])
(if (< (rand) 0.05) [%])
(rand-nth instructions) plushy)))
:mutation-padding)))]
(remove #(= % :mutation-padding)
(interleave (conj plushy :mutation-padding)
rand-code))))
(defn uniform-deletion (defn uniform-deletion
"Randomly deletes instructions from plushy at some rate." "Randomly deletes instructions from plushy at some rate."
[plushy] [plushy UMADRate]
(remove (fn [x] (< (rand) 0.05)) (remove (fn [_] (< (rand)
(/ 1 (+ 1 (/ 1 UMADRate)))))
plushy)) plushy))
(defn new-individual (defn new-individual
@ -41,8 +38,13 @@
{:plushy {:plushy
(let [prob (rand)] (let [prob (rand)]
(cond (cond
(< prob 0.5) (crossover (:plushy (select-parent pop argmap)) (< prob (:crossover (:variation argmap)))
(:plushy (select-parent pop argmap))) (crossover (:plushy (select-parent pop argmap))
(< prob 0.75) (uniform-addition (:plushy (select-parent pop argmap)) (:plushy (select-parent pop argmap)))
(:instructions argmap)) (< prob (+ (:crossover (:variation argmap))
:else (uniform-deletion (:plushy (select-parent pop argmap)))))}) (:UMAD (:variation argmap)) 2))
(uniform-deletion (uniform-addition (:plushy (select-parent pop argmap))
(:instructions argmap)
(:UMADRate argmap))
(:UMADRate argmap))
:else (:plushy (select-parent pop argmap))))})