diff --git a/src/propeller/core.clj b/src/propeller/core.clj index c25aa43..2b57a8f 100644 --- a/src/propeller/core.clj +++ b/src/propeller/core.clj @@ -1,25 +1,25 @@ (ns propeller.core (:gen-class) - (:require [propeller.gp :refer :all] - [propeller.push.core :refer :all] - (propeller.problems [simple-regression :refer :all] - [string-classification :refer :all]))) + (:require [propeller.gp :as gp] + [propeller.push.core :as push] + (propeller.problems [simple-regression :refer [regression-error-function]] + [string-classification :refer [string-classification-error-function]]))) (defn -main "Runs propel-gp, giving it a map of arguments." [& args] - (gp (update-in (merge {:instructions default-instructions - :error-function regression-error-function - :max-generations 500 - :population-size 500 - :max-initial-plushy-size 50 - :step-limit 100 - :parent-selection :lexicase - :tournament-size 5 - :umad-rate 0.1 - :variation {:umad 0.5 :crossover 0.5} - :elitism false} - (apply hash-map - (map read-string args))) - [:error-function] - #(if (fn? %) % (eval %))))) + (gp/gp (update-in (merge {:instructions push/default-instructions + :error-function regression-error-function + :max-generations 500 + :population-size 500 + :max-initial-plushy-size 50 + :step-limit 100 + :parent-selection :lexicase + :tournament-size 5 + :umad-rate 0.1 + :variation {:umad 0.5 :crossover 0.5} + :elitism false} + (apply hash-map + (map read-string args))) + [:error-function] + #(if (fn? %) % (eval %))))) diff --git a/src/propeller/genome.clj b/src/propeller/genome.clj index 2d8c971..b8a60e7 100644 --- a/src/propeller/genome.clj +++ b/src/propeller/genome.clj @@ -1,12 +1,12 @@ (ns propeller.genome - (:require [propeller.push.core :refer :all])) + (:require [propeller.push.core :as push])) (defn plushy->push "Returns the Push program expressed by the given plushy representation." [plushy] (let [opener? #(and (vector? %) (= (first %) 'open))] ;; [open ] marks opens (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 push/opens %)] [% ['open n]] [%]) plushy)] (if (empty? plushy) ;; maybe we're done? (if (some opener? push) ;; done with plushy, but unclosed open (recur push '(close)) ;; recur with one more close diff --git a/src/propeller/gp.clj b/src/propeller/gp.clj index 02673fc..b782e46 100644 --- a/src/propeller/gp.clj +++ b/src/propeller/gp.clj @@ -1,7 +1,7 @@ (ns propeller.gp (:require [propeller.push.core :refer [instruction-table]] - (propeller [genome :refer :all] - [variation :refer :all]))) + (propeller [genome :as genome] + [variation :as variation]))) (defn report "Reports information each generation." @@ -11,7 +11,7 @@ (println " Report for Generation" generation) (println "-------------------------------------------------------") (print "Best plushy: ") (prn (:plushy best)) - (print "Best program: ") (prn (plushy->push (:plushy best))) + (print "Best program: ") (prn (genome/plushy->push (:plushy best))) (println "Best total error:" (:total-error best)) (println "Best errors:" (:errors best)) (println "Best behaviors:" (:behaviors best)) @@ -39,7 +39,7 @@ population (repeatedly population-size #(hash-map :plushy - (make-random-plushy instructions + (genome/make-random-plushy instructions max-initial-plushy-size)))] (let [evaluated-pop (sort-by :total-error (map (partial error-function argmap) @@ -51,7 +51,7 @@ :else (recur (inc generation) (if (:elitism argmap) (conj (repeatedly (dec population-size) - #(new-individual evaluated-pop argmap)) + #(variation/new-individual evaluated-pop argmap)) (first evaluated-pop)) (repeatedly population-size - #(new-individual evaluated-pop argmap)))))))) + #(variation/new-individual evaluated-pop argmap)))))))) diff --git a/src/propeller/problems/string_classification.clj b/src/propeller/problems/string_classification.clj index 3434cfa..9381ca5 100644 --- a/src/propeller/problems/string_classification.clj +++ b/src/propeller/problems/string_classification.clj @@ -1,7 +1,7 @@ (ns propeller.problems.string-classification - (:require [propeller.genome :refer :all] - (propeller.push [state :refer :all] - [interpreter :refer :all]))) + (:require [propeller.genome :as genome] + (propeller.push [state :as state] + [interpreter :as interpreter]))) ;; ============================================================================= ;; String classification @@ -13,14 +13,14 @@ behavior is produced. The behavior is here defined as the final top item on the BOOLEAN stack." [argmap individual] - (let [program (plushy->push (:plushy individual)) + (let [program (genome/plushy->push (:plushy individual)) inputs ["GCG" "GACAG" "AGAAG" "CCCA" "GATTACA" "TAGG" "GACT"] correct-outputs [false false false false true true true] outputs (map (fn [input] - (peek-stack - (interpret-program + (state/peek-stack + (interpreter/interpret-program program - (assoc empty-state :input {:in1 input}) + (assoc state/empty-state :input {:in1 input}) (:step-limit argmap)) :boolean)) inputs) diff --git a/src/propeller/push/interpreter.clj b/src/propeller/push/interpreter.clj index 82e223a..cccc4f1 100644 --- a/src/propeller/push/interpreter.clj +++ b/src/propeller/push/interpreter.clj @@ -1,11 +1,11 @@ (ns propeller.push.interpreter - (:require [propeller.push.core :refer [instruction-table]]) - (:require [propeller.push.state :refer :all])) + (:require [propeller.push.core :refer [instruction-table]] + [propeller.push.state :as state])) (defn interpret-one-step "Takes a Push state and executes the next instruction on the exec stack." [state] - (let [popped-state (pop-stack state :exec) + (let [popped-state (state/pop-stack state :exec) first-instruction-raw (first (:exec state)) first-instruction (if (keyword? first-instruction-raw) (first-instruction-raw @instruction-table) @@ -15,16 +15,16 @@ (first-instruction popped-state) ; (integer? first-instruction) - (push-to-stack popped-state :integer first-instruction) + (state/push-to-stack popped-state :integer first-instruction) ; (string? first-instruction) - (push-to-stack popped-state :string first-instruction) + (state/push-to-stack popped-state :string first-instruction) ; (seq? first-instruction) (update popped-state :exec #(concat %2 %1) first-instruction) ; (or (= first-instruction true) (= first-instruction false)) - (push-to-stack popped-state :boolean first-instruction) + (state/push-to-stack popped-state :boolean first-instruction) ; :else (throw (Exception. (str "Unrecognized Push instruction in program: " diff --git a/src/propeller/push/utils.clj b/src/propeller/push/utils.clj index 793109c..561bda1 100644 --- a/src/propeller/push/utils.clj +++ b/src/propeller/push/utils.clj @@ -1,6 +1,6 @@ (ns propeller.push.utils (:require [propeller.push.core :refer [def-instruction]] - [propeller.push.state :refer :all])) + [propeller.push.state :as state])) ;; A utility function for making Push instructions. Takes a state, a function ;; to apply to the args, the stacks to take the args from, and the stack to @@ -8,12 +8,12 @@ ;; given stacks), and pushes the result onto the return-stack (defn make-instruction [state function arg-stacks return-stack] - (let [popped-args (get-args-from-stacks state arg-stacks)] + (let [popped-args (state/get-args-from-stacks state arg-stacks)] (if (= popped-args :not-enough-args) state (let [result (apply function (:args popped-args)) new-state (:state popped-args)] - (push-to-stack new-state return-stack result))))) + (state/push-to-stack new-state return-stack result))))) ;; Given a sequence of stacks, e.g. [:float :integer], and a sequence of suffix ;; function strings, e.g. [_+, _*, _=], automates the generation of all possible @@ -28,7 +28,7 @@ ;; Pretty-prints a Push state, for logging or debugging purposes (defn print-state [state] - (doseq [stack stacks] + (doseq [stack state/stacks] (printf "%-15s = " stack) (prn (if (get state stack) (get state stack) '())) (flush))) diff --git a/src/propeller/session.clj b/src/propeller/session.clj index 7fca02f..e653159 100644 --- a/src/propeller/session.clj +++ b/src/propeller/session.clj @@ -1,41 +1,41 @@ (ns propeller.session - (:require (propeller [gp :refer :all] - [variation :refer :all] - [selection :refer :all] - [genome :refer :all]) - (propeller.push [interpreter :refer :all] - [core :refer :all] - [state :refer :all]) - (propeller.problems [simple-regression :refer :all] - [string-classification :refer :all]))) + (:require (propeller [gp :as gp] + [variation :as variation] + [selection :as selection] + [genome :as genome]) + (propeller.push [interpreter :as interpreter] + [core :as push] + [state :as state]) + (propeller.problems [simple-regression :refer [regression-error-function]] + [string-classification :refer [string-classification-error-function]]))) -#_(interpret-program '(1 2 integer_+) empty-push-state 1000) +#_(interpreter/interpret-program '(1 2 integer_+) empty-push-state 1000) -#_(interpret-program '(3 5 integer_= exec_if (1 "yes") (2 "no")) +#_(interpreter/interpret-program '(3 5 integer_= exec_if (1 "yes") (2 "no")) empty-push-state 1000) -#_(interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if +#_(interpreter/interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if (in1 " I am asking." string_concat) (in1 " I am saying." string_concat)) (assoc empty-push-state :input {:in1 "Can you hear me?"}) 1000) -#_(interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if +#_(interpreter/interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if (in1 " I am asking." string_concat) (in1 " I am saying." string_concat)) (assoc empty-push-state :input {:in1 "I can hear you."}) 1000) -#_(plushy->push (make-random-plushy default-instructions 20)) +#_(genome/plushy->push (genome/make-random-plushy push/default-instructions 20)) -#_(interpret-program (plushy->push (make-random-plushy default-instructions 20)) +#_(interpreter/interpret-program (genome/plushy->push (genome/make-random-plushy push/default-instructions 20)) (assoc empty-push-state :input {:in1 "I can hear you."}) 1000) ;; Target function: f(x) = x^3 + x + 3 -#_(gp {:instructions default-instructions +#_(gp/gp {:instructions push/default-instructions :error-function regression-error-function :max-generations 50 :population-size 200 @@ -44,7 +44,7 @@ :parent-selection :tournament :tournament-size 5}) -#_(gp {:instructions default-instructions +#_(gp/gp {:instructions push/default-instructions :error-function string-classification-error-function :max-generations 50 :population-size 200 diff --git a/src/propeller/variation.clj b/src/propeller/variation.clj index 8e0e391..4bac3f5 100644 --- a/src/propeller/variation.clj +++ b/src/propeller/variation.clj @@ -1,5 +1,5 @@ (ns propeller.variation - (:require [propeller.selection :refer :all])) + (:require [propeller.selection :as selection])) (defn crossover "Crosses over two individuals using uniform crossover. Pads shorter one." @@ -40,12 +40,12 @@ (let [prob (rand)] (cond (< prob (:crossover (:variation argmap))) - (crossover (:plushy (select-parent pop argmap)) - (:plushy (select-parent pop argmap))) + (crossover (:plushy (selection/select-parent pop argmap)) + (:plushy (selection/select-parent pop argmap))) (< prob (+ (:crossover (:variation argmap)) (:umad (:variation argmap)) 2)) - (uniform-deletion (uniform-addition (:plushy (select-parent pop argmap)) + (uniform-deletion (uniform-addition (:plushy (selection/select-parent pop argmap)) (:instructions argmap) (:umad-rate argmap)) (:umad-rate argmap)) - :else (:plushy (select-parent pop argmap))))}) + :else (:plushy (selection/select-parent pop argmap))))})