From 68bab201437ab496463acdba82814023aed0b13f Mon Sep 17 00:00:00 2001
From: Ryan Boldi <ryan.boldi123@gmail.com>
Date: Sun, 8 Jan 2023 15:08:29 +0100
Subject: [PATCH] prepped for integer and float regression runs

---
 src/propeller/gp.cljc                         |  4 +-
 src/propeller/problems/float_regression.cljc  | 82 +++++++++++++++++++
 ...egression.cljc => integer_regression.cljc} | 10 +--
 3 files changed, 89 insertions(+), 7 deletions(-)
 create mode 100644 src/propeller/problems/float_regression.cljc
 rename src/propeller/problems/{simple_regression.cljc => integer_regression.cljc} (93%)
 mode change 100755 => 100644

diff --git a/src/propeller/gp.cljc b/src/propeller/gp.cljc
index 9ea78d6..ae738bf 100644
--- a/src/propeller/gp.cljc
+++ b/src/propeller/gp.cljc
@@ -42,7 +42,7 @@
            dont-end false
            ds-parent-rate 0
            ds-parent-gens 1
-           ids-type :solved ; :solved or :elite
+           ids-type :solved ; :solved or :elite or :soft
            downsample? false
            ;; The `mapper` will perform a `map`-like operation to apply a function to every individual
            ;; in the population. The default is `map` but other options include `mapv`, or `pmap`.
@@ -126,6 +126,6 @@
                                                                                 #(variation/new-individual reindexed-pop argmap)))))
                      (if downsample?
                       (if (zero? (mod generation ds-parent-gens))
-                        (downsample/update-case-distances rep-evaluated-pop indexed-training-data indexed-training-data ids-type) ; update distances every ds-parent-gens generations
+                        (downsample/update-case-distances rep-evaluated-pop indexed-training-data indexed-training-data ids-type (/ solution-error-threshold (count indexed-training-data))) ; update distances every ds-parent-gens generations
                         indexed-training-data)
                        indexed-training-data))))))
\ No newline at end of file
diff --git a/src/propeller/problems/float_regression.cljc b/src/propeller/problems/float_regression.cljc
new file mode 100644
index 0000000..f7c8ca4
--- /dev/null
+++ b/src/propeller/problems/float_regression.cljc
@@ -0,0 +1,82 @@
+(ns propeller.problems.float-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) = (1+ x^3)^3 + 1"
+  [x]
+  (inc (* (inc (* x x x)) (inc (* x x x)) (inc (* x x x)))))
+
+(def train-and-test-data
+  (let [train-inputs (range -1.5 1.5 0.1)
+        test-inputs (range -1.75 1.75 0.05)]
+    {: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
+  (list :in1
+        :float_add
+        :float_subtract
+        :float_mult
+        :float_quot
+        :float_eq
+        :exec_dup
+        :exec_if
+        'close
+        0
+        1))
+
+(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 FLOAT 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))
+                          :float))
+                      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))))))
+
+(defn -main
+  "Runs propel-gp, giving it a map of arguments."
+  [& args]
+  (gp/gp
+    (merge
+      {: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  100
+       :step-limit               200
+       :parent-selection         :lexicase
+       :tournament-size          5
+       :umad-rate                0.1
+       :solution-error-treshold  0.5
+       :variation                {:umad 1.0 :crossover 0.0}
+       :elitism                  false}
+      (apply hash-map (map #(if (string? %) (read-string %) %) args))))
+  (#?(:clj shutdown-agents)))
diff --git a/src/propeller/problems/simple_regression.cljc b/src/propeller/problems/integer_regression.cljc
old mode 100755
new mode 100644
similarity index 93%
rename from src/propeller/problems/simple_regression.cljc
rename to src/propeller/problems/integer_regression.cljc
index 3f84e9f..ff60213
--- a/src/propeller/problems/simple_regression.cljc
+++ b/src/propeller/problems/integer_regression.cljc
@@ -1,4 +1,4 @@
-(ns propeller.problems.simple-regression
+(ns propeller.problems.integer-regression
   (:require [propeller.genome :as genome]
             [propeller.push.interpreter :as interpreter]
             [propeller.push.state :as state]
@@ -7,9 +7,9 @@
             #?(:cljs [cljs.reader :refer [read-string]])))
 
 (defn- target-function
-  "Target function: f(x) = x^3 + x + 3"
+  "Target function: f(x) = x^3 + 2*x^2 + x + 3"
   [x]
-  (+ (* x x x) x 3))
+  (+ (* x x x) (* 2 x x) x 3))
 
 (def train-and-test-data
   (let [train-inputs (range -10 11)
@@ -68,8 +68,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