diff --git a/src/propeller/gp.cljc b/src/propeller/gp.cljc old mode 100755 new mode 100644 index 0d05a83..7c87229 --- a/src/propeller/gp.cljc +++ b/src/propeller/gp.cljc @@ -2,6 +2,7 @@ (:require [clojure.string] [clojure.pprint] [propeller.genome :as genome] + [propeller.simplification :as simplification] [propeller.variation :as variation] [propeller.push.instructions.bool] [propeller.push.instructions.character] @@ -58,7 +59,10 @@ (<= (:total-error best-individual) solution-error-threshold) (do (prn {:success-generation generation}) (prn {:total-test-error - (:total-error (error-function argmap (:testing-data argmap) best-individual))})) + (:total-error (error-function argmap (:testing-data argmap) best-individual))}) + (if (:simplification? argmap) + (let [simplified-plushy (simplification/auto-simplify-plushy argmap (:plushy best-individual) (:simplification-steps argmap) error-function (:training-data argmap) (:simplification-k argmap) (:simplification-k-prob argmap) (:simplification-verbose? argmap))] + (prn {:total-test-error-simplified (:total-error (error-function argmap (:testing-data argmap) (hash-map :plushy simplified-plushy)))})))) ;; (>= generation max-generations) nil diff --git a/src/propeller/simplification.cljc b/src/propeller/simplification.cljc new file mode 100644 index 0000000..5527be0 --- /dev/null +++ b/src/propeller/simplification.cljc @@ -0,0 +1,37 @@ +(ns propeller.simplification + (:require [propeller.genome :as genome] + [propeller.push.interpreter :as interpreter] + [propeller.push.state :as state] + [propeller.tools.math :as math] + )) + +(defn choose-random-k + [k indices] + (take k (shuffle indices))) + +(defn delete-at-indices + "deletes the values at given set of indices" + [indices plushy] + (let [sorted-indices (sort > indices)] + (keep-indexed #(if (not (some #{%1} sorted-indices)) %2) plushy))) + +(defn delete-k-random + [k plushy] + (delete-at-indices (choose-random-k k (range (count plushy))) plushy)) + +(defn auto-simplify-plushy + "naive auto-simplification with simple k annealing" + [argmap plushy steps error-function training-data start-k decrease-k-on-failure-prob verbose?] + (if verbose? (prn "Starting Auto-Simplification" {:current-plushy-length (count plushy) :k start-k :decrease-k-on-failure-prob decrease-k-on-failure-prob})) + (let [initial-errors (:errors (error-function argmap training-data {:plushy plushy}))] + (loop [step 0 curr-plushy plushy k start-k] + (if (and verbose? (= (mod step 50) 0)) (pr {:step step :k k} " ")) + (if (< steps step) + (do (if verbose? (prn "Finished Auto-Simplification" {:final-plushy-length (count curr-plushy) :final-plushy curr-plushy})) curr-plushy) + (let [new-plushy (delete-k-random k curr-plushy) + new-plushy-errors (:errors (error-function argmap training-data {:plushy new-plushy})) + new-equal? (= new-plushy-errors initial-errors)] + (print-str new-plushy new-plushy-errors new-equal?) + (recur (inc step) + (if new-equal? new-plushy curr-plushy) + (if new-equal? k (if (and (> k 1) (< (rand) decrease-k-on-failure-prob)) (dec k) k)))))))) \ No newline at end of file diff --git a/test/propeller/utils_test.cljc b/test/propeller/utils_test.cljc index 15a4984..e450a38 100644 --- a/test/propeller/utils_test.cljc +++ b/test/propeller/utils_test.cljc @@ -1,6 +1,8 @@ (ns propeller.utils-test (:require [clojure.test :as t] - [propeller.utils :as u])) + [propeller.utils :as u] + [propeller.simplification :as s])) + (t/deftest first-non-nil-test (t/is (= 1 (u/first-non-nil '(1 2 3)))) (t/is (= nil (u/first-non-nil []))) @@ -26,20 +28,11 @@ true (= 2 test)))))) - (t/deftest count-points-test (t/is (= 6 (u/count-points '(:a :b (:c :d))))) (t/is (= 1 (u/count-points '()))) (t/is (= 2 (u/count-points '(:a))))) -<<<<<<< Updated upstream -;(t/deftest seq-zip-test -; (t/is )) - -;(t/deftest depth-test -; (t/is (= 3 (u/depth ())))) - -======= (t/testing "choose-random-k" (t/testing "should return indices that are a member of the original array" (t/is (every? identity (map #(contains? (set (range 10)) %) (s/choose-random-k 3 (range 10)))))) @@ -82,5 +75,4 @@ (let [plushy '(:exec_dup 1 :integer_add close :in1 :integer_add 0 :in1 :in1 :integer_mult :integer_add)] (t/testing "should decrease size of plushy that always has perfect scores" (t/is (< (count (s/auto-simplify-plushy {} plushy 5 (fn [argmap data plushy] 0) {} 3 false)) (count plushy))) - (t/is (< (count (s/auto-simplify-plushy {} plushy 1 (fn [argmap data plushy] 0) {} 10 false)) (count plushy)))))) ->>>>>>> Stashed changes + (t/is (< (count (s/auto-simplify-plushy {} plushy 1 (fn [argmap data plushy] 0) {} 10 false)) (count plushy)))))) \ No newline at end of file