Merge branch 'master' into test-vector-instructions
This commit is contained in:
commit
68802a9e45
2
.gitignore
vendored
2
.gitignore
vendored
@ -10,6 +10,8 @@ pom.xml.asc
|
|||||||
/.nrepl-port
|
/.nrepl-port
|
||||||
.hgignore
|
.hgignore
|
||||||
.hg/
|
.hg/
|
||||||
|
*.iml
|
||||||
|
.idea/
|
||||||
out
|
out
|
||||||
notes
|
notes
|
||||||
.idea/
|
.idea/
|
||||||
|
@ -5,18 +5,33 @@
|
|||||||
<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://C:\Users\user\Documents\GitHub\propeller\dev-resources" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
|
||||||
<sourceFolder url="file://C:\Users\user\Documents\GitHub\propeller\resources" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/dev-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" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="Leiningen: args4j:2.33" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: clojure-complete:0.2.5" level="project" />
|
<orderEntry type="library" name="Leiningen: clojure-complete:0.2.5" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.google.code.findbugs/jsr305:3.0.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.google.code.gson/gson:2.7" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.google.errorprone/error_prone_annotations:2.0.18" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.google.guava/guava:20.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.google.javascript/closure-compiler-externs:v20170910" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.google.javascript/closure-compiler-unshaded:v20170910" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.google.jsinterop/jsinterop-annotations:1.0.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.google.protobuf/protobuf-java:3.0.2" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: nrepl:0.6.0" level="project" />
|
<orderEntry type="library" name="Leiningen: nrepl:0.6.0" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/clojure:1.10.0" level="project" />
|
<orderEntry type="library" name="Leiningen: org.clojure/clojure:1.10.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: org.clojure/clojurescript:1.9.946" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/core.specs.alpha:0.2.44" level="project" />
|
<orderEntry type="library" name="Leiningen: org.clojure/core.specs.alpha:0.2.44" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: org.clojure/data.json:0.2.6" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: org.clojure/google-closure-library-third-party:0.0-20170809-b9c14c6b" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: org.clojure/google-closure-library:0.0-20170809-b9c14c6b" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/spec.alpha:0.2.176" level="project" />
|
<orderEntry type="library" name="Leiningen: org.clojure/spec.alpha:0.2.176" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: org.clojure/tools.reader:1.1.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: org.mozilla/rhino:1.7R5" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
@ -3,18 +3,26 @@
|
|||||||
(:require [propeller.gp :as gp]
|
(:require [propeller.gp :as gp]
|
||||||
[propeller.problems.simple-regression :as regression]
|
[propeller.problems.simple-regression :as regression]
|
||||||
[propeller.problems.string-classification :as string-classif]
|
[propeller.problems.string-classification :as string-classif]
|
||||||
[propeller.problems.software.number-io :as number-io]
|
|
||||||
[propeller.problems.software.smallest :as smallest]
|
|
||||||
#?(:cljs [cljs.reader :refer [read-string]])))
|
#?(:cljs [cljs.reader :refer [read-string]])))
|
||||||
|
|
||||||
|
(defn eval-problem-var
|
||||||
|
[problem-name var-name]
|
||||||
|
(eval (symbol (str "propeller.problems." problem-name "/" var-name))))
|
||||||
|
|
||||||
(defn -main
|
(defn -main
|
||||||
"Runs propel-gp, giving it a map of arguments."
|
"Runs propel-gp, giving it a map of arguments."
|
||||||
[& args]
|
[& args]
|
||||||
|
(when (empty? args)
|
||||||
|
(println "You must specify a problem to run.")
|
||||||
|
(println "Try, for example:")
|
||||||
|
(println " lein run software.smallest")
|
||||||
|
(System/exit 1))
|
||||||
|
(require (symbol (str "propeller.problems." (first args))))
|
||||||
(gp/gp
|
(gp/gp
|
||||||
(update-in
|
(update-in
|
||||||
(merge
|
(merge
|
||||||
{:instructions number-io/instructions
|
{:instructions (eval-problem-var (first args) "instructions")
|
||||||
:error-function number-io/error-function
|
:error-function (eval-problem-var (first args) "error-function")
|
||||||
:max-generations 500
|
:max-generations 500
|
||||||
:population-size 500
|
:population-size 500
|
||||||
:max-initial-plushy-size 100
|
:max-initial-plushy-size 100
|
||||||
@ -25,6 +33,6 @@
|
|||||||
:variation {:umad 0.5 :crossover 0.5}
|
:variation {:umad 0.5 :crossover 0.5}
|
||||||
:elitism false}
|
:elitism false}
|
||||||
(apply hash-map
|
(apply hash-map
|
||||||
(map read-string args)))
|
(map read-string (rest args))))
|
||||||
[:error-function]
|
[:error-function]
|
||||||
identity)))
|
identity)))
|
||||||
|
@ -11,8 +11,10 @@
|
|||||||
|
|
||||||
(defn plushy->push
|
(defn plushy->push
|
||||||
"Returns the Push program expressed by the given plushy representation."
|
"Returns the Push program expressed by the given plushy representation."
|
||||||
[plushy]
|
([plushy] (plushy->push plushy {}))
|
||||||
(let [opener? #(and (vector? %) (= (first %) 'open))] ;; [open <n>] marks opens
|
([plushy argmap]
|
||||||
|
(let [plushy (if (:diploid argmap) (map first (partition 2 plushy)) plushy)
|
||||||
|
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 push/opens %)] [% ['open n]] [%]) plushy)]
|
plushy (mapcat #(if-let [n (get push/opens %)] [% ['open n]] [%]) plushy)]
|
||||||
(if (empty? plushy) ;; maybe we're done?
|
(if (empty? plushy) ;; maybe we're done?
|
||||||
@ -32,4 +34,4 @@
|
|||||||
(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
|
||||||
|
@ -13,13 +13,13 @@
|
|||||||
|
|
||||||
(defn report
|
(defn report
|
||||||
"Reports information each generation."
|
"Reports information each generation."
|
||||||
[pop generation]
|
[pop generation argmap]
|
||||||
(let [best (first pop)]
|
(let [best (first pop)]
|
||||||
(println "-------------------------------------------------------")
|
(println "-------------------------------------------------------")
|
||||||
(println " Report for Generation" generation)
|
(println " Report for Generation" generation)
|
||||||
(println "-------------------------------------------------------")
|
(println "-------------------------------------------------------")
|
||||||
(print "Best plushy: ") (prn (:plushy best))
|
(print "Best plushy: ") (prn (:plushy best))
|
||||||
(print "Best program: ") (prn (genome/plushy->push (:plushy best)))
|
(print "Best program: ") (prn (genome/plushy->push (:plushy best) argmap))
|
||||||
(println "Best total error:" (:total-error best))
|
(println "Best total error:" (:total-error best))
|
||||||
(println "Best errors:" (:errors best))
|
(println "Best errors:" (:errors best))
|
||||||
(println "Best behaviors:" (:behaviors best))
|
(println "Best behaviors:" (:behaviors best))
|
||||||
@ -48,7 +48,7 @@
|
|||||||
:cljs map)
|
:cljs map)
|
||||||
(partial error-function argmap) population))
|
(partial error-function argmap) population))
|
||||||
best-individual (first evaluated-pop)]
|
best-individual (first evaluated-pop)]
|
||||||
(report evaluated-pop generation)
|
(report evaluated-pop generation argmap)
|
||||||
(cond
|
(cond
|
||||||
;; Success on training cases is verified on testing cases
|
;; Success on training cases is verified on testing cases
|
||||||
(zero? (:total-error best-individual))
|
(zero? (:total-error best-individual))
|
||||||
@ -57,7 +57,8 @@
|
|||||||
(if (zero? (:total-error (error-function argmap best-individual :test)))
|
(if (zero? (:total-error (error-function argmap best-individual :test)))
|
||||||
(println "Test cases passed.")
|
(println "Test cases passed.")
|
||||||
(println "Test cases failed."))
|
(println "Test cases failed."))
|
||||||
(#?(:clj shutdown-agents)))
|
;(#?(:clj shutdown-agents))
|
||||||
|
)
|
||||||
;;
|
;;
|
||||||
(>= generation max-generations)
|
(>= generation max-generations)
|
||||||
nil
|
nil
|
||||||
|
@ -32,15 +32,27 @@
|
|||||||
0
|
0
|
||||||
1))
|
1))
|
||||||
|
|
||||||
|
(defn train-and-test-data
|
||||||
|
[target-function]
|
||||||
|
(let [train-inputs (range -10 11)
|
||||||
|
test-inputs (concat (range -20 -10) (range 11 21))]
|
||||||
|
{:train {:inputs train-inputs
|
||||||
|
:outputs (map target-function train-inputs)}
|
||||||
|
:test {:inputs test-inputs
|
||||||
|
:outputs (map target-function test-inputs)}}))
|
||||||
|
|
||||||
(defn error-function
|
(defn error-function
|
||||||
"Finds the behaviors and errors of an individual. The error is the absolute
|
"Finds the behaviors and errors of an individual. The error is the absolute
|
||||||
deviation between the target output value and the program's selected behavior,
|
deviation between the target output value and the program's selected behavior,
|
||||||
or 1000000 if no behavior is produced. The behavior is here defined as the
|
or 1000000 if no behavior is produced. The behavior is here defined as the
|
||||||
final top item on the INTEGER stack."
|
final top item on the INTEGER stack."
|
||||||
[argmap individual]
|
([argmap individual]
|
||||||
(let [program (genome/plushy->push (:plushy individual))
|
(error-function argmap individual :train))
|
||||||
inputs (range -10 11)
|
([argmap individual subset]
|
||||||
correct-outputs (map target-function inputs)
|
(let [program (genome/plushy->push (:plushy individual) argmap)
|
||||||
|
data (get (train-and-test-data target-function) subset)
|
||||||
|
inputs (:inputs data)
|
||||||
|
correct-outputs (:outputs data)
|
||||||
outputs (map (fn [input]
|
outputs (map (fn [input]
|
||||||
(state/peek-stack
|
(state/peek-stack
|
||||||
(interpreter/interpret-program
|
(interpreter/interpret-program
|
||||||
@ -59,4 +71,4 @@
|
|||||||
:behaviors outputs
|
:behaviors outputs
|
||||||
:errors errors
|
:errors errors
|
||||||
:total-error #?(:clj (apply +' errors)
|
:total-error #?(:clj (apply +' errors)
|
||||||
:cljs (apply + errors)))))
|
:cljs (apply + errors))))))
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
([argmap individual]
|
([argmap individual]
|
||||||
(error-function argmap individual :train))
|
(error-function argmap individual :train))
|
||||||
([argmap individual subset]
|
([argmap individual subset]
|
||||||
(let [program (genome/plushy->push (:plushy individual))
|
(let [program (genome/plushy->push (:plushy individual) argmap)
|
||||||
data (get train-and-test-data subset)
|
data (get train-and-test-data subset)
|
||||||
inputs (:inputs data)
|
inputs (:inputs data)
|
||||||
correct-outputs (:outputs data)
|
correct-outputs (:outputs data)
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
([argmap individual]
|
([argmap individual]
|
||||||
(error-function argmap individual :train))
|
(error-function argmap individual :train))
|
||||||
([argmap individual subset]
|
([argmap individual subset]
|
||||||
(let [program (genome/plushy->push (:plushy individual))
|
(let [program (genome/plushy->push (:plushy individual) argmap)
|
||||||
data (get train-and-test-data subset)
|
data (get train-and-test-data subset)
|
||||||
inputs (:inputs data)
|
inputs (:inputs data)
|
||||||
correct-outputs (:outputs data)
|
correct-outputs (:outputs data)
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
:string_reverse
|
:string_reverse
|
||||||
:string_concat
|
:string_concat
|
||||||
:string_length
|
:string_length
|
||||||
:string_includes?
|
:string_contains
|
||||||
'close
|
'close
|
||||||
0
|
0
|
||||||
1
|
1
|
||||||
@ -40,15 +40,27 @@
|
|||||||
"G"
|
"G"
|
||||||
"T"))
|
"T"))
|
||||||
|
|
||||||
|
(defn train-and-test-data
|
||||||
|
[]
|
||||||
|
(let [train-inputs ["GCG" "GACAG" "AGAAG" "CCCA" "GATTACA" "TAGG" "GACT"]
|
||||||
|
test-inputs ["GCGT" "GACTTAG" "AGTAAG" "TCCTCA" "GAACA" "AGG" "GAC"]]
|
||||||
|
{:train {:inputs train-inputs
|
||||||
|
:outputs [false false false false true true true]}
|
||||||
|
:test {:inputs test-inputs
|
||||||
|
:outputs [true true true true false false false]}}))
|
||||||
|
|
||||||
(defn error-function
|
(defn error-function
|
||||||
"Finds the behaviors and errors of an individual: Error is 0 if the value and
|
"Finds the behaviors and errors of an individual: Error is 0 if the value and
|
||||||
the program's selected behavior match, or 1 if they differ, or 1000000 if no
|
the program's selected behavior match, or 1 if they differ, or 1000000 if no
|
||||||
behavior is produced. The behavior is here defined as the final top item on
|
behavior is produced. The behavior is here defined as the final top item on
|
||||||
the BOOLEAN stack."
|
the BOOLEAN stack."
|
||||||
[argmap individual]
|
([argmap individual]
|
||||||
(let [program (genome/plushy->push (:plushy individual))
|
(error-function argmap individual :train))
|
||||||
inputs ["GCG" "GACAG" "AGAAG" "CCCA" "GATTACA" "TAGG" "GACT"]
|
([argmap individual subset]
|
||||||
correct-outputs [false false false false true true true]
|
(let [program (genome/plushy->push (:plushy individual) argmap)
|
||||||
|
data (get (train-and-test-data) subset)
|
||||||
|
inputs (:inputs data)
|
||||||
|
correct-outputs (:outputs data)
|
||||||
outputs (map (fn [input]
|
outputs (map (fn [input]
|
||||||
(state/peek-stack
|
(state/peek-stack
|
||||||
(interpreter/interpret-program
|
(interpreter/interpret-program
|
||||||
@ -69,4 +81,4 @@
|
|||||||
:behaviors outputs
|
:behaviors outputs
|
||||||
:errors errors
|
:errors errors
|
||||||
:total-error #?(:clj (apply +' errors)
|
:total-error #?(:clj (apply +' errors)
|
||||||
:cljs (apply + errors)))))
|
:cljs (apply + errors))))))
|
||||||
|
@ -12,16 +12,16 @@
|
|||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
|
|
||||||
;; Allows Push to handle input instructions of the form :inN, e.g. :in2, taking
|
;; Allows Push to handle input instructions of the form :inN, e.g. :in2, taking
|
||||||
;; elements thus labeled from the :input stack and pushing them onto the :exec
|
;; elements thus labeled from the :input map and pushing them onto the :exec
|
||||||
;; stack. We can tell whether a particular inN instruction is valid if N-1
|
;; stack.
|
||||||
;; values are on the input stack.
|
|
||||||
(defn handle-input-instruction
|
(defn handle-input-instruction
|
||||||
[state instruction]
|
[state instruction]
|
||||||
(if-let [input (instruction (:input state))]
|
(if (contains? (:input state) instruction)
|
||||||
(state/push-to-stack state :exec input)
|
(let [input (instruction (:input state))]
|
||||||
(throw #?(:clj (Exception. (str "Undefined input instruction " instruction))
|
(state/push-to-stack state :exec input))
|
||||||
|
(throw #?(:clj (Exception. (str "Undefined instruction " instruction))
|
||||||
:cljs (js/Error
|
:cljs (js/Error
|
||||||
(str "Undefined input instruction " instruction))))))
|
(str "Undefined instruction " instruction))))))
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; OUTPUT Instructions
|
;; OUTPUT Instructions
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
(:require [propeller.utils :as utils]
|
(:require [propeller.utils :as utils]
|
||||||
[propeller.push.state :as state]
|
[propeller.push.state :as state]
|
||||||
[propeller.push.utils.helpers :refer [make-instruction]]
|
[propeller.push.utils.helpers :refer [make-instruction]]
|
||||||
|
[propeller.push.utils.globals :as globals]
|
||||||
#?(:clj
|
#?(:clj
|
||||||
[propeller.push.utils.macros :refer [def-instruction
|
[propeller.push.utils.macros :refer [def-instruction
|
||||||
generate-instructions]])))
|
generate-instructions]])))
|
||||||
@ -29,7 +30,8 @@
|
|||||||
;; its argument (since that would negate the effect of the duplication). The
|
;; its argument (since that would negate the effect of the duplication). The
|
||||||
;; number n is determined by the top INTEGER. For n = 0, equivalent to POP.
|
;; number n is determined by the top INTEGER. For n = 0, equivalent to POP.
|
||||||
;; For n = 1, equivalent to NOOP. For n = 2, equivalent to DUP. Negative values
|
;; For n = 1, equivalent to NOOP. For n = 2, equivalent to DUP. Negative values
|
||||||
;; of n are treated as 0
|
;; of n are treated as 0. The final number of items on the stack is limited to
|
||||||
|
;; globals/max-stack-items.
|
||||||
(def _dup_times
|
(def _dup_times
|
||||||
^{:stacks #{:integer}}
|
^{:stacks #{:integer}}
|
||||||
(fn [stack state]
|
(fn [stack state]
|
||||||
@ -38,7 +40,8 @@
|
|||||||
(and (not= stack :integer)
|
(and (not= stack :integer)
|
||||||
(not (state/empty-stack? state :integer))
|
(not (state/empty-stack? state :integer))
|
||||||
(not (state/empty-stack? state stack))))
|
(not (state/empty-stack? state stack))))
|
||||||
(let [n (state/peek-stack state :integer)
|
(let [n (min (state/peek-stack state :integer)
|
||||||
|
(inc (- globals/max-stack-items (state/stack-size state stack))))
|
||||||
popped-state (state/pop-stack state :integer)
|
popped-state (state/pop-stack state :integer)
|
||||||
top-item (state/peek-stack popped-state stack)
|
top-item (state/peek-stack popped-state stack)
|
||||||
top-item-dup (take (- n 1) (repeat top-item))]
|
top-item-dup (take (- n 1) (repeat top-item))]
|
||||||
@ -50,12 +53,14 @@
|
|||||||
;; Duplicates the top n items on the stack, one time each. The number n is
|
;; Duplicates the top n items on the stack, one time each. The number n is
|
||||||
;; determined by the top INTEGER. If n <= 0, no items will be duplicated. If
|
;; determined by the top INTEGER. If n <= 0, no items will be duplicated. If
|
||||||
;; fewer than n items are on the stack, the entire stack will be duplicated.
|
;; fewer than n items are on the stack, the entire stack will be duplicated.
|
||||||
|
;; The final number of items on the stack is limited to globals/max-stack-items.
|
||||||
(def _dup_items
|
(def _dup_items
|
||||||
^{:stacks #{:integer}}
|
^{:stacks #{:integer}}
|
||||||
(fn [stack state]
|
(fn [stack state]
|
||||||
(if (state/empty-stack? state :integer)
|
(if (state/empty-stack? state :integer)
|
||||||
state
|
state
|
||||||
(let [n (state/peek-stack state :integer)
|
(let [n (min (state/peek-stack state :integer)
|
||||||
|
(- globals/max-stack-items (state/stack-size state stack)))
|
||||||
popped-state (state/pop-stack state :integer)
|
popped-state (state/pop-stack state :integer)
|
||||||
top-items (take n (get popped-state stack))]
|
top-items (take n (get popped-state stack))]
|
||||||
(state/push-to-stack-many popped-state stack top-items)))))
|
(state/push-to-stack-many popped-state stack top-items)))))
|
||||||
|
@ -35,6 +35,11 @@
|
|||||||
[state stack]
|
[state stack]
|
||||||
(empty? (get state stack)))
|
(empty? (get state stack)))
|
||||||
|
|
||||||
|
;; Returns the stack size
|
||||||
|
(defn stack-size
|
||||||
|
[state stack]
|
||||||
|
(count (get state stack)))
|
||||||
|
|
||||||
;; Returns the top item on the stack
|
;; Returns the top item on the stack
|
||||||
(defn peek-stack
|
(defn peek-stack
|
||||||
[state stack]
|
[state stack]
|
||||||
|
11
src/propeller/push/utils/globals.cljc
Normal file
11
src/propeller/push/utils/globals.cljc
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
(ns propeller.push.utils.globals)
|
||||||
|
|
||||||
|
;; =============================================================================
|
||||||
|
;; Values used by the Push instructions to keep the stack sizes within
|
||||||
|
;; reasonable limits.
|
||||||
|
;; =============================================================================
|
||||||
|
|
||||||
|
;; Limits the number of items that can be duplicated onto a stack at once.
|
||||||
|
;; We might want to extend this to limit all the different that things may be
|
||||||
|
;; placed on a stack.
|
||||||
|
(def max-stack-items 100)
|
@ -7,56 +7,148 @@
|
|||||||
[propeller.problems.string-classification :as string-classif]
|
[propeller.problems.string-classification :as string-classif]
|
||||||
[propeller.push.core :as push]
|
[propeller.push.core :as push]
|
||||||
[propeller.push.interpreter :as interpreter]
|
[propeller.push.interpreter :as interpreter]
|
||||||
[propeller.push.state :as state]))
|
[propeller.push.state :as state]
|
||||||
|
[propeller.push.utils.helpers :refer [get-stack-instructions]]))
|
||||||
|
|
||||||
#_(interpreter/interpret-program
|
#_(interpreter/interpret-program
|
||||||
'(1 2 integer_add) state/empty-state 1000)
|
'(1 2 :integer_add) state/empty-state 1000)
|
||||||
|
|
||||||
#_(interpreter/interpret-program
|
#_(interpreter/interpret-program
|
||||||
'(3 5 :integer_eq :exec_if (1 "yes") (2 "no"))
|
'(3 3 :integer_eq :exec_if (1 "yes") (2 "no"))
|
||||||
state/empty-state
|
state/empty-state
|
||||||
1000)
|
1000)
|
||||||
|
|
||||||
#_(interpreter/interpret-program
|
#_(interpreter/interpret-program
|
||||||
'(in1 :string_reverse 1 :string_take "?" :string_eq :exec_if
|
'(:in1 :string_reverse 1 :string_take "?" :string_eq :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 state/empty-state :input {:in1 "Can you hear me?"})
|
(assoc state/empty-state :input {:in1 "Can you hear me?"})
|
||||||
1000)
|
1000)
|
||||||
|
|
||||||
#_(interpreter/interpret-program
|
#_(interpreter/interpret-program
|
||||||
'(in1 :string_reverse 1 :string_take "?" :string_eq :exec_if
|
'(:in1 :string_reverse 1 :string_take "?" :string_eq :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 state/empty-state :input {:in1 "I can hear you."})
|
(assoc state/empty-state :input {:in1 "I can hear you."})
|
||||||
1000)
|
1000)
|
||||||
|
|
||||||
#_(genome/plushy->push
|
#_(genome/plushy->push
|
||||||
(genome/make-random-plushy push/default-instructions 20))
|
(genome/make-random-plushy (get-stack-instructions #{:float :integer :exec :boolean}) 20))
|
||||||
|
|
||||||
#_(interpreter/interpret-program
|
#_(gp/gp {:instructions propeller.problems.software.number-io/instructions
|
||||||
(genome/plushy->push
|
:error-function propeller.problems.software.number-io/error-function
|
||||||
(genome/make-random-plushy push/default-instructions 20))
|
:max-generations 500
|
||||||
(assoc state/empty-state :input {:in1 "I can hear you."})
|
:population-size 500
|
||||||
1000)
|
:max-initial-plushy-size 100
|
||||||
|
:step-limit 200
|
||||||
|
:parent-selection :lexicase
|
||||||
|
:tournament-size 5
|
||||||
|
:umad-rate 0.1
|
||||||
|
:variation {:umad 0.5 :crossover 0.5}
|
||||||
|
:elitism false})
|
||||||
|
|
||||||
;; =============================================================================
|
#_(gp/gp {:instructions propeller.problems.simple-regression/instructions
|
||||||
;; Target function: f(x) = x^3 + x + 3
|
:error-function propeller.problems.simple-regression/error-function
|
||||||
;; =============================================================================
|
:max-generations 500
|
||||||
|
:population-size 500
|
||||||
#_(gp/gp {:instructions push/default-instructions
|
:max-initial-plushy-size 100
|
||||||
:error-function regression/error-function
|
:step-limit 200
|
||||||
:max-generations 50
|
|
||||||
:population-size 200
|
|
||||||
:max-initial-plushy-size 50
|
|
||||||
:step-limit 100
|
|
||||||
:parent-selection :tournament
|
:parent-selection :tournament
|
||||||
:tournament-size 5})
|
:tournament-size 5
|
||||||
|
:umad-rate 0.01
|
||||||
|
:variation {:umad 1.0
|
||||||
|
:crossover 0.0}
|
||||||
|
:elitism false})
|
||||||
|
|
||||||
#_(gp/gp {:instructions push/default-instructions
|
#_(gp/gp {:instructions propeller.problems.simple-regression/instructions
|
||||||
:error-function string-classif/error-function
|
:error-function propeller.problems.simple-regression/error-function
|
||||||
:max-generations 50
|
:max-generations 500
|
||||||
:population-size 200
|
:population-size 500
|
||||||
:max-initial-plushy-size 50
|
:max-initial-plushy-size 100
|
||||||
:step-limit 100
|
:step-limit 200
|
||||||
:parent-selection :lexicase})
|
:parent-selection :tournament
|
||||||
|
:tournament-size 5
|
||||||
|
:umad-rate 0.1
|
||||||
|
:variation {:umad 1.0
|
||||||
|
:crossover 0.0}
|
||||||
|
:elitism false})
|
||||||
|
|
||||||
|
|
||||||
|
#_(gp/gp {:instructions propeller.problems.simple-regression/instructions
|
||||||
|
:error-function propeller.problems.simple-regression/error-function
|
||||||
|
:max-generations 500
|
||||||
|
:population-size 500
|
||||||
|
:max-initial-plushy-size 100
|
||||||
|
:step-limit 200
|
||||||
|
:parent-selection :lexicase
|
||||||
|
:tournament-size 5
|
||||||
|
:umad-rate 0.1
|
||||||
|
:variation {:umad 1.0
|
||||||
|
:crossover 0.0}
|
||||||
|
:elitism false})
|
||||||
|
|
||||||
|
#_(gp/gp {:instructions propeller.problems.simple-regression/instructions
|
||||||
|
:error-function propeller.problems.simple-regression/error-function
|
||||||
|
:max-generations 500
|
||||||
|
:population-size 500
|
||||||
|
:max-initial-plushy-size 100
|
||||||
|
:step-limit 200
|
||||||
|
:parent-selection :lexicase
|
||||||
|
:tournament-size 5
|
||||||
|
:umad-rate 0.1
|
||||||
|
:diploid-flip-rate 0.1
|
||||||
|
:variation {:umad 0.8
|
||||||
|
:diploid-flip 0.2}
|
||||||
|
:elitism false
|
||||||
|
:diploid true})
|
||||||
|
|
||||||
|
|
||||||
|
#_(gp/gp {:instructions propeller.problems.software.smallest/instructions
|
||||||
|
:error-function propeller.problems.software.smallest/error-function
|
||||||
|
:max-generations 500
|
||||||
|
:population-size 500
|
||||||
|
:max-initial-plushy-size 100
|
||||||
|
:step-limit 200
|
||||||
|
:parent-selection :lexicase
|
||||||
|
:tournament-size 5
|
||||||
|
:umad-rate 0.1
|
||||||
|
:diploid-flip-rate 0.1
|
||||||
|
:variation {;:umad 0.8
|
||||||
|
;:diploid-flip 0.2
|
||||||
|
:umad 1
|
||||||
|
}
|
||||||
|
:elitism false
|
||||||
|
:diploid false})
|
||||||
|
|
||||||
|
#_(gp/gp {:instructions propeller.problems.software.smallest/instructions
|
||||||
|
:error-function propeller.problems.software.smallest/error-function
|
||||||
|
:max-generations 500
|
||||||
|
:population-size 500
|
||||||
|
:max-initial-plushy-size 200 ;100
|
||||||
|
:step-limit 200
|
||||||
|
:parent-selection :lexicase
|
||||||
|
:tournament-size 5
|
||||||
|
:umad-rate 0.1
|
||||||
|
:diploid-flip-rate 0.1
|
||||||
|
:variation {:umad 0.8
|
||||||
|
:diploid-flip 0.2
|
||||||
|
;:umad 1
|
||||||
|
}
|
||||||
|
:elitism false
|
||||||
|
:diploid true})
|
||||||
|
|
||||||
|
#_(gp/gp {:instructions propeller.problems.string-classification/instructions
|
||||||
|
:error-function propeller.problems.string-classification/error-function
|
||||||
|
:max-generations 500
|
||||||
|
:population-size 500
|
||||||
|
:max-initial-plushy-size 100
|
||||||
|
:step-limit 200
|
||||||
|
:parent-selection :lexicase
|
||||||
|
:tournament-size 5
|
||||||
|
:umad-rate 0.1
|
||||||
|
:diploid-flip-rate 0.1
|
||||||
|
:variation {:umad 0.8
|
||||||
|
:diploid-flip 0.2
|
||||||
|
}
|
||||||
|
:elitism false
|
||||||
|
:diploid true})
|
||||||
|
@ -16,6 +16,22 @@
|
|||||||
shorter-padded
|
shorter-padded
|
||||||
longer))))
|
longer))))
|
||||||
|
|
||||||
|
(defn diploid-crossover
|
||||||
|
"Crosses over two individuals using uniform crossover. Pads shorter one."
|
||||||
|
[plushy-a plushy-b]
|
||||||
|
(let [plushy-a (partition 2 plushy-a)
|
||||||
|
plushy-b (partition 2 plushy-b)
|
||||||
|
shorter (min-key count plushy-a plushy-b)
|
||||||
|
longer (if (= shorter plushy-a)
|
||||||
|
plushy-b
|
||||||
|
plushy-a)
|
||||||
|
length-diff (- (count longer) (count shorter))
|
||||||
|
shorter-padded (concat shorter (repeat length-diff :crossover-padding))]
|
||||||
|
(flatten (remove #(= % :crossover-padding)
|
||||||
|
(map #(if (< (rand) 0.5) %1 %2)
|
||||||
|
shorter-padded
|
||||||
|
longer)))))
|
||||||
|
|
||||||
(defn uniform-addition
|
(defn uniform-addition
|
||||||
"Returns plushy with new instructions possibly added before or after each
|
"Returns plushy with new instructions possibly added before or after each
|
||||||
existing instruction."
|
existing instruction."
|
||||||
@ -26,6 +42,26 @@
|
|||||||
[%])
|
[%])
|
||||||
plushy)))
|
plushy)))
|
||||||
|
|
||||||
|
(defn uniform-replacement
|
||||||
|
"Returns plushy with new instructions possibly replacing existing
|
||||||
|
instructions."
|
||||||
|
[plushy instructions replacement-rate]
|
||||||
|
(map #(if (< (rand) replacement-rate)
|
||||||
|
(utils/random-instruction instructions)
|
||||||
|
%)
|
||||||
|
plushy))
|
||||||
|
|
||||||
|
(defn diploid-uniform-addition
|
||||||
|
"Returns plushy with new instructions possibly added before or after each
|
||||||
|
existing instruction."
|
||||||
|
[plushy instructions umad-rate]
|
||||||
|
(flatten
|
||||||
|
(map (fn [pair]
|
||||||
|
(if (< (rand) umad-rate)
|
||||||
|
(shuffle [pair (repeatedly 2 #(utils/random-instruction instructions))])
|
||||||
|
[pair]))
|
||||||
|
(partition 2 plushy))))
|
||||||
|
|
||||||
(defn uniform-deletion
|
(defn uniform-deletion
|
||||||
"Randomly deletes instructions from plushy at some rate."
|
"Randomly deletes instructions from plushy at some rate."
|
||||||
[plushy umad-rate]
|
[plushy umad-rate]
|
||||||
@ -33,20 +69,85 @@
|
|||||||
(/ 1 (+ 1 (/ 1 umad-rate)))))
|
(/ 1 (+ 1 (/ 1 umad-rate)))))
|
||||||
plushy))
|
plushy))
|
||||||
|
|
||||||
|
(defn diploid-uniform-deletion
|
||||||
|
"Randomly deletes instructions from plushy at some rate."
|
||||||
|
[plushy umad-rate]
|
||||||
|
(flatten (remove (fn [_] (< (rand)
|
||||||
|
(/ 1 (+ 1 (/ 1 umad-rate)))))
|
||||||
|
(partition 2 plushy))))
|
||||||
|
|
||||||
|
(defn diploid-flip
|
||||||
|
"Randomly flips pairs in a diploid plushy at some rate."
|
||||||
|
[plushy flip-rate]
|
||||||
|
(flatten (map #(if (< (rand) flip-rate)
|
||||||
|
(reverse %)
|
||||||
|
%)
|
||||||
|
(partition 2 plushy))))
|
||||||
|
|
||||||
(defn new-individual
|
(defn new-individual
|
||||||
"Returns a new individual produced by selection and variation of
|
"Returns a new individual produced by selection and variation of
|
||||||
individuals in the population."
|
individuals in the population."
|
||||||
[pop argmap]
|
[pop argmap]
|
||||||
{:plushy
|
{:plushy
|
||||||
(let [prob (rand)]
|
(let [r (rand)
|
||||||
(cond
|
op (loop [accum 0.0
|
||||||
(< prob (:crossover (:variation argmap)))
|
ops-probs (vec (:variation argmap))]
|
||||||
(crossover (:plushy (selection/select-parent pop argmap))
|
(if (empty? ops-probs)
|
||||||
|
:reproduction
|
||||||
|
(let [[op1 prob1] (first ops-probs)]
|
||||||
|
(if (>= (+ accum prob1) r)
|
||||||
|
op1
|
||||||
|
(recur (+ accum prob1)
|
||||||
|
(rest ops-probs))))))]
|
||||||
|
(case op
|
||||||
|
:crossover
|
||||||
|
(crossover
|
||||||
|
(:plushy (selection/select-parent pop argmap))
|
||||||
(:plushy (selection/select-parent pop argmap)))
|
(:plushy (selection/select-parent pop argmap)))
|
||||||
(< prob (+ (:crossover (:variation argmap))
|
;
|
||||||
(:umad (:variation argmap)) 2))
|
:umad
|
||||||
(uniform-deletion (uniform-addition (:plushy (selection/select-parent pop argmap))
|
(-> (:plushy (selection/select-parent pop argmap))
|
||||||
(:instructions argmap)
|
(uniform-addition (:instructions argmap) (:umad-rate argmap))
|
||||||
(:umad-rate argmap))
|
(uniform-deletion (:umad-rate argmap)))
|
||||||
(:umad-rate argmap))
|
;
|
||||||
:else (:plushy (selection/select-parent pop argmap))))})
|
:uniform-addition
|
||||||
|
(-> (:plushy (selection/select-parent pop argmap))
|
||||||
|
(uniform-addition (:instructions argmap) (:umad-rate argmap)))
|
||||||
|
;
|
||||||
|
:uniform-replacement
|
||||||
|
(-> (:plushy (selection/select-parent pop argmap))
|
||||||
|
(uniform-replacement (:instructions argmap) (:replacement-rate argmap)))
|
||||||
|
;
|
||||||
|
:uniform-deletion
|
||||||
|
(-> (:plushy (selection/select-parent pop argmap))
|
||||||
|
(uniform-deletion (:umad-rate argmap)))
|
||||||
|
;
|
||||||
|
:diploid-crossover
|
||||||
|
(diploid-crossover
|
||||||
|
(:plushy (selection/select-parent pop argmap))
|
||||||
|
(:plushy (selection/select-parent pop argmap)))
|
||||||
|
;
|
||||||
|
:diploid-umad
|
||||||
|
(-> (:plushy (selection/select-parent pop argmap))
|
||||||
|
(diploid-uniform-addition (:instructions argmap) (:umad-rate argmap))
|
||||||
|
(diploid-uniform-deletion (:umad-rate argmap)))
|
||||||
|
;
|
||||||
|
:diploid-uniform-addition
|
||||||
|
(-> (:plushy (selection/select-parent pop argmap))
|
||||||
|
(diploid-uniform-addition (:instructions argmap) (:umad-rate argmap)))
|
||||||
|
;
|
||||||
|
:diploid-uniform-deletion
|
||||||
|
(-> (:plushy (selection/select-parent pop argmap))
|
||||||
|
(diploid-uniform-deletion (:umad-rate argmap)))
|
||||||
|
;
|
||||||
|
:diploid-flip
|
||||||
|
(-> (:plushy (selection/select-parent pop argmap))
|
||||||
|
(diploid-flip (:diploid-flip-rate argmap)))
|
||||||
|
;
|
||||||
|
:reproduction
|
||||||
|
(:plushy (selection/select-parent pop argmap))
|
||||||
|
;
|
||||||
|
:else
|
||||||
|
(throw #?(:clj (Exception. (str "No match in new-individual for " op))
|
||||||
|
:cljs (js/Error
|
||||||
|
(str "No match in new-individual for " op))))))})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user