Merge pull request #35 from thelmuth/fix/def-instruction-not-macro
Fix/def instruction not macro
This commit is contained in:
commit
7c9ff00dc1
@ -1,5 +1,5 @@
|
||||
(ns propeller.genome
|
||||
(:require [propeller.push.core :as push]
|
||||
(:require [propeller.push.instructions :as instructions]
|
||||
[propeller.utils :as utils]))
|
||||
|
||||
(defn make-random-plushy
|
||||
@ -16,7 +16,12 @@
|
||||
(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
|
||||
plushy (mapcat #(if-let [n (get push/opens %)] [% ['open n]] [%]) plushy)]
|
||||
plushy (mapcat #(let [n (get instructions/opens %)]
|
||||
(if (and n
|
||||
(> n 0))
|
||||
[% ['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
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,9 +3,8 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[clojure.pprint :as pprint]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
#?(:cljs [cljs.reader :refer [read-string]])))
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.metrics :as metrics]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.metrics :as metrics]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.metrics :as metrics]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.gp :as gp]
|
||||
#?(:cljs [cljs.reader :refer [read-string]])))
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.metrics :as metrics]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.metrics :as metrics]
|
||||
[propeller.gp :as gp]
|
||||
|
@ -3,9 +3,8 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.tools.metrics :as metrics]
|
||||
[propeller.gp :as gp]
|
||||
#?(:cljs [cljs.reader :refer [read-string]])))
|
||||
|
@ -3,9 +3,8 @@
|
||||
[propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.tools.metrics :as metrics]
|
||||
[propeller.gp :as gp]
|
||||
#?(:cljs [cljs.reader :refer [read-string]])))
|
||||
|
@ -2,9 +2,8 @@
|
||||
(:require [propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.tools.math :as math]
|
||||
[propeller.gp :as gp]
|
||||
#?(:cljs [cljs.reader :refer [read-string]])))
|
||||
@ -99,8 +98,8 @@
|
||||
:error-function error-function
|
||||
:training-data (:train train-and-test-data)
|
||||
:testing-data (:test train-and-test-data)
|
||||
:max-generations 500
|
||||
:population-size 500
|
||||
:max-generations 300
|
||||
:population-size 1000
|
||||
:max-initial-plushy-size 100
|
||||
:step-limit 200
|
||||
:parent-selection :lexicase
|
||||
|
@ -2,9 +2,8 @@
|
||||
(:require [propeller.genome :as genome]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]
|
||||
[propeller.push.instructions :refer [get-stack-instructions]]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.gp :as gp]
|
||||
#?(:cljs [cljs.reader :refer [read-string]])))
|
||||
|
||||
@ -80,10 +79,7 @@
|
||||
:print))
|
||||
inputs)
|
||||
errors (map (fn [correct-output output]
|
||||
(let [parsed-output (try (read-string output)
|
||||
#?(:clj (catch Exception e 1000.0)
|
||||
:cljs (catch js/Error. e 1000.0)))]
|
||||
(if (= correct-output parsed-output) 0 1)))
|
||||
(if (= (str correct-output) output) 0 1))
|
||||
correct-outputs
|
||||
outputs)]
|
||||
(assoc individual
|
||||
@ -101,8 +97,8 @@
|
||||
:error-function error-function
|
||||
:training-data (:train train-and-test-data)
|
||||
:testing-data (:test train-and-test-data)
|
||||
:max-generations 500
|
||||
:population-size 500
|
||||
:max-generations 300
|
||||
:population-size 1000
|
||||
:max-initial-plushy-size 100
|
||||
:step-limit 200
|
||||
:parent-selection :lexicase
|
||||
|
BIN
src/propeller/push/.DS_Store
vendored
BIN
src/propeller/push/.DS_Store
vendored
Binary file not shown.
@ -1,15 +0,0 @@
|
||||
(ns propeller.push.core)
|
||||
|
||||
;; PushGP instructions are represented as keywords, and stored in an atom. They
|
||||
;; can be either constant literals or functions that take and return a Push state
|
||||
(def instruction-table (atom (hash-map)))
|
||||
|
||||
;; Number of blocks opened by instructions (default = 0)
|
||||
(def opens {:exec_dup 1
|
||||
:exec_if 2
|
||||
:exec_when 1
|
||||
:exec_while 1
|
||||
:exec_do_while 1
|
||||
:exec_k 2
|
||||
:exec_s 3
|
||||
:exec_y 1})
|
154
src/propeller/push/instructions.cljc
Normal file
154
src/propeller/push/instructions.cljc
Normal file
@ -0,0 +1,154 @@
|
||||
(ns propeller.push.instructions
|
||||
(:require [clojure.set]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.utils :as u]
|
||||
#?(:cljs [goog.string :as gstring])
|
||||
#?(:cljs [goog.string.format])))
|
||||
|
||||
;; PushGP instructions are represented as keywords, and stored in an atom. They
|
||||
;; can be either constant literals or functions that take and return a Push state
|
||||
(def instruction-table (atom (hash-map)))
|
||||
|
||||
;; Number of blocks opened by instructions (default = 0)
|
||||
(def opens {:exec_dup 1
|
||||
:exec_dup_times 1
|
||||
:exec_dup_items 0 ; explicitly set to 0 to make it clear that this is intended
|
||||
:exec_eq 0 ; explicitly set to 0 to make it clear that this is intended
|
||||
:exec_pop 1
|
||||
:exec_rot 3
|
||||
:exec_shove 1
|
||||
:exec_swap 2
|
||||
:exec_yank 0 ; explicitly set to 0 to make it clear that this is intended
|
||||
:exec_yank_dup 0 ; explicitly set to 0 to make it clear that this is intended
|
||||
:exec_deep_dup 0 ; explicitly set to 0 to make it clear that this is intended
|
||||
:exec_print 1
|
||||
:exec_if 2
|
||||
:exec_when 1
|
||||
:exec_while 1
|
||||
:exec_do_while 1
|
||||
:exec_do_range 1
|
||||
:exec_do_count 1
|
||||
:exec_do_times 1
|
||||
:exec_k 2
|
||||
:exec_s 3
|
||||
:exec_y 1
|
||||
:string_iterate 1
|
||||
:vector_boolean_iterate 1
|
||||
:vector_string_iterate 1
|
||||
:vector_integer_iterate 1
|
||||
:vector_float_iterate 1
|
||||
})
|
||||
|
||||
|
||||
#?(:clj
|
||||
(def cls->type
|
||||
{Boolean :boolean
|
||||
Short :integer
|
||||
Integer :integer
|
||||
Long :integer
|
||||
BigInteger :integer
|
||||
Double :float
|
||||
BigDecimal :float
|
||||
Float :float
|
||||
Character :char
|
||||
String :string}))
|
||||
|
||||
#?(:cljs
|
||||
(def pred->type
|
||||
[[boolean? :boolean]
|
||||
[int? :integer]
|
||||
[float? :float]
|
||||
[string? :string]
|
||||
[char? :char]]))
|
||||
|
||||
(defn get-literal-type
|
||||
"If a piece of data is a literal, return its corresponding stack name
|
||||
e.g. `:integer`. Otherwise, return `nil`."
|
||||
[data]
|
||||
(or (when (vector? data)
|
||||
(if (empty? data)
|
||||
:generic-vector
|
||||
(keyword (str "vector_" (name (get-literal-type (u/first-non-nil data)))))))
|
||||
#?(:clj (cls->type (type data))
|
||||
:cljs (loop [remaining pred->type]
|
||||
(let [[pred d-type] (first remaining)]
|
||||
(cond
|
||||
(empty? remaining) nil
|
||||
(pred data) d-type
|
||||
:else (recur (rest remaining))))))))
|
||||
|
||||
(defn get-vector-literal-type
|
||||
"Returns the literal stack corresponding to some vector stack."
|
||||
[vector-stack]
|
||||
(get state/vec-stacks vector-stack))
|
||||
|
||||
(defn def-instruction
|
||||
"Defines a Push instruction as a keyword-function pair, and adds it to the
|
||||
instruction table"
|
||||
[instruction function]
|
||||
(swap! instruction-table assoc instruction function))
|
||||
|
||||
(defn make-metadata
|
||||
"Given a generic function, e.g. _dup, and a stack type to instantiate it for,
|
||||
e.g. :char, returns the appropriate stack metadata for that function instance"
|
||||
[function stack]
|
||||
(->> (:stacks (meta function))
|
||||
(replace {:elem (get-vector-literal-type stack)})
|
||||
(cons stack)
|
||||
set
|
||||
(assoc-in (meta function) [:stacks])
|
||||
(#(dissoc % :name))))
|
||||
|
||||
(defn generate-instructions
|
||||
"Given a sequence of stacks, e.g. [:float :integer], and a sequence of suffix
|
||||
function strings, e.g. [_add, _mult, _eq], automates the generation of all
|
||||
possible combination instructions, which here would be :float_add, :float_mult,
|
||||
:float_eq, :integer_add, :integer_mult, and :integer_eq, also transferring
|
||||
and updating the generic function's stack-type metadata. For some vector
|
||||
instructions, the placeholder :elem will be replaced with the stack of the
|
||||
corresponding element type (e.g. for :vector_integer, with :integer)"
|
||||
[stacks functions]
|
||||
(doseq [stack stacks
|
||||
func functions]
|
||||
(let [instruction-name (keyword (str (name stack) (:name (meta func))))
|
||||
metadata (make-metadata func stack)
|
||||
new-func (with-meta (partial func stack) metadata)]
|
||||
(def-instruction instruction-name new-func))))
|
||||
|
||||
|
||||
(defn make-instruction
|
||||
"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
|
||||
return the result to. Applies the function to the args (popped from the
|
||||
given stacks), and pushes the result onto the return-stack.
|
||||
|
||||
If the function returns :ignore-instruction, then we will return the
|
||||
initial state unchanged. This allows instructions to fail gracefully
|
||||
without consuming stack values."
|
||||
[state function arg-stacks return-stack]
|
||||
(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)]
|
||||
(if (= result :ignore-instruction)
|
||||
state
|
||||
(state/push-to-stack new-state return-stack result))))))
|
||||
|
||||
(defn get-stack-instructions
|
||||
"Given a set of stacks, returns all instructions that operate on those stacks
|
||||
only. Won't include random instructions unless :random is in the set as well"
|
||||
[stacks]
|
||||
(doseq [[instruction-name function] @instruction-table]
|
||||
(assert
|
||||
(:stacks (meta function))
|
||||
#?(:clj (format
|
||||
"ERROR: Instruction %s does not have :stacks defined in metadata."
|
||||
(name instruction-name))
|
||||
:cljs (gstring/format
|
||||
"ERROR: Instruction %s does not have :stacks defined in metadata."
|
||||
(name instruction-name)))))
|
||||
(for [[instruction-name function] @instruction-table
|
||||
:when (clojure.set/subset? (:stacks (meta function)) stacks)]
|
||||
instruction-name))
|
||||
|
@ -1,7 +1,6 @@
|
||||
(ns propeller.push.instructions.bool
|
||||
#?(:cljs (:require-macros [propeller.push.utils.macros :refer [def-instruction]]))
|
||||
(:require [propeller.push.utils.helpers :refer [make-instruction]]
|
||||
#?(:clj [propeller.push.utils.macros :refer [def-instruction]])))
|
||||
(:require [propeller.push.instructions :refer [def-instruction
|
||||
make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; BOOLEAN Instructions
|
||||
|
@ -1,9 +1,8 @@
|
||||
(ns propeller.push.instructions.character
|
||||
#?(:cljs (:require-macros [propeller.push.utils.macros :refer [def-instruction]]))
|
||||
(:require [propeller.push.state :as state]
|
||||
[propeller.push.utils.helpers :refer [make-instruction]]
|
||||
[propeller.tools.character :as char]
|
||||
#?(:clj [propeller.push.utils.macros :refer [def-instruction]])))
|
||||
[propeller.push.instructions :refer [def-instruction
|
||||
make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; CHAR Instructions
|
||||
|
@ -1,9 +1,8 @@
|
||||
(ns propeller.push.instructions.code
|
||||
#?(:cljs (:require-macros [propeller.push.utils.macros :refer [def-instruction]]))
|
||||
(:require [propeller.utils :as utils]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.push.utils.helpers :refer [make-instruction]]
|
||||
#?(:clj [propeller.push.utils.macros :refer [def-instruction]])))
|
||||
[propeller.push.instructions :refer [def-instruction
|
||||
make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; CODE Instructions
|
||||
|
@ -1,10 +1,6 @@
|
||||
(ns propeller.push.instructions.input-output
|
||||
#?(:cljs (:require-macros
|
||||
[propeller.push.utils.macros :refer [def-instruction
|
||||
generate-instructions]]))
|
||||
(:require [propeller.push.state :as state]
|
||||
[propeller.push.utils.helpers :refer [make-instruction]]
|
||||
[propeller.push.utils.macros :refer [def-instruction
|
||||
[propeller.push.instructions :refer [def-instruction
|
||||
generate-instructions]]))
|
||||
|
||||
;; =============================================================================
|
||||
|
@ -1,12 +1,8 @@
|
||||
(ns propeller.push.instructions.numeric
|
||||
#?(:cljs (:require-macros
|
||||
[propeller.push.utils.macros :refer [def-instruction
|
||||
generate-instructions]]))
|
||||
(:require [propeller.push.utils.helpers :refer [make-instruction]]
|
||||
[propeller.tools.math :as math]
|
||||
#?(:cljs [cljs.reader :refer [read-string]]
|
||||
:clj [propeller.push.utils.macros :refer [def-instruction
|
||||
generate-instructions]])))
|
||||
(:require [propeller.tools.math :as math]
|
||||
[propeller.push.instructions :refer [def-instruction
|
||||
generate-instructions
|
||||
make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; FLOAT and INTEGER Instructions (polymorphic)
|
||||
|
@ -1,13 +1,10 @@
|
||||
(ns propeller.push.instructions.polymorphic
|
||||
#?(:cljs (:require-macros
|
||||
[propeller.push.utils.macros :refer [def-instruction
|
||||
generate-instructions]]))
|
||||
(:require [propeller.utils :as utils]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.push.utils.helpers :refer [make-instruction]]
|
||||
[propeller.push.utils.limits :as limit]
|
||||
#?(:clj [propeller.push.utils.macros :refer [def-instruction
|
||||
generate-instructions]])))
|
||||
[propeller.push.limits :as limit]
|
||||
[propeller.push.instructions :refer [def-instruction
|
||||
generate-instructions
|
||||
make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; Polymorphic Instructions
|
||||
|
@ -1,10 +1,8 @@
|
||||
(ns propeller.push.instructions.string
|
||||
#?(:cljs (:require-macros
|
||||
[propeller.push.utils.macros :refer [def-instruction]]))
|
||||
(:require [clojure.string :as string]
|
||||
[propeller.push.utils.helpers :refer [make-instruction]]
|
||||
[propeller.push.state :as state]
|
||||
#?(:clj [propeller.push.utils.macros :refer [def-instruction]])))
|
||||
[propeller.push.instructions :refer [def-instruction
|
||||
make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; STRING Instructions
|
||||
|
@ -1,11 +1,10 @@
|
||||
(ns propeller.push.instructions.vector
|
||||
#?(:cljs (:require-macros [propeller.push.utils.macros :refer [generate-instructions]]))
|
||||
(:require [clojure.string]
|
||||
[propeller.utils :as utils]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.push.utils.helpers :refer [get-vector-literal-type
|
||||
make-instruction]]
|
||||
#?(:clj [propeller.push.utils.macros :refer [generate-instructions]])))
|
||||
[propeller.push.instructions :refer [generate-instructions
|
||||
make-instruction
|
||||
get-vector-literal-type]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; VECTOR Instructions
|
||||
|
@ -1,20 +1,19 @@
|
||||
(ns propeller.push.interpreter
|
||||
(:require [propeller.push.core :as push]
|
||||
(:require [propeller.push.instructions :as instructions]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.push.instructions.input-output :as io]
|
||||
[propeller.push.utils.helpers :refer [get-literal-type]]))
|
||||
[propeller.push.instructions.input-output :as io]))
|
||||
|
||||
(defn interpret-one-step
|
||||
"Takes a Push state and executes the next instruction on the exec stack."
|
||||
[state]
|
||||
(let [popped-state (state/pop-stack state :exec)
|
||||
instruction (first (:exec state))
|
||||
literal-type (get-literal-type instruction)] ; nil for non-literals
|
||||
literal-type (instructions/get-literal-type instruction)] ; nil for non-literals
|
||||
(cond
|
||||
;;
|
||||
;; Recognize functional instruction or input instruction
|
||||
(keyword? instruction)
|
||||
(if-let [function (instruction @push/instruction-table)]
|
||||
(if-let [function (instruction @instructions/instruction-table)]
|
||||
(function popped-state)
|
||||
(io/handle-input-instruction popped-state instruction))
|
||||
;;
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns propeller.push.utils.limits
|
||||
(ns propeller.push.limits
|
||||
(:require [propeller.utils :as u]))
|
||||
|
||||
;; =============================================================================
|
@ -1,5 +1,5 @@
|
||||
(ns propeller.push.state
|
||||
(:require [propeller.push.utils.limits :as l]
|
||||
(:require [propeller.push.limits :as l]
|
||||
#?(:cljs [goog.string :as gstring])))
|
||||
|
||||
;; Empty push state - all available stacks are empty
|
||||
|
@ -1,86 +0,0 @@
|
||||
(ns propeller.push.utils.helpers
|
||||
(:require [clojure.set]
|
||||
[propeller.push.core :as push]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.utils :as u]
|
||||
#?(:cljs [goog.string :as gstring])
|
||||
#?(:cljs [goog.string.format])))
|
||||
|
||||
;; 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
|
||||
;; return the result to. Applies the function to the args (popped from the
|
||||
;; given stacks), and pushes the result onto the return-stack.
|
||||
;;
|
||||
;; If the function returns :ignore-instruction, then we will return the
|
||||
;; initial state unchanged. This allows instructions to fail gracefully
|
||||
;; without consuming stack values.
|
||||
(defn make-instruction
|
||||
[state function arg-stacks return-stack]
|
||||
(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)]
|
||||
(if (= result :ignore-instruction)
|
||||
state
|
||||
(state/push-to-stack new-state return-stack result))))))
|
||||
|
||||
;; Given a set of stacks, returns all instructions that operate on those stacks
|
||||
;; only. Won't include random instructions unless :random is in the set as well
|
||||
(defn get-stack-instructions
|
||||
[stacks]
|
||||
(doseq [[instruction-name function] @push/instruction-table]
|
||||
(assert
|
||||
(:stacks (meta function))
|
||||
#?(:clj (format
|
||||
"ERROR: Instruction %s does not have :stacks defined in metadata."
|
||||
(name instruction-name))
|
||||
:cljs (gstring/format
|
||||
"ERROR: Instruction %s does not have :stacks defined in metadata."
|
||||
(name instruction-name)))))
|
||||
(for [[instruction-name function] @push/instruction-table
|
||||
:when (clojure.set/subset? (:stacks (meta function)) stacks)]
|
||||
instruction-name))
|
||||
|
||||
|
||||
#?(:clj
|
||||
(def cls->type
|
||||
{Boolean :boolean
|
||||
Short :integer
|
||||
Integer :integer
|
||||
Long :integer
|
||||
BigInteger :integer
|
||||
Double :float
|
||||
BigDecimal :float
|
||||
Float :float
|
||||
Character :char
|
||||
String :string}))
|
||||
|
||||
#?(:cljs
|
||||
(def pred->type
|
||||
[[boolean? :boolean]
|
||||
[int? :integer]
|
||||
[float? :float]
|
||||
[string? :string]
|
||||
[char? :char]]))
|
||||
|
||||
(defn get-literal-type
|
||||
"If a piece of data is a literal, return its corresponding stack name
|
||||
e.g. `:integer`. Otherwise, return `nil`."
|
||||
[data]
|
||||
(or (when (vector? data)
|
||||
(if (empty? data)
|
||||
:generic-vector
|
||||
(keyword (str "vector_" (name (get-literal-type (u/first-non-nil data)))))))
|
||||
#?(:clj (cls->type (type data))
|
||||
:cljs (loop [remaining pred->type]
|
||||
(let [[pred d-type] (first remaining)]
|
||||
(cond
|
||||
(empty? remaining) nil
|
||||
(pred data) d-type
|
||||
:else (recur (rest remaining))))))))
|
||||
|
||||
(defn get-vector-literal-type
|
||||
"Returns the literal stack corresponding to some vector stack."
|
||||
[vector-stack]
|
||||
(get state/vec-stacks vector-stack))
|
@ -1,35 +0,0 @@
|
||||
(ns propeller.push.utils.macros
|
||||
(:require [propeller.push.core :as push]
|
||||
[propeller.push.utils.helpers :refer [get-vector-literal-type]]))
|
||||
|
||||
;; Defines a Push instruction as a keyword-function pair, and adds it to the
|
||||
;; instruction table
|
||||
(defmacro def-instruction
|
||||
[instruction definition]
|
||||
`(swap! push/instruction-table assoc ~instruction ~definition))
|
||||
|
||||
;; Given a generic function, e.g. _dup, and a stack type to instantiate it for,
|
||||
;; e.g. :char, returns the appropriate stack metadata for that function instance
|
||||
(defmacro make-metadata
|
||||
[function stack]
|
||||
`(->> (:stacks (meta ~function))
|
||||
(replace {:elem (get-vector-literal-type ~stack)})
|
||||
(cons ~stack)
|
||||
set
|
||||
(assoc-in (meta ~function) [:stacks])
|
||||
(#(dissoc % :name))))
|
||||
|
||||
;; Given a sequence of stacks, e.g. [:float :integer], and a sequence of suffix
|
||||
;; function strings, e.g. [_add, _mult, _eq], automates the generation of all
|
||||
;; possible combination instructions, which here would be :float_add, :float_mult,
|
||||
;; :float_eq, :integer_add, :integer_mult, and :integer_eq, also transferring
|
||||
;; and updating the generic function's stack-type metadata. For some vector
|
||||
;; instructions, the placeholder :elem will be replaced with the stack of the
|
||||
;; corresponding element type (e.g. for :vector_integer, with :integer)
|
||||
(defmacro generate-instructions [stacks functions]
|
||||
`(doseq [stack# ~stacks
|
||||
func# ~functions
|
||||
:let [instruction-name# (keyword (str (name stack#) (:name (meta func#))))
|
||||
metadata# (make-metadata func# stack#)
|
||||
new-func# (with-meta (partial func# stack#) metadata#)]]
|
||||
(def-instruction instruction-name# new-func#)))
|
@ -5,10 +5,9 @@
|
||||
[propeller.variation :as variation]
|
||||
[propeller.problems.simple-regression :as regression]
|
||||
[propeller.problems.string-classification :as string-classif]
|
||||
[propeller.push.core :as push]
|
||||
[propeller.push.instructions :as instructions]
|
||||
[propeller.push.interpreter :as interpreter]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.push.utils.helpers :refer [get-stack-instructions]]))
|
||||
[propeller.push.state :as state]))
|
||||
|
||||
#_(interpreter/interpret-program
|
||||
'(1 2 :integer_add) state/empty-state 1000)
|
||||
@ -36,7 +35,7 @@
|
||||
; 1000)
|
||||
;
|
||||
;#_(genome/plushy->push
|
||||
; (genome/make-random-plushy (get-stack-instructions #{:float :integer :exec :boolean}) 20))
|
||||
; (genome/make-random-plushy (instructions/get-stack-instructions #{:float :integer :exec :boolean}) 20))
|
||||
;
|
||||
;#_(gp/gp {:instructions propeller.problems.software.number-io/instructions
|
||||
; :error-function propeller.problems.software.number-io/error-function
|
||||
|
Loading…
x
Reference in New Issue
Block a user