From 617b03aeb676227a6d36bf945f3233e42f436241 Mon Sep 17 00:00:00 2001 From: Rowan Torbitzky-Lane Date: Fri, 14 Mar 2025 00:48:43 -0500 Subject: [PATCH] start of stock regression --- .../problems/regression/stock_regression.cljc | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/propeller/problems/regression/stock_regression.cljc diff --git a/src/propeller/problems/regression/stock_regression.cljc b/src/propeller/problems/regression/stock_regression.cljc new file mode 100644 index 0000000..bb10464 --- /dev/null +++ b/src/propeller/problems/regression/stock_regression.cljc @@ -0,0 +1,92 @@ +(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)))))