Move tools module for ClojureScript compatibility, and style fixes
This commit is contained in:
parent
64d43756b6
commit
4bd92503a3
@ -2,24 +2,27 @@
|
||||
(:gen-class)
|
||||
(: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]])))
|
||||
(propeller.problems [simple-regression :as regression]
|
||||
[string-classification :as string-classif])))
|
||||
|
||||
(defn -main
|
||||
"Runs propel-gp, giving it a map of arguments."
|
||||
[& args]
|
||||
(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 %)))))
|
||||
(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 %)))))
|
||||
|
@ -1,7 +1,7 @@
|
||||
(ns propeller.gp
|
||||
(:require [propeller.push.core :refer [instruction-table]]
|
||||
(propeller [genome :as genome]
|
||||
[variation :as variation])))
|
||||
(:require (propeller [genome :as genome]
|
||||
[variation :as variation])
|
||||
[propeller.push.core :as push]))
|
||||
|
||||
(defn report
|
||||
"Reports information each generation."
|
||||
@ -33,14 +33,14 @@
|
||||
(require '[propeller.push.instructions boolean char code input-output
|
||||
numeric polymorphic string])
|
||||
(println "Done. Registered instructions:")
|
||||
(println (sort (keys @instruction-table))))
|
||||
(println (sort (keys @push/instruction-table))))
|
||||
;;
|
||||
(loop [generation 0
|
||||
population (repeatedly
|
||||
population-size
|
||||
#(hash-map :plushy
|
||||
(genome/make-random-plushy instructions
|
||||
max-initial-plushy-size)))]
|
||||
max-initial-plushy-size)))]
|
||||
(let [evaluated-pop (sort-by :total-error
|
||||
(map (partial error-function argmap)
|
||||
population))]
|
||||
|
@ -1,9 +1,8 @@
|
||||
(ns propeller.problems.simple-regression
|
||||
(:require [propeller.genome :refer [plushy->push]]
|
||||
[propeller.push.interpreter :refer [interpret-program]]
|
||||
[propeller.push.state :refer [empty-state
|
||||
peek-stack]]
|
||||
[tools.math :as math]))
|
||||
(:require [propeller.genome :as genome]
|
||||
(propeller.push [interpreter :as interpreter]
|
||||
[state :as state])
|
||||
[propeller.tools.math :as math]))
|
||||
|
||||
;; =============================================================================
|
||||
;; Problem: f(x) = 7x^2 - 20x + 13
|
||||
@ -19,20 +18,20 @@
|
||||
[x]
|
||||
(+ (* 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
|
||||
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
|
||||
final top item on the INTEGER stack."
|
||||
[argmap individual]
|
||||
(let [program (plushy->push (:plushy individual))
|
||||
(let [program (genome/plushy->push (:plushy individual))
|
||||
inputs (range -10 11)
|
||||
correct-outputs (map target-function inputs)
|
||||
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))
|
||||
:integer))
|
||||
inputs)
|
||||
|
@ -1,13 +1,13 @@
|
||||
(ns propeller.problems.string-classification
|
||||
(:require [propeller.genome :as genome]
|
||||
(propeller.push [state :as state]
|
||||
[interpreter :as interpreter])))
|
||||
(propeller.push [interpreter :as interpreter]
|
||||
[state :as state])))
|
||||
|
||||
;; =============================================================================
|
||||
;; 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
|
||||
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
|
||||
|
@ -1,6 +1,4 @@
|
||||
(ns propeller.push.core
|
||||
(:require [propeller.push.state :refer [get-args-from-stacks
|
||||
push-to-stack]]))
|
||||
(ns propeller.push.core)
|
||||
|
||||
;; =============================================================================
|
||||
;; PushGP Instructions
|
||||
@ -13,6 +11,8 @@
|
||||
;; TMH: ERCs?
|
||||
;; =============================================================================
|
||||
|
||||
(def instruction-table (atom (hash-map)))
|
||||
|
||||
;; Set of original propel instructions
|
||||
(def default-instructions
|
||||
(list :in1
|
||||
@ -46,12 +46,6 @@
|
||||
"G"
|
||||
"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)
|
||||
(def opens {:exec_dup 1
|
||||
:exec_if 2})
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns propeller.push.instructions.boolean
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.utils :refer [make-instruction]]))
|
||||
(:require [propeller.push.utils :refer [def-instruction
|
||||
make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; BOOLEAN Instructions
|
||||
|
@ -1,7 +1,7 @@
|
||||
(ns propeller.push.instructions.char
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.utils :refer [make-instruction]]
|
||||
[tools.character :as char]))
|
||||
(:require [propeller.push.utils :refer [def-instruction
|
||||
make-instruction]]
|
||||
[propeller.tools.character :as char]))
|
||||
|
||||
;; =============================================================================
|
||||
;; CHAR Instructions
|
||||
|
@ -1,7 +1,7 @@
|
||||
(ns propeller.push.instructions.code
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.push.utils :refer [make-instruction]]))
|
||||
(:require (propeller.push [state :as state]
|
||||
[utils :refer [def-instruction
|
||||
make-instruction]])))
|
||||
|
||||
;; =============================================================================
|
||||
;; CODE and EXEC Instructions
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns propeller.push.instructions.input-output
|
||||
(:require [propeller.push.state :as state]
|
||||
[propeller.push.core :refer [def-instruction]]))
|
||||
(:require (propeller.push [state :as state]
|
||||
[utils :refer [def-instruction]])))
|
||||
|
||||
;; =============================================================================
|
||||
;; INPUT and OUTPUT Instructions
|
||||
|
@ -1,8 +1,8 @@
|
||||
(ns propeller.push.instructions.numeric
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.utils :refer [generate-functions
|
||||
(:require [propeller.push.utils :refer [def-instruction
|
||||
generate-functions
|
||||
make-instruction]]
|
||||
[tools.math :as math]))
|
||||
[propeller.tools.math :as math]))
|
||||
|
||||
;; =============================================================================
|
||||
;; FLOAT and INTEGER Instructions (polymorphic)
|
||||
|
@ -1,11 +1,8 @@
|
||||
(ns propeller.push.instructions.polymorphic
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.state :refer [empty-stack?
|
||||
peek-stack
|
||||
pop-stack
|
||||
push-to-stack]]
|
||||
[propeller.push.utils :refer [generate-functions
|
||||
make-instruction]]))
|
||||
(:require (propeller.push [state :as state]
|
||||
[utils :refer [def-instruction
|
||||
generate-functions
|
||||
make-instruction]])))
|
||||
|
||||
;; =============================================================================
|
||||
;; Polymorphic Instructions
|
||||
@ -24,10 +21,10 @@
|
||||
;; would negate the effect of the duplication)
|
||||
(defn- _dup
|
||||
[stack state]
|
||||
(let [top-item (peek-stack state stack)]
|
||||
(if (empty-stack? state stack)
|
||||
(let [top-item (state/peek-stack state stack)]
|
||||
(if (state/empty-stack? state stack)
|
||||
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
|
||||
;; its argument (since that would negate the effect of the duplication). The
|
||||
@ -39,10 +36,10 @@
|
||||
(if (or (and (= stack :integer)
|
||||
(>= (count (:integer state)) 2))
|
||||
(and (not= stack :integer)
|
||||
(not (empty-stack? state :integer))
|
||||
(not (empty-stack? state stack))))
|
||||
(let [n (peek-stack state :integer)
|
||||
item-to-duplicate (peek-stack state stack)]
|
||||
(not (state/empty-stack? state :integer))
|
||||
(not (state/empty-stack? state stack))))
|
||||
(let [n (state/peek-stack state :integer)
|
||||
item-to-duplicate (state/peek-stack state stack)]
|
||||
nil)
|
||||
state))
|
||||
|
||||
@ -54,7 +51,7 @@
|
||||
;; Pushes TRUE onto the BOOLEAN stack if the stack is empty. Otherwise FALSE
|
||||
(defn- _empty
|
||||
[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
|
||||
(defn- _flush
|
||||
@ -64,7 +61,7 @@
|
||||
;; Pops the given stack
|
||||
(defn- _pop
|
||||
[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
|
||||
;; pushes it on top). Equivalent to (yank state stack-type 2)
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns propeller.push.instructions.string
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.utils :refer [make-instruction]]))
|
||||
(:require [propeller.push.utils :refer [def-instruction
|
||||
make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; STRING Instructions
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns propeller.push.interpreter
|
||||
(:require [propeller.push.core :refer [instruction-table]]
|
||||
[propeller.push.state :as state]))
|
||||
(:require (propeller.push [core :as push]
|
||||
[state :as state])))
|
||||
|
||||
(defn interpret-one-step
|
||||
"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)
|
||||
first-instruction-raw (first (:exec state))
|
||||
first-instruction (if (keyword? first-instruction-raw)
|
||||
(first-instruction-raw @instruction-table)
|
||||
(first-instruction-raw @push/instruction-table)
|
||||
first-instruction-raw)]
|
||||
(cond
|
||||
(fn? first-instruction)
|
||||
|
@ -1,6 +1,10 @@
|
||||
(ns propeller.push.utils
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.state :as state]))
|
||||
(:require (propeller.push [core :as push]
|
||||
[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
|
||||
;; to apply to the args, the stacks to take the args from, and the stack to
|
||||
|
@ -1,53 +1,62 @@
|
||||
(ns propeller.session
|
||||
(:require (propeller [gp :as gp]
|
||||
[variation :as variation]
|
||||
(:require (propeller [genome :as genome]
|
||||
[gp :as gp]
|
||||
[selection :as selection]
|
||||
[genome :as genome])
|
||||
(propeller.push [interpreter :as interpreter]
|
||||
[core :as push]
|
||||
[variation :as variation])
|
||||
(propeller.push [core :as push]
|
||||
[interpreter :as interpreter]
|
||||
[state :as state])
|
||||
(propeller.problems [simple-regression :refer [regression-error-function]]
|
||||
[string-classification :refer [string-classification-error-function]])))
|
||||
(propeller.problems [simple-regression :as regression]
|
||||
[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"))
|
||||
empty-push-state
|
||||
1000)
|
||||
#_(interpreter/interpret-program
|
||||
'(3 5 :integer_eq :exec_if (1 "yes") (2 "no"))
|
||||
state/empty-state
|
||||
1000)
|
||||
|
||||
#_(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)
|
||||
#_(interpreter/interpret-program
|
||||
'(in1 :string_reverse 1 :string_take "?" :string_eq :exec_if
|
||||
(in1 " I am asking." :string_concat)
|
||||
(in1 " I am saying." :string_concat))
|
||||
(assoc state/empty-state :input {:in1 "Can you hear me?"})
|
||||
1000)
|
||||
|
||||
#_(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)
|
||||
#_(interpreter/interpret-program
|
||||
'(in1 :string_reverse 1 :string_take "?" :string_eq :exec_if
|
||||
(in1 " I am asking." :string_concat)
|
||||
(in1 " I am saying." :string_concat))
|
||||
(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))
|
||||
(assoc empty-push-state :input {:in1 "I can hear you."})
|
||||
1000)
|
||||
#_(interpreter/interpret-program
|
||||
(genome/plushy->push
|
||||
(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
|
||||
;; =============================================================================
|
||||
|
||||
#_(gp/gp {:instructions push/default-instructions
|
||||
:error-function regression-error-function
|
||||
:max-generations 50
|
||||
:population-size 200
|
||||
:max-initial-plushy-size 50
|
||||
:step-limit 100
|
||||
:parent-selection :tournament
|
||||
:tournament-size 5})
|
||||
:error-function regression/error-function
|
||||
:max-generations 50
|
||||
:population-size 200
|
||||
:max-initial-plushy-size 50
|
||||
:step-limit 100
|
||||
:parent-selection :tournament
|
||||
:tournament-size 5})
|
||||
|
||||
#_(gp/gp {:instructions push/default-instructions
|
||||
:error-function string-classification-error-function
|
||||
:max-generations 50
|
||||
:population-size 200
|
||||
:max-initial-plushy-size 50
|
||||
:step-limit 100
|
||||
:parent-selection :lexicase})
|
||||
:error-function string-classif/error-function
|
||||
:max-generations 50
|
||||
:population-size 200
|
||||
:max-initial-plushy-size 50
|
||||
:step-limit 100
|
||||
:parent-selection :lexicase})
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns tools.calculus)
|
||||
(ns propeller.tools.calculus)
|
||||
|
||||
(defonce ^:const dx 0.0001)
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns tools.character)
|
||||
(ns propeller.tools.character)
|
||||
|
||||
(defn is-letter
|
||||
"Returns true if the given character is a letter, A-Z or a-z."
|
@ -1,10 +1,10 @@
|
||||
(ns tools.distributions
|
||||
(:require [tools.math :as math])
|
||||
(:require [tools.calculus :as calculus]))
|
||||
(ns propeller.tools.distributions
|
||||
(:require (propeller.tools [calculus :as calculus]
|
||||
[math :as math])))
|
||||
|
||||
;; -----------------------------------------------------------------------------
|
||||
;; =============================================================================
|
||||
;; NORMAL
|
||||
;; -----------------------------------------------------------------------------
|
||||
;; =============================================================================
|
||||
|
||||
(defn- box-muller
|
||||
"Given two uniformly distributed random variables (from 0 to 1), returns a
|
@ -1,4 +1,4 @@
|
||||
(ns tools.math)
|
||||
(ns propeller.tools.math)
|
||||
|
||||
(defonce PI #?(:clj Math/PI
|
||||
:cljs js/Math.PI))
|
@ -1,5 +1,5 @@
|
||||
(ns tools.metrics
|
||||
(:require [tools.math :as math]))
|
||||
(ns propeller.tools.metrics
|
||||
(:require [propeller.tools.math :as math]))
|
||||
|
||||
(defn mean
|
||||
"Returns the mean of a collection."
|
Loading…
x
Reference in New Issue
Block a user