Namespace cleanup and add polymorphic instructions
This commit is contained in:
parent
73b3963b90
commit
f04804b00b
@ -1,9 +1,9 @@
|
||||
(ns propeller.core
|
||||
(:gen-class)
|
||||
(:require [propeller.push.instructions boolean char code input-output numeric random string])
|
||||
(:use propeller.gp
|
||||
propeller.push.instructions
|
||||
[propeller.problems simple-regression string-classification]))
|
||||
(:require [propeller.gp :refer :all]
|
||||
[propeller.push.core :refer :all]
|
||||
(propeller.problems [simple-regression :refer :all]
|
||||
[string-classification :refer :all])))
|
||||
|
||||
(defn -main
|
||||
"Runs propel-gp, giving it a map of arguments."
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns propeller.genome
|
||||
(:use propeller.push.instructions))
|
||||
(:require [propeller.push.core :refer :all]))
|
||||
|
||||
(defn plushy->push
|
||||
"Returns the Push program expressed by the given plushy representation."
|
||||
|
@ -1,5 +1,7 @@
|
||||
(ns propeller.gp
|
||||
(:use [propeller genome variation]))
|
||||
(:require [propeller.push.core :refer [instruction-table]]
|
||||
(propeller [genome :refer :all]
|
||||
[variation :refer :all])))
|
||||
|
||||
(defn report
|
||||
"Reports information each generation."
|
||||
@ -24,7 +26,15 @@
|
||||
[{:keys [population-size max-generations error-function instructions
|
||||
max-initial-plushy-size]
|
||||
:as argmap}]
|
||||
(println "Starting GP with args:" argmap)
|
||||
;;
|
||||
(println "Starting GP with args: " argmap)
|
||||
;;
|
||||
(do (print "Registering instructions... ")
|
||||
(require '[propeller.push.instructions boolean char code input-output
|
||||
numeric polymorphic string])
|
||||
(println "Done. Registered instructions:")
|
||||
(println (sort (keys @instruction-table))))
|
||||
;;
|
||||
(loop [generation 0
|
||||
population (repeatedly
|
||||
population-size
|
||||
|
@ -1,6 +1,7 @@
|
||||
(ns propeller.problems.string-classification
|
||||
(:use propeller.genome
|
||||
[propeller.push state interpreter]))
|
||||
(:require [propeller.genome :refer :all]
|
||||
(propeller.push [state :refer :all]
|
||||
[interpreter :refer :all])))
|
||||
|
||||
;; =============================================================================
|
||||
;; String classification
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns propeller.push.instructions
|
||||
(ns propeller.push.core
|
||||
(:require [propeller.push.state :refer [get-args-from-stacks
|
||||
push-to-stack]]))
|
||||
|
@ -1,12 +1,10 @@
|
||||
(ns propeller.push.instructions.boolean
|
||||
(:require [propeller.push.instructions :refer [def-instruction]]
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.utils :refer [make-instruction]]))
|
||||
|
||||
;; Pushes TRUE if the top two BOOLEANs are equal, and FALSE otherwise
|
||||
(def-instruction
|
||||
:boolean_=
|
||||
(fn [state]
|
||||
(make-instruction state = [:boolean :boolean] :boolean)))
|
||||
;; =============================================================================
|
||||
;; BOOLEAN Instructions
|
||||
;; =============================================================================
|
||||
|
||||
;; Pushes the logical AND of the top two BOOLEANs
|
||||
(def-instruction
|
||||
|
@ -1,8 +1,12 @@
|
||||
(ns propeller.push.instructions.char
|
||||
(:require [propeller.push.instructions :refer [def-instruction]]
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.utils :refer [make-instruction]]
|
||||
[tools.character :as char]))
|
||||
|
||||
;; =============================================================================
|
||||
;; CHAR Instructions
|
||||
;; =============================================================================
|
||||
|
||||
;; Pushes TRUE onto the BOOLEAN stack if the popped character is a letter
|
||||
(def-instruction
|
||||
:char_isletter
|
||||
@ -22,13 +26,14 @@
|
||||
(fn [state]
|
||||
(make-instruction state char/is-whitespace [:char] :boolean)))
|
||||
|
||||
;; Pops the STRING stack and pushes the top element's constituent characters
|
||||
;; onto the CHAR stack, in order. For instance, "hello" will result in the
|
||||
;; top of the CHAR stack being o l l e h
|
||||
;; Pops the FLOAT stack, converts the top item to a whole number, and pushes
|
||||
;; its corresponding ASCII value onto the CHAR stack. Whole numbers larger than
|
||||
;; 128 will be reduced modulo 128. For instance, 248.45 will result in x being
|
||||
;; pushed.
|
||||
(def-instruction
|
||||
:char_allfromstring
|
||||
:char_fromfloat
|
||||
(fn [state]
|
||||
(make-instruction state #(map char %) [:string] :char)))
|
||||
(make-instruction state #(char (mod (long %) 128)) [:float] :char)))
|
||||
|
||||
;; Pops the INTEGER stack and pushes the top element's corresponding ASCII
|
||||
;; value onto the CHAR stack. Integers larger than 128 will be reduced modulo
|
||||
@ -38,11 +43,10 @@
|
||||
(fn [state]
|
||||
(make-instruction state #(char (mod % 128)) [:integer] :char)))
|
||||
|
||||
;; Pops the FLOAT stack, converts the top item to a whole number, and pushes
|
||||
;; its corresponding ASCII value onto the CHAR stack. Whole numbers larger than
|
||||
;; 128 will be reduced modulo 128. For instance, 248.45 will result in x being
|
||||
;; pushed.
|
||||
;; Pops the STRING stack and pushes the top element's constituent characters
|
||||
;; onto the CHAR stack, in order. For instance, "hello" will result in the
|
||||
;; top of the CHAR stack being o l l e h
|
||||
(def-instruction
|
||||
:char_fromfloat
|
||||
:char_allfromstring
|
||||
(fn [state]
|
||||
(make-instruction state #(char (mod (long %) 128)) [:float] :char)))
|
||||
(make-instruction state #(map char %) [:string] :char)))
|
||||
|
@ -1,8 +1,12 @@
|
||||
(ns propeller.push.instructions.code
|
||||
(:require [propeller.push.instructions :refer [def-instruction]]
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.state :as state]
|
||||
[propeller.push.utils :refer [make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; CODE and EXEC Instructions
|
||||
;; =============================================================================
|
||||
|
||||
(def-instruction
|
||||
:exec_dup
|
||||
(fn [state]
|
||||
|
@ -1,6 +1,10 @@
|
||||
(ns propeller.push.instructions.input-output
|
||||
(:require [propeller.push.state :as state]
|
||||
[propeller.push.instructions :refer [def-instruction]]))
|
||||
[propeller.push.core :refer [def-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; INPUT and OUTPUT Instructions
|
||||
;; =============================================================================
|
||||
|
||||
;; Pushes the input labeled :in1 on the inputs map onto the :exec stack
|
||||
(def-instruction
|
||||
|
@ -1,31 +1,37 @@
|
||||
(ns propeller.push.instructions.numeric
|
||||
(:require [propeller.push.instructions :refer [def-instruction]]
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.utils :refer [generate-functions
|
||||
make-instruction]]
|
||||
[tools.math :as math]))
|
||||
|
||||
;; =============================================================================
|
||||
;; FLOAT and INTEGER (polymorphic)
|
||||
;; FLOAT and INTEGER Instructions (polymorphic)
|
||||
;; =============================================================================
|
||||
|
||||
;; Pushes TRUE onto the BOOLEAN stack if the top two items are equal, and
|
||||
;; FALSE otherwise
|
||||
(defn- _=
|
||||
[stack state]
|
||||
(make-instruction state = [stack stack] :boolean))
|
||||
|
||||
;; Pushes TRUE onto the BOOLEAN stack if the second item is greater than the top
|
||||
;; item, and FALSE otherwise
|
||||
(defn- _>
|
||||
[stack state]
|
||||
(make-instruction state > [stack stack] :boolean))
|
||||
|
||||
;; Pushes TRUE onto the BOOLEAN stack if the second item is greater than or
|
||||
;; equal to the top item, and FALSE otherwise
|
||||
(defn- _>=
|
||||
[stack state]
|
||||
(make-instruction state >= [stack stack] :boolean))
|
||||
|
||||
;; Pushes TRUE onto the BOOLEAN stack if the second item is less than the top
|
||||
;; item, and FALSE otherwise
|
||||
(defn- _<
|
||||
[stack state]
|
||||
(make-instruction state < [stack stack] :boolean))
|
||||
|
||||
;; Pushes TRUE onto the BOOLEAN stack if the second item is less than or equal
|
||||
;; to the top item, and FALSE otherwise
|
||||
(defn- _<=
|
||||
[stack state]
|
||||
(make-instruction state <= [stack stack] :boolean))
|
||||
|
||||
;; Pushes the sum of the top two items onto the same stack
|
||||
(defn- _+
|
||||
[stack state]
|
||||
@ -48,7 +54,7 @@
|
||||
[stack state]
|
||||
(make-instruction state
|
||||
#(if (zero? %2)
|
||||
(list %1 %2) ; push both items back
|
||||
(list %1 %2) ; push both items back (NOOP)
|
||||
(quot %1 %2))
|
||||
[stack stack]
|
||||
stack))
|
||||
@ -61,7 +67,7 @@
|
||||
[stack state]
|
||||
(make-instruction state
|
||||
#(if (zero? %2)
|
||||
(list %1 %2) ; push both items back
|
||||
(list %1 %2) ; push both items back (NOOP)
|
||||
(mod %1 %2))
|
||||
[stack stack]
|
||||
stack))
|
||||
@ -80,21 +86,43 @@
|
||||
(defn- _fromboolean
|
||||
[stack state]
|
||||
(make-instruction state
|
||||
#((if (= stack :float) float int) (if % 1 0))
|
||||
#((if (= stack :integer) int float) (if % 1 0))
|
||||
[:boolean]
|
||||
stack))
|
||||
|
||||
;; Automate type-specific function generation. All resulting functions take a
|
||||
;; Push state as their only argument. For FLOAT and INTEGER, create one of each
|
||||
;; of the 11 following type-specific functions: =, >, <, +, -, *, QUOT, %, MAX,
|
||||
;; MIN, and FROMBOOLEAN. (22 functions total, with syntax e.g. integer_=,
|
||||
;; float_min etc.)
|
||||
;; Pushes the ASCII value of the top CHAR
|
||||
(defn- _fromchar
|
||||
[stack state]
|
||||
(make-instruction state (if (= stack :integer) int float) [:char] stack))
|
||||
|
||||
;; Pushes the value of the top STRING, if it can be parsed as a number.
|
||||
;; Otherwise, acts as a NOOP
|
||||
(defn- _fromstring
|
||||
[stack state]
|
||||
(make-instruction state
|
||||
#(try ((if (= stack :integer) int float) (read-string %))
|
||||
(catch Exception e))
|
||||
[:string]
|
||||
stack))
|
||||
|
||||
;; Pushes the increment (i.e. +1) of the top item of the stack
|
||||
(defn- _inc
|
||||
[stack state]
|
||||
(make-instruction state inc [stack] stack))
|
||||
|
||||
;; Pushes the decrement (i.e. -1) of the top item of the stack
|
||||
(defn- _dec
|
||||
[stack state]
|
||||
(make-instruction state dec [stack] stack))
|
||||
|
||||
;; 2 types x 16 functions = 32 instructions
|
||||
(generate-functions
|
||||
[:float :integer]
|
||||
[_=, _>, _<, _+, _-, _*, _quot, _%, _max, _min, _fromboolean])
|
||||
[_> _>= _< _<= _+ _- _* _quot _% _max _min _inc _dec
|
||||
_fromboolean _fromchar _fromstring])
|
||||
|
||||
;; =============================================================================
|
||||
;; FLOAT only
|
||||
;; FLOAT Instructions only
|
||||
;; =============================================================================
|
||||
|
||||
;; Pushes the cosine of the top FLOAT
|
||||
@ -115,20 +143,14 @@
|
||||
(fn [state]
|
||||
(make-instruction state math/tan [:float] :float)))
|
||||
|
||||
;; Pushes the tangent of the top FLOAT
|
||||
(def-instruction
|
||||
:float_tan
|
||||
(fn [state]
|
||||
(make-instruction state math/tan [:float] :float)))
|
||||
|
||||
;; Pushes a floating point version of the top INTEGER
|
||||
;; Pushes the floating point version of the top INTEGER
|
||||
(def-instruction
|
||||
:float_frominteger
|
||||
(fn [state]
|
||||
(make-instruction state math/tan [:float] :float)))
|
||||
(make-instruction state float [:integer] :float)))
|
||||
|
||||
;; =============================================================================
|
||||
;; INTEGER only
|
||||
;; INTEGER Instructions only
|
||||
;; =============================================================================
|
||||
|
||||
;; Pushes the result of truncating the top FLOAT towards negative infinity
|
||||
|
110
src/propeller/push/instructions/polymorphic.clj
Normal file
110
src/propeller/push/instructions/polymorphic.clj
Normal file
@ -0,0 +1,110 @@
|
||||
(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]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; Polymorphic Instructions
|
||||
;;
|
||||
;; (for all types, with the exception of non-data stacks like auxiliary, tag,
|
||||
;; input, and output)
|
||||
;; =============================================================================
|
||||
|
||||
;; Pushes TRUE onto the BOOLEAN stack if the top two items are equal.
|
||||
;; Otherwise FALSE
|
||||
(defn- _=
|
||||
[stack state]
|
||||
(make-instruction state = [stack stack] :boolean))
|
||||
|
||||
;; Duplicates the top item of the stack. Does not pop its argument (since that
|
||||
;; would negate the effect of the duplication)
|
||||
(defn- _dup
|
||||
[stack state]
|
||||
(let [top-item (peek-stack state stack)]
|
||||
(if (empty-stack? state stack)
|
||||
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
|
||||
;; number n is determined by the top INTEGER. For n = 0, equivalent to POP.
|
||||
;; For n = 1, equivalent to NOOP. For n = 2, equivalent to DUP. Negative values
|
||||
;; of n are treated as 0.
|
||||
(defn- _duptimes
|
||||
[stack state]
|
||||
(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)]
|
||||
nil)
|
||||
state))
|
||||
|
||||
|
||||
(defn- _dupitems
|
||||
[stack state]
|
||||
())
|
||||
|
||||
;; 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)))
|
||||
|
||||
;; Empties the given stack
|
||||
(defn- _flush
|
||||
[stack state]
|
||||
())
|
||||
|
||||
;; Pops the given stack
|
||||
(defn- _pop
|
||||
[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)
|
||||
(defn- _rot
|
||||
[stack state]
|
||||
())
|
||||
|
||||
;; Inserts the top item deeper into the stack, using the top INTEGER to
|
||||
;; determine how deep
|
||||
(defn- _shove
|
||||
[stack state]
|
||||
())
|
||||
|
||||
;; Pushes the given stack's depth onto the INTEGER stack
|
||||
(defn- _stackdepth
|
||||
[stack state]
|
||||
())
|
||||
|
||||
;; Swaps the top two items on the stack
|
||||
(defn- _swap
|
||||
[stack state]
|
||||
())
|
||||
|
||||
;; Removes an indexed item from deep in the stack. The top INTEGER is used to
|
||||
;; determine how deep to yank from
|
||||
(defn- _yank
|
||||
[stack state]
|
||||
())
|
||||
|
||||
;; Pushes a copy of an indexed item deep in the stack, without removing it.
|
||||
;; The top INTEGER is used to determine how deep to yankdup from
|
||||
(defn- _yankdup
|
||||
[stack state]
|
||||
())
|
||||
|
||||
;; 5 types x 1 function = 5 instructions
|
||||
(generate-functions [:boolean :char :float :integer :string] [_=])
|
||||
|
||||
;; 8 types x 12 function = 96 instructions
|
||||
(generate-functions
|
||||
[:boolean :char :code :exec :float :integer :string :zip]
|
||||
[_dup _duptimes _dupitems _empty _flush _pop _rot _shove _stackdepth
|
||||
_swap _yank _yankdup])
|
@ -1,17 +0,0 @@
|
||||
(ns propeller.push.instructions.random
|
||||
(:require [propeller.push.instructions :refer [def-instruction]]))
|
||||
|
||||
;;; Pushes a random BOOLEAN
|
||||
;(def-instruction
|
||||
; :boolean_rand
|
||||
; (fn [state]
|
||||
; (make-instruction state #(rand-nth [true false]) [] :boolean)))
|
||||
;
|
||||
;(defn- _rand
|
||||
; "For an INTEGER stack type, pushes a newly generated random INTEGER that is
|
||||
; greater than or equal to MIN-RANDOM-INTEGER and less than or equal to
|
||||
; MAX-RANDOM-INTEGER. Analogous for a FLOAT stack type, with its corresponding
|
||||
; MAX-RANDOM-FLOAT and MIN-RANDOM-FLOAT."
|
||||
; [state stack-type]
|
||||
; (let [data-type (keyword stack-type)]
|
||||
; ()))
|
@ -1,7 +1,11 @@
|
||||
(ns propeller.push.instructions.string
|
||||
(:require [propeller.push.instructions :refer [def-instruction]]
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.utils :refer [make-instruction]]))
|
||||
|
||||
;; =============================================================================
|
||||
;; STRING Instructions
|
||||
;; =============================================================================
|
||||
|
||||
(def-instruction
|
||||
:string_=
|
||||
(fn [state]
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns propeller.push.interpreter
|
||||
(:require [propeller.push.instructions :refer [instruction-table]])
|
||||
(:require [propeller.push.core :refer [instruction-table]])
|
||||
(:require [propeller.push.state :refer :all]))
|
||||
|
||||
(defn interpret-one-step
|
||||
|
@ -58,7 +58,9 @@
|
||||
(defn push-to-stack
|
||||
"Pushes item(s) onto stack."
|
||||
[state stack items]
|
||||
(update state stack (if (seq? items) into conj) items))
|
||||
(let [items-list (if (coll? items) items (list items))
|
||||
items-list-no-nil (filter #(not (nil? %)) items-list)] ; do not push nil items
|
||||
(update state stack into items-list-no-nil)))
|
||||
|
||||
(defn get-args-from-stacks
|
||||
"Takes a state and a collection of stacks to take args from. If there are
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns propeller.push.utils
|
||||
(:require [propeller.push.instructions :refer [def-instruction]]
|
||||
[propeller.push.state :as push-state]))
|
||||
(:require [propeller.push.core :refer [def-instruction]]
|
||||
[propeller.push.state :refer :all]))
|
||||
|
||||
;; 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 (push-state/get-args-from-stacks state arg-stacks)]
|
||||
(let [popped-args (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-state/push-to-stack new-state return-stack result)))))
|
||||
(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 push-state/stacks]
|
||||
(doseq [stack stacks]
|
||||
(printf "%-15s = " stack)
|
||||
(prn (if (get state stack) (get state stack) '()))
|
||||
(flush)))
|
||||
|
@ -1,7 +1,13 @@
|
||||
(ns propeller.session
|
||||
(:use [propeller core gp variation selection genome]
|
||||
[propeller.push interpreter instructions state]
|
||||
[propeller.problems simple-regression string-classification]))
|
||||
(: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])))
|
||||
|
||||
#_(interpret-program '(1 2 integer_+) empty-push-state 1000)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user