Move tools module for ClojureScript compatibility, and style fixes

This commit is contained in:
mcgirjau 2020-06-25 12:57:20 -04:00
parent 64d43756b6
commit 4bd92503a3
20 changed files with 134 additions and 128 deletions

View File

@ -2,24 +2,27 @@
(:gen-class) (:gen-class)
(:require [propeller.gp :as gp] (:require [propeller.gp :as gp]
[propeller.push.core :as push] [propeller.push.core :as push]
(propeller.problems [simple-regression :refer [regression-error-function]] (propeller.problems [simple-regression :as regression]
[string-classification :refer [string-classification-error-function]]))) [string-classification :as string-classif])))
(defn -main (defn -main
"Runs propel-gp, giving it a map of arguments." "Runs propel-gp, giving it a map of arguments."
[& args] [& args]
(gp/gp (update-in (merge {:instructions push/default-instructions (gp/gp
:error-function regression-error-function (update-in
:max-generations 500 (merge
:population-size 500 {:instructions push/default-instructions
:max-initial-plushy-size 50 :error-function regression/error-function
:step-limit 100 :max-generations 500
:parent-selection :lexicase :population-size 500
:tournament-size 5 :max-initial-plushy-size 50
:umad-rate 0.1 :step-limit 100
:variation {:umad 0.5 :crossover 0.5} :parent-selection :lexicase
:elitism false} :tournament-size 5
(apply hash-map :umad-rate 0.1
(map read-string args))) :variation {:umad 0.5 :crossover 0.5}
[:error-function] :elitism false}
#(if (fn? %) % (eval %))))) (apply hash-map
(map read-string args)))
[:error-function]
#(if (fn? %) % (eval %)))))

View File

@ -1,7 +1,7 @@
(ns propeller.gp (ns propeller.gp
(:require [propeller.push.core :refer [instruction-table]] (:require (propeller [genome :as genome]
(propeller [genome :as genome] [variation :as variation])
[variation :as variation]))) [propeller.push.core :as push]))
(defn report (defn report
"Reports information each generation." "Reports information each generation."
@ -33,14 +33,14 @@
(require '[propeller.push.instructions boolean char code input-output (require '[propeller.push.instructions boolean char code input-output
numeric polymorphic string]) numeric polymorphic string])
(println "Done. Registered instructions:") (println "Done. Registered instructions:")
(println (sort (keys @instruction-table)))) (println (sort (keys @push/instruction-table))))
;; ;;
(loop [generation 0 (loop [generation 0
population (repeatedly population (repeatedly
population-size population-size
#(hash-map :plushy #(hash-map :plushy
(genome/make-random-plushy instructions (genome/make-random-plushy instructions
max-initial-plushy-size)))] max-initial-plushy-size)))]
(let [evaluated-pop (sort-by :total-error (let [evaluated-pop (sort-by :total-error
(map (partial error-function argmap) (map (partial error-function argmap)
population))] population))]

View File

@ -1,9 +1,8 @@
(ns propeller.problems.simple-regression (ns propeller.problems.simple-regression
(:require [propeller.genome :refer [plushy->push]] (:require [propeller.genome :as genome]
[propeller.push.interpreter :refer [interpret-program]] (propeller.push [interpreter :as interpreter]
[propeller.push.state :refer [empty-state [state :as state])
peek-stack]] [propeller.tools.math :as math]))
[tools.math :as math]))
;; ============================================================================= ;; =============================================================================
;; Problem: f(x) = 7x^2 - 20x + 13 ;; Problem: f(x) = 7x^2 - 20x + 13
@ -19,20 +18,20 @@
[x] [x]
(+ (* x x x) x 3)) (+ (* x x x) x 3))
(defn regression-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 (plushy->push (:plushy individual)) (let [program (genome/plushy->push (:plushy individual))
inputs (range -10 11) inputs (range -10 11)
correct-outputs (map target-function inputs) correct-outputs (map target-function inputs)
outputs (map (fn [input] outputs (map (fn [input]
(peek-stack (state/peek-stack
(interpret-program (interpreter/interpret-program
program program
(assoc empty-state :input {:in1 input}) (assoc state/empty-state :input {:in1 input})
(:step-limit argmap)) (:step-limit argmap))
:integer)) :integer))
inputs) inputs)

View File

@ -1,13 +1,13 @@
(ns propeller.problems.string-classification (ns propeller.problems.string-classification
(:require [propeller.genome :as genome] (:require [propeller.genome :as genome]
(propeller.push [state :as state] (propeller.push [interpreter :as interpreter]
[interpreter :as interpreter]))) [state :as state])))
;; ============================================================================= ;; =============================================================================
;; String classification ;; String classification
;; ============================================================================= ;; =============================================================================
(defn string-classification-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

View File

@ -1,6 +1,4 @@
(ns propeller.push.core (ns propeller.push.core)
(:require [propeller.push.state :refer [get-args-from-stacks
push-to-stack]]))
;; ============================================================================= ;; =============================================================================
;; PushGP Instructions ;; PushGP Instructions
@ -13,6 +11,8 @@
;; TMH: ERCs? ;; TMH: ERCs?
;; ============================================================================= ;; =============================================================================
(def instruction-table (atom (hash-map)))
;; Set of original propel instructions ;; Set of original propel instructions
(def default-instructions (def default-instructions
(list :in1 (list :in1
@ -46,12 +46,6 @@
"G" "G"
"T")) "T"))
(def instruction-table (atom (hash-map)))
(defmacro def-instruction
[instruction definition]
`(swap! instruction-table assoc '~instruction ~definition))
;; Number of blocks opened by instructions (default = 0) ;; Number of blocks opened by instructions (default = 0)
(def opens {:exec_dup 1 (def opens {:exec_dup 1
:exec_if 2}) :exec_if 2})

View File

@ -1,6 +1,6 @@
(ns propeller.push.instructions.boolean (ns propeller.push.instructions.boolean
(:require [propeller.push.core :refer [def-instruction]] (:require [propeller.push.utils :refer [def-instruction
[propeller.push.utils :refer [make-instruction]])) make-instruction]]))
;; ============================================================================= ;; =============================================================================
;; BOOLEAN Instructions ;; BOOLEAN Instructions

View File

@ -1,7 +1,7 @@
(ns propeller.push.instructions.char (ns propeller.push.instructions.char
(:require [propeller.push.core :refer [def-instruction]] (:require [propeller.push.utils :refer [def-instruction
[propeller.push.utils :refer [make-instruction]] make-instruction]]
[tools.character :as char])) [propeller.tools.character :as char]))
;; ============================================================================= ;; =============================================================================
;; CHAR Instructions ;; CHAR Instructions

View File

@ -1,7 +1,7 @@
(ns propeller.push.instructions.code (ns propeller.push.instructions.code
(:require [propeller.push.core :refer [def-instruction]] (:require (propeller.push [state :as state]
[propeller.push.state :as state] [utils :refer [def-instruction
[propeller.push.utils :refer [make-instruction]])) make-instruction]])))
;; ============================================================================= ;; =============================================================================
;; CODE and EXEC Instructions ;; CODE and EXEC Instructions

View File

@ -1,6 +1,6 @@
(ns propeller.push.instructions.input-output (ns propeller.push.instructions.input-output
(:require [propeller.push.state :as state] (:require (propeller.push [state :as state]
[propeller.push.core :refer [def-instruction]])) [utils :refer [def-instruction]])))
;; ============================================================================= ;; =============================================================================
;; INPUT and OUTPUT Instructions ;; INPUT and OUTPUT Instructions

View File

@ -1,8 +1,8 @@
(ns propeller.push.instructions.numeric (ns propeller.push.instructions.numeric
(:require [propeller.push.core :refer [def-instruction]] (:require [propeller.push.utils :refer [def-instruction
[propeller.push.utils :refer [generate-functions generate-functions
make-instruction]] make-instruction]]
[tools.math :as math])) [propeller.tools.math :as math]))
;; ============================================================================= ;; =============================================================================
;; FLOAT and INTEGER Instructions (polymorphic) ;; FLOAT and INTEGER Instructions (polymorphic)

View File

@ -1,11 +1,8 @@
(ns propeller.push.instructions.polymorphic (ns propeller.push.instructions.polymorphic
(:require [propeller.push.core :refer [def-instruction]] (:require (propeller.push [state :as state]
[propeller.push.state :refer [empty-stack? [utils :refer [def-instruction
peek-stack generate-functions
pop-stack make-instruction]])))
push-to-stack]]
[propeller.push.utils :refer [generate-functions
make-instruction]]))
;; ============================================================================= ;; =============================================================================
;; Polymorphic Instructions ;; Polymorphic Instructions
@ -24,10 +21,10 @@
;; would negate the effect of the duplication) ;; would negate the effect of the duplication)
(defn- _dup (defn- _dup
[stack state] [stack state]
(let [top-item (peek-stack state stack)] (let [top-item (state/peek-stack state stack)]
(if (empty-stack? state stack) (if (state/empty-stack? state stack)
state state
(push-to-stack state stack top-item)))) (state/push-to-stack state stack top-item))))
;; Duplicates n copies of the top item (i.e leaves n copies there). Does not pop ;; Duplicates n copies of the top item (i.e leaves n copies there). Does not pop
;; its argument (since that would negate the effect of the duplication). The ;; its argument (since that would negate the effect of the duplication). The
@ -39,10 +36,10 @@
(if (or (and (= stack :integer) (if (or (and (= stack :integer)
(>= (count (:integer state)) 2)) (>= (count (:integer state)) 2))
(and (not= stack :integer) (and (not= stack :integer)
(not (empty-stack? state :integer)) (not (state/empty-stack? state :integer))
(not (empty-stack? state stack)))) (not (state/empty-stack? state stack))))
(let [n (peek-stack state :integer) (let [n (state/peek-stack state :integer)
item-to-duplicate (peek-stack state stack)] item-to-duplicate (state/peek-stack state stack)]
nil) nil)
state)) state))
@ -54,7 +51,7 @@
;; Pushes TRUE onto the BOOLEAN stack if the stack is empty. Otherwise FALSE ;; Pushes TRUE onto the BOOLEAN stack if the stack is empty. Otherwise FALSE
(defn- _empty (defn- _empty
[stack state] [stack state]
(push-to-stack state :boolean (empty-stack? state stack))) (state/push-to-stack state :boolean (state/empty-stack? state stack)))
;; Empties the given stack ;; Empties the given stack
(defn- _flush (defn- _flush
@ -64,7 +61,7 @@
;; Pops the given stack ;; Pops the given stack
(defn- _pop (defn- _pop
[stack state] [stack state]
(pop-stack state stack)) (state/pop-stack state stack))
;; Rotates the top three items on the stack (i.e. pulls the third item out and ;; Rotates the top three items on the stack (i.e. pulls the third item out and
;; pushes it on top). Equivalent to (yank state stack-type 2) ;; pushes it on top). Equivalent to (yank state stack-type 2)

View File

@ -1,6 +1,6 @@
(ns propeller.push.instructions.string (ns propeller.push.instructions.string
(:require [propeller.push.core :refer [def-instruction]] (:require [propeller.push.utils :refer [def-instruction
[propeller.push.utils :refer [make-instruction]])) make-instruction]]))
;; ============================================================================= ;; =============================================================================
;; STRING Instructions ;; STRING Instructions

View File

@ -1,6 +1,6 @@
(ns propeller.push.interpreter (ns propeller.push.interpreter
(:require [propeller.push.core :refer [instruction-table]] (:require (propeller.push [core :as push]
[propeller.push.state :as state])) [state :as state])))
(defn interpret-one-step (defn interpret-one-step
"Takes a Push state and executes the next instruction on the exec stack." "Takes a Push state and executes the next instruction on the exec stack."
@ -8,7 +8,7 @@
(let [popped-state (state/pop-stack state :exec) (let [popped-state (state/pop-stack state :exec)
first-instruction-raw (first (:exec state)) first-instruction-raw (first (:exec state))
first-instruction (if (keyword? first-instruction-raw) first-instruction (if (keyword? first-instruction-raw)
(first-instruction-raw @instruction-table) (first-instruction-raw @push/instruction-table)
first-instruction-raw)] first-instruction-raw)]
(cond (cond
(fn? first-instruction) (fn? first-instruction)

View File

@ -1,6 +1,10 @@
(ns propeller.push.utils (ns propeller.push.utils
(:require [propeller.push.core :refer [def-instruction]] (:require (propeller.push [core :as push]
[propeller.push.state :as state])) [state :as state])))
(defmacro def-instruction
[instruction definition]
`(swap! push/instruction-table assoc '~instruction ~definition))
;; A utility function for making Push instructions. Takes a state, a function ;; 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 ;; to apply to the args, the stacks to take the args from, and the stack to

View File

@ -1,53 +1,62 @@
(ns propeller.session (ns propeller.session
(:require (propeller [gp :as gp] (:require (propeller [genome :as genome]
[variation :as variation] [gp :as gp]
[selection :as selection] [selection :as selection]
[genome :as genome]) [variation :as variation])
(propeller.push [interpreter :as interpreter] (propeller.push [core :as push]
[core :as push] [interpreter :as interpreter]
[state :as state]) [state :as state])
(propeller.problems [simple-regression :refer [regression-error-function]] (propeller.problems [simple-regression :as regression]
[string-classification :refer [string-classification-error-function]]))) [string-classification :as string-classif])))
#_(interpreter/interpret-program '(1 2 integer_+) empty-push-state 1000) #_(interpreter/interpret-program
'(1 2 integer_add) state/empty-state 1000)
#_(interpreter/interpret-program '(3 5 integer_= exec_if (1 "yes") (2 "no")) #_(interpreter/interpret-program
empty-push-state '(3 5 :integer_eq :exec_if (1 "yes") (2 "no"))
1000) state/empty-state
1000)
#_(interpreter/interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if #_(interpreter/interpret-program
(in1 " I am asking." string_concat) '(in1 :string_reverse 1 :string_take "?" :string_eq :exec_if
(in1 " I am saying." string_concat)) (in1 " I am asking." :string_concat)
(assoc empty-push-state :input {:in1 "Can you hear me?"}) (in1 " I am saying." :string_concat))
1000) (assoc state/empty-state :input {:in1 "Can you hear me?"})
1000)
#_(interpreter/interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if #_(interpreter/interpret-program
(in1 " I am asking." string_concat) '(in1 :string_reverse 1 :string_take "?" :string_eq :exec_if
(in1 " I am saying." string_concat)) (in1 " I am asking." :string_concat)
(assoc empty-push-state :input {:in1 "I can hear you."}) (in1 " I am saying." :string_concat))
1000) (assoc state/empty-state :input {:in1 "I can hear you."})
1000)
#_(genome/plushy->push (genome/make-random-plushy push/default-instructions 20)) #_(genome/plushy->push
(genome/make-random-plushy push/default-instructions 20))
#_(interpreter/interpret-program (genome/plushy->push (genome/make-random-plushy push/default-instructions 20)) #_(interpreter/interpret-program
(assoc empty-push-state :input {:in1 "I can hear you."}) (genome/plushy->push
1000) (genome/make-random-plushy push/default-instructions 20))
(assoc state/empty-state :input {:in1 "I can hear you."})
1000)
;; =============================================================================
;; Target function: f(x) = x^3 + x + 3 ;; Target function: f(x) = x^3 + x + 3
;; =============================================================================
#_(gp/gp {:instructions push/default-instructions #_(gp/gp {:instructions push/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/gp {:instructions push/default-instructions #_(gp/gp {:instructions push/default-instructions
:error-function string-classification-error-function :error-function string-classif/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 :lexicase}) :parent-selection :lexicase})

