Compare commits

..

No commits in common. "239f3cb4c15ef68bd5bdba88bbf7b0728e15a425" and "a4703d60a85f4848297c52394eceacb95dc1d9b7" have entirely different histories.

6 changed files with 17 additions and 244 deletions

View File

@ -1,92 +0,0 @@
(ns propeller.problems.regression.stock-regression
(:require [propeller.genome :as genome]
[propeller.push.interpreter :as interpreter]
[propeller.push.state :as state]
[propeller.tools.math :as math]
[propeller.gp :as gp]
#?(:cljs [cljs.reader :refer [read-string]])))
(defn- target-function
"Target function: f(x) = x^3 + 2*x^2 + x + 3"
[x]
(+ (* x x x) (* 2 x x) x 3))
(def train-and-test-data
"Training data: Inputs and outputs with -10 <= x < 11
Test data: Inputs and outputs of -20 <= x < -10 and 11 <= x < 21"
(let [train-inputs (range -10 11)
test-inputs (concat (range -20 -10) (range 11 21))]
{:train (map (fn [x] {:input1 (vector x) :output1 (vector (target-function x))}) train-inputs)
:test (map (fn [x] {:input1 (vector x) :output1 (vector (target-function x))}) test-inputs)}))
(def instructions
"stack-specific instructions, input instructions, close, and constants"
(list :in1
:integer_add
:integer_subtract
:integer_mult
:integer_quot
:integer_eq
:exec_dup
:exec_if
'close
0
1
:buy
:sell
:hold
))
(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 data individual]
(let [program (genome/plushy->push (:plushy individual) argmap)
inputs (map (fn [x] (first (:input1 x))) data)
correct-outputs (map (fn [x] (first (:output1 x))) data)
outputs (map (fn [input]
(state/peek-stack
(interpreter/interpret-program
program
(assoc state/empty-state :input {:in1 input})
(:step-limit argmap))
:integer))
inputs)
errors (map (fn [correct-output output]
(if (= output :no-stack-item)
1000000
(math/abs (- correct-output output))))
correct-outputs
outputs)]
(assoc individual
:behaviors outputs
:errors errors
:total-error #?(:clj (apply +' errors)
:cljs (apply + errors))))))
(def integer-argmap
{:instructions instructions
:error-function error-function
:training-data (:train train-and-test-data)
:testing-data (:test train-and-test-data)
:max-generations 300
:population-size 1000
:max-initial-plushy-size 5
:step-limit 200
:parent-selection :lexicase
:tournament-size 5
:umad-rate 0.1
:variation {:umad 1.0 :crossover 0.0}
:elitism false})
(defn -main
"Runs the top-level genetic programming function, giving it a map of
arguments with defaults that can be overridden from the command line
or through a passed map."
[& args]
(gp/gp
(merge
integer-argmap
(apply hash-map (map #(if (string? %) (read-string %) %) args)))))

View File

@ -20,36 +20,6 @@
(fn [stack state] (fn [stack state]
(make-instruction state > [stack stack] :boolean))) (make-instruction state > [stack stack] :boolean)))
;; Pushes :buy onto the SIGNAL stack if the first item is greater than the second
;; item, and acts as a no-op otherwise.
(def _gt_buy
"Pushes :buy onto the SIGNAL stack if the first item is greater
than the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_gt_buy"}
(fn [stack state]
(make-instruction state #(if (> %1 %2) :buy nil) [stack stack] :signal)))
;; Pushes :sell onto the SIGNAL stack if the first item is greater than the second
;; item, and acts as a no-op otherwise.
(def _gt_sell
"Pushes :sell onto the SIGNAL stack if the first item is greater
than the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_gt_sell"}
(fn [stack state]
(make-instruction state #(if (> %1 %2) :sell nil) [stack stack] :signal)))
;; Pushes :hold onto the SIGNAL stack if the first item is greater than the second
;; item, and acts as a no-op otherwise.
(def _gt_hold
"Pushes :hold onto the SIGNAL stack if the first item is greater
than the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_gt_hold"}
(fn [stack state]
(make-instruction state #(if (> %1 %2) :hold nil) [stack stack] :signal)))
;; Pushes TRUE onto the BOOLEAN stack if the second item is greater than or ;; Pushes TRUE onto the BOOLEAN stack if the second item is greater than or
;; equal to the top item, and FALSE otherwise ;; equal to the top item, and FALSE otherwise
(def _gte (def _gte
@ -60,36 +30,6 @@
(fn [stack state] (fn [stack state]
(make-instruction state >= [stack stack] :boolean))) (make-instruction state >= [stack stack] :boolean)))
;; Pushes :buy onto the SIGNAL stack if the first item is greater than or equal to the second
;; item, and acts as a no-op otherwise.
(def _gte_buy
"Pushes :buy onto the SIGNAL stack if the first item is greater
than or equal to the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_gte_buy"}
(fn [stack state]
(make-instruction state #(if (>= %1 %2) :buy nil) [stack stack] :signal)))
;; Pushes :sell onto the SIGNAL stack if the first item is greater than or equal to the second
;; item, and acts as a no-op otherwise.
(def _gte_sell
"Pushes :sell onto the SIGNAL stack if the first item is greater
than or equal to the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_gte_sell"}
(fn [stack state]
(make-instruction state #(if (>= %1 %2) :sell nil) [stack stack] :signal)))
;; Pushes :hold onto the SIGNAL stack if the first item is greater than or equal to the second
;; item, and acts as a no-op otherwise.
(def _gte_hold
"Pushes :hold onto the SIGNAL stack if the first item is greater
than or equal to the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_gte_hold"}
(fn [stack state]
(make-instruction state #(if (>= %1 %2) :hold nil) [stack stack] :signal)))
;; Pushes TRUE onto the BOOLEAN stack if the second item is less than the top ;; Pushes TRUE onto the BOOLEAN stack if the second item is less than the top
;; item, and FALSE otherwise ;; item, and FALSE otherwise
(def _lt (def _lt
@ -100,36 +40,6 @@
(fn [stack state] (fn [stack state]
(make-instruction state < [stack stack] :boolean))) (make-instruction state < [stack stack] :boolean)))
;; Pushes :buy onto the SIGNAL stack if the first item is less than the second
;; item, and acts as a no-op otherwise.
(def _lt_buy
"Pushes :buy onto the SIGNAL stack if the first item is less
than the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_lt_buy"}
(fn [stack state]
(make-instruction state #(if (< %1 %2) :buy nil) [stack stack] :signal)))
;; Pushes :sell onto the SIGNAL stack if the first item is less than the second
;; item, and acts as a no-op otherwise.
(def _lt_sell
"Pushes :sell onto the SIGNAL stack if the first item is less
than the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_lt_sell"}
(fn [stack state]
(make-instruction state #(if (< %1 %2) :sell nil) [stack stack] :signal)))
;; Pushes :hold onto the SIGNAL stack if the first item is less than the second
;; item, and acts as a no-op otherwise.
(def _lt_hold
"Pushes :hold onto the SIGNAL stack if the first item is less
than the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_lt_hold"}
(fn [stack state]
(make-instruction state #(if (< %1 %2) :hold nil) [stack stack] :signal)))
;; Pushes TRUE onto the BOOLEAN stack if the second item is less than or equal ;; Pushes TRUE onto the BOOLEAN stack if the second item is less than or equal
;; to the top item, and FALSE otherwise ;; to the top item, and FALSE otherwise
(def _lte (def _lte
@ -140,36 +50,6 @@
(fn [stack state] (fn [stack state]
(make-instruction state <= [stack stack] :boolean))) (make-instruction state <= [stack stack] :boolean)))
;; Pushes :buy onto the SIGNAL stack if the first item is less than or equal to the second
;; item, and acts as a no-op otherwise.
(def _lte_buy
"Pushes :buy onto the SIGNAL stack if the first item is less
than or equal to the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_lte_buy"}
(fn [stack state]
(make-instruction state #(if (<= %1 %2) :buy nil) [stack stack] :signal)))
;; Pushes :sell onto the SIGNAL stack if the first item is less than or equal to the second
;; item, and acts as a no-op otherwise.
(def _lte_sell
"Pushes :sell onto the SIGNAL stack if the first item is less
than or equal to the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_lte_sell"}
(fn [stack state]
(make-instruction state #(if (<= %1 %2) :sell nil) [stack stack] :signal)))
;; Pushes :hold onto the SIGNAL stack if the first item is less than or equal to the second
;; item, and acts as a no-op otherwise.
(def _lte_hold
"Pushes :hold onto the SIGNAL stack if the first item is less
than or equal to the second item, and acts as a no-op otherwise"
^{:stacks #{:signal}
:name "_lte_hold"}
(fn [stack state]
(make-instruction state #(if (<= %1 %2) :hold nil) [stack stack] :signal)))
;; Pushes the sum of the top two items onto the same stack ;; Pushes the sum of the top two items onto the same stack
(def _add (def _add
"Pushes the sum of the top two items onto the same stack" "Pushes the sum of the top two items onto the same stack"
@ -293,11 +173,11 @@ Otherwise, acts as a NOOP"
(fn [stack state] (fn [stack state]
(make-instruction state dec [stack] stack))) (make-instruction state dec [stack] stack)))
;; 2 types x 16 functions = 32 instructions
(generate-instructions (generate-instructions
[:float :integer] [:float :integer]
[_gt _gte _lt _lte _add _subtract _mult _quot _mod _max _min _inc _dec [_gt _gte _lt _lte _add _subtract _mult _quot _mod _max _min _inc _dec
_from_boolean _from_char _from_string _gt_buy _gt_sell _gt_hold _gte_buy _from_boolean _from_char _from_string])
_gte_sell _gte_hold _lt_buy _lt_sell _lt_hold _lte_buy _lte_sell _lte_hold])
;; ============================================================================= ;; =============================================================================
;; FLOAT Instructions only ;; FLOAT Instructions only

View File

@ -232,9 +232,9 @@
(state/push-to-stack popped-state stack indexed-item)) (state/push-to-stack popped-state stack indexed-item))
state))) state)))
;; 12 types x 13 functions = 156 instructions ;; 11 types x 13 functions = 143 instructions
(generate-instructions (generate-instructions
[:boolean :char :code :exec :float :integer :string [:boolean :char :code :exec :float :integer :string
:vector_boolean :vector_float :vector_integer :vector_string :signal] :vector_boolean :vector_float :vector_integer :vector_string]
[_dup _dup_times _dup_items _empty _eq _flush _pop _rot _shove [_dup _dup_times _dup_items _empty _eq _flush _pop _rot _shove
_stack_depth _swap _yank _yank_dup _deep_dup]) _stack_depth _swap _yank _yank_dup _deep_dup])

View File

@ -1,8 +0,0 @@
(ns propeller.push.instructions.signal
"SIGNAL instructions. Instructions pertaining only to trading signals
are located here."
(:require [propeller.tools.math :as math]
[propeller.push.instructions :refer [def-instruction
generate-instructions
make-instruction]]))

View File

@ -11,11 +11,6 @@
instruction (first (:exec state)) instruction (first (:exec state))
literal-type (instructions/get-literal-type instruction)] ; nil for non-literals literal-type (instructions/get-literal-type instruction)] ; nil for non-literals
(cond (cond
;;
;; Catch the trading signal keywords before the other
;; keyword checks.
(some #(= instruction %) '(:buy :sell :hold))
(state/push-to-stack popped-state :signal instruction)
;; ;;
;; Recognize functional instruction or input instruction ;; Recognize functional instruction or input instruction
(keyword? instruction) (keyword? instruction)

View File

@ -5,21 +5,19 @@
;; Empty push state - all available stacks are empty ;; Empty push state - all available stacks are empty
(defonce ^:no-doc empty-state {:boolean '() (defonce ^:no-doc empty-state {:boolean '()
:char '() :char '()
:code '() :code '()
:exec '() :exec '()
:float '() :float '()
:input {} :input {}
:output {} :output {}
:integer '() :integer '()
:print '("") :print '("")
:string '() :string '()
:vector_boolean '() :vector_boolean '()
:vector_float '() :vector_float '()
:vector_integer '() :vector_integer '()
:vector_string '() :vector_string '()})
:signal '() ;; stock trading signal (:buy, :sell, or :hold only), long only for now
})
;; All stack types available in a Push state ;; All stack types available in a Push state
(defonce ^:no-doc stacks (set (keys empty-state))) (defonce ^:no-doc stacks (set (keys empty-state)))