View File

@ -1,4 +1,4 @@
(ns tools.calculus) (ns propeller.tools.calculus)
(defonce ^:const dx 0.0001) (defonce ^:const dx 0.0001)

View File

@ -1,4 +1,4 @@
(ns tools.character) (ns propeller.tools.character)
(defn is-letter (defn is-letter
"Returns true if the given character is a letter, A-Z or a-z." "Returns true if the given character is a letter, A-Z or a-z."

View File

@ -1,10 +1,10 @@
(ns tools.distributions (ns propeller.tools.distributions
(:require [tools.math :as math]) (:require (propeller.tools [calculus :as calculus]
(:require [tools.calculus :as calculus])) [math :as math])))
;; ----------------------------------------------------------------------------- ;; =============================================================================
;; NORMAL ;; NORMAL
;; ----------------------------------------------------------------------------- ;; =============================================================================
(defn- box-muller (defn- box-muller
"Given two uniformly distributed random variables (from 0 to 1), returns a "Given two uniformly distributed random variables (from 0 to 1), returns a

View File

@ -1,4 +1,4 @@
(ns tools.math) (ns propeller.tools.math)
(defonce PI #?(:clj Math/PI (defonce PI #?(:clj Math/PI
:cljs js/Math.PI)) :cljs js/Math.PI))

View File

@ -1,5 +1,5 @@
(ns tools.metrics (ns propeller.tools.metrics
(:require [tools.math :as math])) (:require [propeller.tools.math :as math]))
(defn mean (defn mean
"Returns the mean of a collection." "Returns the mean of a collection."