From cddb60c63fc15f3ad1591c13342463659f812550 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Sat, 11 Jun 2022 10:24:45 -0400 Subject: [PATCH 01/13] data parsing works for data with strings now --- src/propeller/problems/data_creation.cljc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/propeller/problems/data_creation.cljc b/src/propeller/problems/data_creation.cljc index 193b14d..33c38e5 100644 --- a/src/propeller/problems/data_creation.cljc +++ b/src/propeller/problems/data_creation.cljc @@ -71,6 +71,12 @@ "grade" "count-odds"])) +(defn read-string-and-convert [elem] + (let [before (read-string elem)] + (if (symbol? before) + (str before) + before))) + (defn read-data-that-has-no-strings [problem train-or-test] (apply list (with-open [reader (io/reader (str "picked/" problem "-" train-or-test ".csv"))] (let [csv-data (csv/read-csv reader)] @@ -78,4 +84,5 @@ (->> (first csv-data) ;; First row is the header (map keyword) ;; Drop if you want string keys instead repeat) - (map (fn [elem] (map #(read-string %) elem)) (rest csv-data))))))) + (map (fn [elem] (map #(read-string-and-convert %) elem)) (rest csv-data))))))) + From 039769eaf6ca8a5454db5bf333b6087e2be6ca04 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Sat, 11 Jun 2022 10:30:51 -0400 Subject: [PATCH 02/13] gcd problem implemented --- src/propeller/problems/PSB2/fuel_cost.cljc | 4 ++-- src/propeller/problems/PSB2/gcd.cljc | 12 ++++++++---- src/propeller/problems/data_creation.cljc | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/propeller/problems/PSB2/fuel_cost.cljc b/src/propeller/problems/PSB2/fuel_cost.cljc index 071bf99..3c9379d 100644 --- a/src/propeller/problems/PSB2/fuel_cost.cljc +++ b/src/propeller/problems/PSB2/fuel_cost.cljc @@ -20,8 +20,8 @@ ; Source: https://arxiv.org/pdf/2106.06086.pdf ; ============================================================ -(def train-data (dc/read-data-that-has-no-strings "fuel-cost" "train")) -(def test-data (dc/read-data-that-has-no-strings "fuel-cost" "test")) +(def train-data (dc/read-data-formatted "fuel-cost" "train")) +(def test-data (dc/read-data-formatted "fuel-cost" "test")) ; Random integer between -100 and 100 (from smallest) (defn random-int [] (- (rand-int 201) 100)) diff --git a/src/propeller/problems/PSB2/gcd.cljc b/src/propeller/problems/PSB2/gcd.cljc index 209900e..9d0a948 100644 --- a/src/propeller/problems/PSB2/gcd.cljc +++ b/src/propeller/problems/PSB2/gcd.cljc @@ -2,6 +2,7 @@ (:require [psb2.core :as psb2] [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] + [propeller.problems.data-creation :as dc] [propeller.utils :as utils] [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] @@ -17,7 +18,10 @@ ; Source: https://arxiv.org/pdf/2106.06086.pdf ; ================================================================== -(def train-and-test-data (psb2/fetch-examples "data" "gcd" 200 2000)) +;(def train-and-test-data (psb2/fetch-examples "data" "gcd" 200 2000)) + +(def train-data (dc/read-data-formatted "gcd" "train")) +(def test-data (dc/read-data-formatted "gcd" "test")) (defn random-int [] (- (rand-int 201) 100)) @@ -76,9 +80,9 @@ (merge {:instructions instructions :error-function error-function - :training-data (:train train-and-test-data) - :testing-data (:test train-and-test-data) - :case-t-size (count (:train train-and-test-data)) + :training-data train-data + :testing-data test-data + :case-t-size (count train-data) :case-parent-rate 0 :case-parent-gens 1 :max-generations 300 diff --git a/src/propeller/problems/data_creation.cljc b/src/propeller/problems/data_creation.cljc index 33c38e5..de40c82 100644 --- a/src/propeller/problems/data_creation.cljc +++ b/src/propeller/problems/data_creation.cljc @@ -77,7 +77,7 @@ (str before) before))) -(defn read-data-that-has-no-strings [problem train-or-test] +(defn read-data-formatted [problem train-or-test] (apply list (with-open [reader (io/reader (str "picked/" problem "-" train-or-test ".csv"))] (let [csv-data (csv/read-csv reader)] (mapv zipmap From 39aa7a8cf303fb407daed10ee2305f35c2f93c9b Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Thu, 16 Jun 2022 11:14:43 -0400 Subject: [PATCH 03/13] implemented all problems but find-pair --- src/propeller/problems/PSB1/count_odds.cljc | 78 +++++++++++++ src/propeller/problems/PSB1/grade.cljc | 88 ++++++++++++++ .../problems/PSB1/scrabble_score.cljc | 108 ++++++++++++++++++ .../problems/PSB1/small_or_large.cljc | 80 +++++++++++++ src/propeller/problems/PSB2/fizz_buzz.cljc | 15 ++- src/propeller/problems/PSB2/gcd.cljc | 4 +- src/propeller/problems/data_creation.cljc | 17 ++- 7 files changed, 380 insertions(+), 10 deletions(-) create mode 100644 src/propeller/problems/PSB1/count_odds.cljc create mode 100644 src/propeller/problems/PSB1/grade.cljc create mode 100644 src/propeller/problems/PSB1/scrabble_score.cljc create mode 100644 src/propeller/problems/PSB1/small_or_large.cljc diff --git a/src/propeller/problems/PSB1/count_odds.cljc b/src/propeller/problems/PSB1/count_odds.cljc new file mode 100644 index 0000000..84a6ef7 --- /dev/null +++ b/src/propeller/problems/PSB1/count_odds.cljc @@ -0,0 +1,78 @@ +(ns propeller.problems.PSB1.count-odds + (:require [psb2.core :as psb2] + [propeller.genome :as genome] + [propeller.push.interpreter :as interpreter] + [propeller.problems.data-creation :as dc] + [propeller.utils :as utils] + [propeller.push.instructions :refer [get-stack-instructions]] + [propeller.push.state :as state] + [propeller.tools.math :as math] + [propeller.gp :as gp] + #?(:cljs [cljs.reader :refer [read-string]]))) + +(def train-data (dc/read-data-formatted "count-odds" "train")) +(def test-data (dc/read-data-formatted "count-odds" "test")) + +; Random integer between -100 and 100 (from smallest) +(defn random-int [] (- (rand-int 201) 100)) + +(def instructions + (utils/not-lazy + (concat + ;;; stack-specific instructions + (get-stack-instructions #{:exec :integer :boolean :vector_integer :print}) + ;;; input instructions + (list :in1) + ;;; close + (list 'close) + ;;; ERCs (constants) + (list random-int 0 1 2)))) + +(defn error-function + [argmap data individual] + (let [program (genome/plushy->push (:plushy individual) argmap) + inputs (map (fn [i] (get i :input1)) data) + correct-outputs (map (fn [i] (get i :output1)) 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))))) + +(defn -main + "Runs propel-gp, giving it a map of arguments." + [& args] + (gp/gp + (merge + {:instructions instructions + :error-function error-function + :training-data train-data + :testing-data test-data + :case-t-size (count train-data) + :ds-parent-rate 0 + :ds-parent-gens 1 + :max-generations 300 + :population-size 1000 + :max-initial-plushy-size 250 + :step-limit 2000 + :parent-selection :lexicase + :tournament-size 5 + :umad-rate 0.1 + :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/PSB1/grade.cljc b/src/propeller/problems/PSB1/grade.cljc new file mode 100644 index 0000000..399619e --- /dev/null +++ b/src/propeller/problems/PSB1/grade.cljc @@ -0,0 +1,88 @@ +(ns propeller.problems.PSB1.grade + (:require [propeller.genome :as genome] + [propeller.push.interpreter :as interpreter] + [propeller.problems.data-creation :as dc] + [propeller.push.state :as state] + [propeller.push.instructions :refer [get-stack-instructions]] + [propeller.utils :as utils] + [propeller.tools.metrics :as metrics] + [propeller.gp :as gp] + #?(:cljs [cljs.reader :refer [read-string]]))) + +;"“Student has a ”, “ grade.”, “A”, “B”, “C”, “D”, “F”, integer ERC" + +(def train-data (dc/read-data-formatted "grade" "train")) +(def test-data (dc/read-data-formatted "grade" "test")) + +(defn map-vals-input + "Returns all the input values of a map" + [i] + (vals (select-keys i [:input1 :input2 :input3 :input4 :input5]))) + +; Random integer between -100 and 100 +(defn random-int [] (- (rand-int 201) 100)) + +(def instructions + (utils/not-lazy + (concat + ;; stack-specific instructions + (get-stack-instructions #{:boolean :exec :integer :string :print}) + ;; input instructions + (list :in1 :in2 :in3 :in4 :in5) + ;;close + (list 'close) + ;; ERCs (constants) + (list "Student has a " " grade." "A" "B" "C" "D" "F" random-int)))) + +(defn error-function + [argmap data individual] + (let [program (genome/plushy->push (:plushy individual) argmap) + inputs (map (fn [i] (map-vals-input i)) data) + correct-outputs (map (fn [i] (get i :output1)) data) + outputs (map (fn [input] + (state/peek-stack + (interpreter/interpret-program + program + (assoc state/empty-state :input {:in1 (nth input 0) + :in2 (nth input 1) + :in3 (nth input 2) + :in4 (nth input 3) + :in5 (nth input 4)}) + (:step-limit argmap)) + :string)) + inputs) + errors (map (fn [correct-output output] + (if (= output :no-stack-item) + 1000000.0 + (metrics/levenshtein-distance 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-data + :testing-data test-data + :case-t-size (count train-data) + :ds-parent-rate 0 + :ds-parent-gens 1 + :max-generations 300 + :population-size 1000 + :max-initial-plushy-size 250 + :step-limit 2000 + :parent-selection :lexicase + :tournament-size 5 + :umad-rate 0.1 + :variation {:umad 1.0 :crossover 0.0} + :elitism false} + (apply hash-map (map #(if (string? %) (read-string %) %) args)))) + (#?(:clj shutdown-agents))) \ No newline at end of file diff --git a/src/propeller/problems/PSB1/scrabble_score.cljc b/src/propeller/problems/PSB1/scrabble_score.cljc new file mode 100644 index 0000000..d77ab53 --- /dev/null +++ b/src/propeller/problems/PSB1/scrabble_score.cljc @@ -0,0 +1,108 @@ +(ns propeller.problems.PSB1.scrabble-score + (:require [psb2.core :as psb2] + [propeller.genome :as genome] + [propeller.push.interpreter :as interpreter] + [clojure.string :as string] + [propeller.tools.math :as math] + [propeller.problems.data-creation :as dc] + [propeller.utils :as utils] + [propeller.push.instructions :refer [get-stack-instructions]] + [propeller.push.state :as state] + [propeller.tools.metrics :as metrics] + [propeller.gp :as gp] + #?(:cljs [cljs.reader :refer [read-string]]))) + +(def train-data (dc/scrabble-score-read-data-formatted "scrabble-score" "train")) +(def test-data (dc/scrabble-score-read-data-formatted "scrabble-score" "test")) + +(def scrabble-letter-values + (let [scrabble-map {\a 1 + \b 3 + \c 3 + \d 2 + \e 1 + \f 4 + \g 2 + \h 4 + \i 1 + \j 8 + \k 5 + \l 1 + \m 3 + \n 1 + \o 1 + \p 3 + \q 10 + \r 1 + \s 1 + \t 1 + \u 1 + \v 4 + \w 4 + \x 8 + \y 4 + \z 10} + visible-chars (map char (range 0 127))] + (vec (for [c visible-chars] + (get scrabble-map (first (string/lower-case c)) 0))))) + +(def instructions + (utils/not-lazy + (concat + ;;; stack-specific instructions + (get-stack-instructions #{:exec :integer :boolean :char :vector_integer :string :print}) + ;;; input instructions + (list :in1) + ;;; close + (list 'close) + ;;; ERCs (constants) + (list scrabble-letter-values)))) + +(defn error-function + [argmap data individual] + (let [program (genome/plushy->push (:plushy individual) argmap) + inputs (map (fn [i] (get i :input1)) data) + correct-outputs (map (fn [i] (get i :output1)) 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))))) + +(defn -main + "Runs propel-gp, giving it a map of arguments." + [& args] + (gp/gp + (merge + {:instructions instructions + :error-function error-function + :training-data train-data + :testing-data test-data + :case-t-size (count train-data) + :ds-parent-rate 0 + :ds-parent-gens 1 + :max-generations 300 + :population-size 1000 + :max-initial-plushy-size 250 + :step-limit 2000 + :parent-selection :lexicase + :tournament-size 5 + :umad-rate 0.1 + :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/PSB1/small_or_large.cljc b/src/propeller/problems/PSB1/small_or_large.cljc new file mode 100644 index 0000000..ca6512d --- /dev/null +++ b/src/propeller/problems/PSB1/small_or_large.cljc @@ -0,0 +1,80 @@ +(ns propeller.problems.PSB1.small-or-large + (:require [psb2.core :as psb2] + [propeller.genome :as genome] + [propeller.push.interpreter :as interpreter] + [propeller.problems.data-creation :as dc] + [propeller.utils :as utils] + [propeller.push.instructions :refer [get-stack-instructions]] + [propeller.push.state :as state] + [propeller.tools.metrics :as metrics] + [propeller.gp :as gp] + #?(:cljs [cljs.reader :refer [read-string]]))) + + +(def train-data (dc/read-data-formatted "small-or-large" "train")) +(def test-data (dc/read-data-formatted "small-or-large" "test")) + +; Random integer between -100 and 100 +(defn random-int [] (- (rand-int 201) 100)) + +(def instructions + (utils/not-lazy + (concat + ;;; stack-specific instructions + (get-stack-instructions #{:exec :integer :boolean :string :print}) + ;;; input instructions + (list :in1) + ;;; close + (list 'close) + ;;; ERCs (constants) + (list "small" "large" random-int)))) + +(defn error-function + [argmap data individual] + (let [program (genome/plushy->push (:plushy individual) argmap) + inputs (map (fn [i] (get i :input1)) data) + correct-outputs (map (fn [i] (get i :output1)) data) + outputs (map (fn [input] + (state/peek-stack + (interpreter/interpret-program + program + (assoc state/empty-state :input {:in1 input}) + (:step-limit argmap)) + :string)) + inputs) + errors (map (fn [correct-output output] + (if (= output :no-stack-item) + 10000 + (metrics/levenshtein-distance 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-data + :testing-data test-data + :case-t-size (count train-data) + :ds-parent-rate 0 + :ds-parent-gens 1 + :max-generations 300 + :population-size 1000 + :max-initial-plushy-size 250 + :step-limit 2000 + :parent-selection :lexicase + :tournament-size 5 + :umad-rate 0.1 + :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/PSB2/fizz_buzz.cljc b/src/propeller/problems/PSB2/fizz_buzz.cljc index d59fdda..773ca24 100644 --- a/src/propeller/problems/PSB2/fizz_buzz.cljc +++ b/src/propeller/problems/PSB2/fizz_buzz.cljc @@ -2,6 +2,7 @@ (:require [psb2.core :as psb2] [propeller.genome :as genome] [propeller.push.interpreter :as interpreter] + [propeller.problems.data-creation :as dc] [propeller.utils :as utils] [propeller.push.instructions :refer [get-stack-instructions]] [propeller.push.state :as state] @@ -19,7 +20,9 @@ ; Source: https://arxiv.org/pdf/2106.06086.pdf ; ============================================================ -(def train-and-test-data (psb2/fetch-examples "data" "fizz-buzz" 200 2000)) +(def train-data (dc/read-data-formatted "fizz-buzz" "train")) +(def test-data (dc/read-data-formatted "fizz-buzz" "test")) + (def instructions (utils/not-lazy @@ -66,11 +69,11 @@ (merge {:instructions instructions :error-function error-function - :training-data (:train train-and-test-data) - :testing-data (:test train-and-test-data) - :case-t-size (count (:train train-and-test-data)) - :case-parent-rate 0 - :case-parent-gens 1 + :training-data train-data + :testing-data test-data + :case-t-size (count train-data) + :ds-parent-rate 0 + :ds-parent-gens 1 :max-generations 300 :population-size 1000 :max-initial-plushy-size 250 diff --git a/src/propeller/problems/PSB2/gcd.cljc b/src/propeller/problems/PSB2/gcd.cljc index 9d0a948..9ef7355 100644 --- a/src/propeller/problems/PSB2/gcd.cljc +++ b/src/propeller/problems/PSB2/gcd.cljc @@ -83,8 +83,8 @@ :training-data train-data :testing-data test-data :case-t-size (count train-data) - :case-parent-rate 0 - :case-parent-gens 1 + :ds-parent-rate 0 + :ds-parent-gens 1 :max-generations 300 :population-size 1000 :max-initial-plushy-size 250 diff --git a/src/propeller/problems/data_creation.cljc b/src/propeller/problems/data_creation.cljc index de40c82..b08e8ed 100644 --- a/src/propeller/problems/data_creation.cljc +++ b/src/propeller/problems/data_creation.cljc @@ -72,10 +72,13 @@ "count-odds"])) (defn read-string-and-convert [elem] + (if (= elem "") + "" (let [before (read-string elem)] (if (symbol? before) - (str before) - before))) + elem + before)))) + (defn read-data-formatted [problem train-or-test] (apply list (with-open [reader (io/reader (str "picked/" problem "-" train-or-test ".csv"))] @@ -86,3 +89,13 @@ repeat) (map (fn [elem] (map #(read-string-and-convert %) elem)) (rest csv-data))))))) + +;scrabble-score doesn't play nice with read-string, hacky solution below +(defn scrabble-score-read-data-formatted [problem train-or-test] + (apply list (with-open [reader (io/reader (str "picked/" problem "-" train-or-test ".csv"))] + (let [csv-data (csv/read-csv reader)] + (mapv zipmap + (->> (first csv-data) ;; First row is the header + (map keyword) ;; Drop if you want string keys instead + repeat) + (map (fn [elem] (list (first elem) (read-string (second elem)))) (rest csv-data))))))) \ No newline at end of file From 98474297fb8abbfec3e4aec3a6333fabab878179 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Mon, 20 Jun 2022 22:30:08 -0400 Subject: [PATCH 04/13] Update small_or_large.cljc --- src/propeller/problems/PSB1/small_or_large.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/propeller/problems/PSB1/small_or_large.cljc b/src/propeller/problems/PSB1/small_or_large.cljc index ca6512d..d3106e4 100644 --- a/src/propeller/problems/PSB1/small_or_large.cljc +++ b/src/propeller/problems/PSB1/small_or_large.cljc @@ -27,7 +27,7 @@ ;;; close (list 'close) ;;; ERCs (constants) - (list "small" "large" random-int)))) + (list "" "small" "large" random-int)))) (defn error-function [argmap data individual] From 98d6881d68a8dd8304ef5f07c4d2c7c940d7f7e5 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Fri, 29 Jul 2022 10:48:50 -0400 Subject: [PATCH 05/13] Create find_pair.cljc --- src/propeller/problems/PSB2/find_pair.cljc | 106 +++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/propeller/problems/PSB2/find_pair.cljc diff --git a/src/propeller/problems/PSB2/find_pair.cljc b/src/propeller/problems/PSB2/find_pair.cljc new file mode 100644 index 0000000..4e71ea1 --- /dev/null +++ b/src/propeller/problems/PSB2/find_pair.cljc @@ -0,0 +1,106 @@ +(ns propeller.problems.PSB2.find-pair + (:require [psb2.core :as psb2] + [propeller.genome :as genome] + [propeller.push.interpreter :as interpreter] + [propeller.problems.data-creation :as dc] + [propeller.utils :as utils] + [propeller.push.instructions :refer [get-stack-instructions]] + [propeller.push.state :as state] + [propeller.tools.math :as math] + [propeller.gp :as gp] + #?(:cljs [cljs.reader :refer [read-string]]))) + +; =========== PROBLEM DESCRIPTION =============================== +; GCD [GREATEST COMMON DIVISOR] from PSB2 +; Given two integers, return the largest integer that divides each +; of the integers evenly +; +; Source: https://arxiv.org/pdf/2106.06086.pdf +; ================================================================== + +;(def train-and-test-data (psb2/fetch-examples "data" "gcd" 200 2000)) + +(def train-data (dc/read-data-formatted "find-pair" "train")) +(def test-data (dc/read-data-formatted "find-pair" "test")) + +(defn random-int [] (- (rand-int 201) 100)) + +(defn map-vals-input + "Returns all the input values of a map" + [i] + (vals (select-keys i [:input1 :input2]))) + +(defn map-vals-output + "Returns the output values of a map" + [i] + (vals (select-keys i [:output1 :output2]))) + +(def instructions + (utils/not-lazy + (concat + ;;; stack-specific instructions + (get-stack-instructions #{:exec :integer :vector_integer :boolean :string_print :integer_print}) + ;;; input instructions + (list :in1 :in2) + ;;; close + (list 'close) + ;;; ERCs (constants) + (list -1 0 1 2 random-int)))) + +(defn error-function + [argmap data individual] + (let [program (genome/plushy->push (:plushy individual) argmap) + inputs (map (fn [i] (map-vals-input i)) data) + correct-outputs (map (fn [i] (map-vals-output i)) data) + outputs (map (fn [input] + (state/peek-stack + (interpreter/interpret-program + program + (assoc state/empty-state :input {:in1 (nth input 0) + :in2 (nth input 1)}) + (:step-limit argmap)) + :print)) + inputs) + parsed-outputs (map (fn [output] + (try (read-string (str "(" output ")")) + #?(:clj (catch Exception e 1000000.0) + :cljs (catch js/Error. e 1000000.0)))) + outputs) + errors (map (fn [correct-output output] + (if (not= (count output) (count correct-output)) + 1000000.0 + (apply + (map (fn [c o] (if (and (number? c) (number? o)) + (math/abs (- c o)) + 1000000.0)) correct-output output)))) + correct-outputs + parsed-outputs) + null (prn {:output (first outputs) :correct-output (first correct-outputs) :parsed (first parsed-outputs) :error (first errors)})] + (assoc individual + :behaviors parsed-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-data + :testing-data test-data + :case-t-size (count train-data) + :ds-parent-rate 0 + :ds-parent-gens 1 + :max-generations 300 + :population-size 1000 + :max-initial-plushy-size 250 + :step-limit 2000 + :parent-selection :lexicase + :tournament-size 5 + :umad-rate 0.1 + :variation {:umad 1.0 :crossover 0.0} + :elitism false} + (apply hash-map (map #(if (string? %) (read-string %) %) args)))) + (#?(:clj shutdown-agents))) \ No newline at end of file From dd1fc992058567fc87c443032b74832d20fa735f Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Fri, 29 Jul 2022 10:50:08 -0400 Subject: [PATCH 06/13] Update find_pair.cljc --- src/propeller/problems/PSB2/find_pair.cljc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/propeller/problems/PSB2/find_pair.cljc b/src/propeller/problems/PSB2/find_pair.cljc index 4e71ea1..092ae8f 100644 --- a/src/propeller/problems/PSB2/find_pair.cljc +++ b/src/propeller/problems/PSB2/find_pair.cljc @@ -74,7 +74,8 @@ 1000000.0)) correct-output output)))) correct-outputs parsed-outputs) - null (prn {:output (first outputs) :correct-output (first correct-outputs) :parsed (first parsed-outputs) :error (first errors)})] + ;null (prn {:output (first outputs) :correct-output (first correct-outputs) :parsed (first parsed-outputs) :error (first errors)}) + ] (assoc individual :behaviors parsed-outputs :errors errors From 27e64b2362b1c0bb71eb8dc5d6e61d0536bb0bdc Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Sun, 31 Jul 2022 09:10:20 -0400 Subject: [PATCH 07/13] grade prints, scrabble score doesn't --- src/propeller/problems/PSB1/grade.cljc | 2 +- src/propeller/problems/PSB1/scrabble_score.cljc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/propeller/problems/PSB1/grade.cljc b/src/propeller/problems/PSB1/grade.cljc index 399619e..008ad95 100644 --- a/src/propeller/problems/PSB1/grade.cljc +++ b/src/propeller/problems/PSB1/grade.cljc @@ -49,7 +49,7 @@ :in4 (nth input 3) :in5 (nth input 4)}) (:step-limit argmap)) - :string)) + :print)) inputs) errors (map (fn [correct-output output] (if (= output :no-stack-item) diff --git a/src/propeller/problems/PSB1/scrabble_score.cljc b/src/propeller/problems/PSB1/scrabble_score.cljc index d77ab53..3518cc7 100644 --- a/src/propeller/problems/PSB1/scrabble_score.cljc +++ b/src/propeller/problems/PSB1/scrabble_score.cljc @@ -50,7 +50,7 @@ (utils/not-lazy (concat ;;; stack-specific instructions - (get-stack-instructions #{:exec :integer :boolean :char :vector_integer :string :print}) + (get-stack-instructions #{:exec :integer :boolean :char :vector_integer :string}) ;;; input instructions (list :in1) ;;; close From 560a614afad76183d1a37f06fc8813427744b222 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Sun, 31 Jul 2022 09:53:38 -0400 Subject: [PATCH 08/13] Update find_pair.cljc --- src/propeller/problems/PSB2/find_pair.cljc | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/propeller/problems/PSB2/find_pair.cljc b/src/propeller/problems/PSB2/find_pair.cljc index 092ae8f..313c1e4 100644 --- a/src/propeller/problems/PSB2/find_pair.cljc +++ b/src/propeller/problems/PSB2/find_pair.cljc @@ -10,16 +10,6 @@ [propeller.gp :as gp] #?(:cljs [cljs.reader :refer [read-string]]))) -; =========== PROBLEM DESCRIPTION =============================== -; GCD [GREATEST COMMON DIVISOR] from PSB2 -; Given two integers, return the largest integer that divides each -; of the integers evenly -; -; Source: https://arxiv.org/pdf/2106.06086.pdf -; ================================================================== - -;(def train-and-test-data (psb2/fetch-examples "data" "gcd" 200 2000)) - (def train-data (dc/read-data-formatted "find-pair" "train")) (def test-data (dc/read-data-formatted "find-pair" "test")) @@ -39,7 +29,7 @@ (utils/not-lazy (concat ;;; stack-specific instructions - (get-stack-instructions #{:exec :integer :vector_integer :boolean :string_print :integer_print}) + (get-stack-instructions #{:exec :integer :vector_integer :boolean :print}) ;;; input instructions (list :in1 :in2) ;;; close From 75fd08e1dc65086da7355dab24c3448d99aacce2 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Tue, 2 Aug 2022 09:33:05 -0400 Subject: [PATCH 09/13] fixed scrabble score bug --- src/propeller/problems/data_creation.cljc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/propeller/problems/data_creation.cljc b/src/propeller/problems/data_creation.cljc index b08e8ed..84a278d 100644 --- a/src/propeller/problems/data_creation.cljc +++ b/src/propeller/problems/data_creation.cljc @@ -1,7 +1,8 @@ (ns propeller.problems.data-creation (:require [psb2.core :as psb2] [clojure.data.csv :as csv] - [clojure.java.io :as io])) + [clojure.java.io :as io] + [clojure.string :as s])) (defn generate-data [problem train-or-test] (let [train-and-test-data (psb2/fetch-examples "data" problem 200 1000) @@ -94,8 +95,9 @@ (defn scrabble-score-read-data-formatted [problem train-or-test] (apply list (with-open [reader (io/reader (str "picked/" problem "-" train-or-test ".csv"))] (let [csv-data (csv/read-csv reader)] + (prn {:csv-data csv-data}) (mapv zipmap (->> (first csv-data) ;; First row is the header (map keyword) ;; Drop if you want string keys instead repeat) - (map (fn [elem] (list (first elem) (read-string (second elem)))) (rest csv-data))))))) \ No newline at end of file + (map (fn [elem] (list (s/replace (first elem) "\\n" "\n") (read-string (second elem)))) (rest csv-data))))))) \ No newline at end of file From 6ffd3bea590f0b1da231112f9968740a2371ca0c Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Sun, 14 Aug 2022 09:34:31 -0400 Subject: [PATCH 10/13] grade is now easier, more aligned with comparison. Doesn't use whole string, just output letter. --- src/propeller/problems/PSB1/grade.cljc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/propeller/problems/PSB1/grade.cljc b/src/propeller/problems/PSB1/grade.cljc index 008ad95..07e059a 100644 --- a/src/propeller/problems/PSB1/grade.cljc +++ b/src/propeller/problems/PSB1/grade.cljc @@ -14,11 +14,20 @@ (def train-data (dc/read-data-formatted "grade" "train")) (def test-data (dc/read-data-formatted "grade" "test")) +(def outputs (map (fn [i] (get i :output1)) train-data)) + +outputs + (defn map-vals-input "Returns all the input values of a map" [i] (vals (select-keys i [:input1 :input2 :input3 :input4 :input5]))) +(defn get-output + "returns the outputs of the grade function with JUST the letter grade" + [i] + (str (nth i 14))) + ; Random integer between -100 and 100 (defn random-int [] (- (rand-int 201) 100)) @@ -32,13 +41,13 @@ ;;close (list 'close) ;; ERCs (constants) - (list "Student has a " " grade." "A" "B" "C" "D" "F" random-int)))) + (list "A" "B" "C" "D" "F" random-int)))) (defn error-function [argmap data individual] (let [program (genome/plushy->push (:plushy individual) argmap) inputs (map (fn [i] (map-vals-input i)) data) - correct-outputs (map (fn [i] (get i :output1)) data) + correct-outputs (map (fn [i] (get-output (get i :output1))) data) outputs (map (fn [input] (state/peek-stack (interpreter/interpret-program From 239de881cec8e6e47685eb346c4f7368fc2d505e Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Sun, 14 Aug 2022 09:36:56 -0400 Subject: [PATCH 11/13] fixed scrabble score test-data bugs. (might revert) --- picked/scrabble-score-test.csv | 4 +- .../problems/PSB1/scrabble_score.cljc | 40 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/picked/scrabble-score-test.csv b/picked/scrabble-score-test.csv index 5b73d40..44e1e0c 100644 --- a/picked/scrabble-score-test.csv +++ b/picked/scrabble-score-test.csv @@ -1,4 +1,4 @@ -input1, output1 +input1,output1 Ptpo|Nr<-0~K|X6)y,27 "H6X?"":qX}Q(",40 \O&T_ag7+qtKE,22 @@ -646,7 +646,7 @@ _..^g2_\r~Ck,11 "}Guj<7\nk}\,\nK3jb",32 AT:c'0)bz3p`',21 * .],0 -">9j4p8""S]0%\n%.7hH",21 +">9j4p8""S]0%\n%.7hH",20 .JX\nKF9\nP3W;b._DDS.(,40 " ~1\n}w!""",4 \npnjy+{\nw,20 diff --git a/src/propeller/problems/PSB1/scrabble_score.cljc b/src/propeller/problems/PSB1/scrabble_score.cljc index 3518cc7..779e177 100644 --- a/src/propeller/problems/PSB1/scrabble_score.cljc +++ b/src/propeller/problems/PSB1/scrabble_score.cljc @@ -46,6 +46,46 @@ (vec (for [c visible-chars] (get scrabble-map (first (string/lower-case c)) 0))))) +;; scrabble-letter-values + +;; (def program '(0 :in1 :string_iterate (:integer_from_char [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 3 2 1 4 2 4 1 8 5 1 3 1 1 3 10 1 1 1 1 4 4 8 4 10 0 0 0 0 0 0 1 3 3 2 1 4 2 4 1 8 5 1 3 1 1 3 10 1 1 1 1 4 4 8 4 10 0 0 0 0] :vector_integer_nth :integer_add))) + +;; (def inputs (map (fn [i] (get i :input1)) test-data)) +;; test-data +;; (def correct-outputs (map (fn [i] (get i :output1)) test-data)) + +;; correct-outputs +;; inputs + +;; (def outputs (map (fn [input] +;; (state/peek-stack +;; (interpreter/interpret-program +;; program +;; (assoc state/empty-state :input {:in1 input}) +;; 200) +;; :integer)) +;; inputs)) + +;; outputs +;; correct-outputs + +;; (def errors (map (fn [correct-output output] +;; (if (= output :no-stack-item) +;; 1000000 +;; (math/abs (- correct-output output)))) +;; correct-outputs +;; outputs)) + +;; (apply + errors) + +;; (defn index-of [item coll] +;; (count (take-while (partial not= item) coll))) + +;; (index-of 1 errors) +;; (nth inputs 647) +;; (nth outputs 647) +;; (nth correct-outputs 647) + (def instructions (utils/not-lazy (concat From 0ffed2b56cd2682a578364c16768aebb610e77d7 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Tue, 16 Aug 2022 11:13:25 -0400 Subject: [PATCH 12/13] fix find-pair (maybe) --- src/propeller/problems/PSB2/find_pair.cljc | 111 +++++++++++---------- 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/src/propeller/problems/PSB2/find_pair.cljc b/src/propeller/problems/PSB2/find_pair.cljc index 313c1e4..34d7867 100644 --- a/src/propeller/problems/PSB2/find_pair.cljc +++ b/src/propeller/problems/PSB2/find_pair.cljc @@ -4,7 +4,7 @@ [propeller.push.interpreter :as interpreter] [propeller.problems.data-creation :as dc] [propeller.utils :as utils] - [propeller.push.instructions :refer [get-stack-instructions]] + [propeller.push.instructions :refer [def-instruction get-stack-instructions]] [propeller.push.state :as state] [propeller.tools.math :as math] [propeller.gp :as gp] @@ -25,17 +25,35 @@ [i] (vals (select-keys i [:output1 :output2]))) +(def-instruction :output-one + ^{:stacks #{:integer :output}} + (fn [state] + (if (empty? (:integer state)) + state + (let [top-int (state/peek-stack state :input)] + (assoc-in state [:output :out1] top-int))))) + + +(def-instruction :output-two + ^{:stacks #{:integer :output}} + (fn [state] + (if (empty? (:integer state)) + state + (let [top-int (state/peek-stack state :input)] + (assoc-in state [:output :out2] top-int))))) + (def instructions (utils/not-lazy - (concat + (concat ;;; stack-specific instructions - (get-stack-instructions #{:exec :integer :vector_integer :boolean :print}) + (get-stack-instructions #{:exec :integer :vector_integer :boolean}) + (list :output-one :output-two) ;;; input instructions - (list :in1 :in2) + (list :in1 :in2) ;;; close - (list 'close) + (list 'close) ;;; ERCs (constants) - (list -1 0 1 2 random-int)))) + (list -1 0 1 2 random-int)))) (defn error-function [argmap data individual] @@ -43,55 +61,48 @@ inputs (map (fn [i] (map-vals-input i)) data) correct-outputs (map (fn [i] (map-vals-output i)) data) outputs (map (fn [input] - (state/peek-stack - (interpreter/interpret-program - program - (assoc state/empty-state :input {:in1 (nth input 0) - :in2 (nth input 1)}) - (:step-limit argmap)) - :print)) + (:output + (interpreter/interpret-program + program + (assoc state/empty-state :input {:in1 (nth input 0) + :in2 (nth input 1)}) + (:step-limit argmap)))) inputs) - parsed-outputs (map (fn [output] - (try (read-string (str "(" output ")")) - #?(:clj (catch Exception e 1000000.0) - :cljs (catch js/Error. e 1000000.0)))) - outputs) - errors (map (fn [correct-output output] - (if (not= (count output) (count correct-output)) - 1000000.0 - (apply + (map (fn [c o] (if (and (number? c) (number? o)) - (math/abs (- c o)) - 1000000.0)) correct-output output)))) - correct-outputs - parsed-outputs) - ;null (prn {:output (first outputs) :correct-output (first correct-outputs) :parsed (first parsed-outputs) :error (first errors)}) - ] + outputs-1 (map #(:out1 %) outputs) + outputs-2 (map #(:out2 %) outputs) + _ (prn {:o1 outputs-1 :o2 outputs-2}) + errors (map (fn [correct-output output-1 output-2] + (if (not (and (number? output-2) (number? output-1))) + 100000 + (+ (math/abs (- (first correct-output) output-1)) + (math/abs (- (second correct-output) output-2))))) + correct-outputs outputs-1 outputs-2)] (assoc individual - :behaviors parsed-outputs - :errors errors - :total-error #?(:clj (apply +' errors) - :cljs (apply + errors))))) + :behavior 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-data - :testing-data test-data - :case-t-size (count train-data) - :ds-parent-rate 0 - :ds-parent-gens 1 - :max-generations 300 - :population-size 1000 - :max-initial-plushy-size 250 - :step-limit 2000 - :parent-selection :lexicase - :tournament-size 5 - :umad-rate 0.1 - :variation {:umad 1.0 :crossover 0.0} - :elitism false} - (apply hash-map (map #(if (string? %) (read-string %) %) args)))) + (merge + {:instructions instructions + :error-function error-function + :training-data train-data + :testing-data test-data + :case-t-size (count train-data) + :ds-parent-rate 0 + :ds-parent-gens 1 + :max-generations 300 + :population-size 1000 + :max-initial-plushy-size 250 + :step-limit 2000 + :parent-selection :lexicase + :tournament-size 5 + :umad-rate 0.1 + :variation {:umad 1.0 :crossover 0.0} + :elitism false} + (apply hash-map (map #(if (string? %) (read-string %) %) args)))) (#?(:clj shutdown-agents))) \ No newline at end of file From 28b76e14abe6a61966bed02b8cbcdb77920406d3 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Fri, 19 Aug 2022 11:23:35 -0400 Subject: [PATCH 13/13] fixed find-pair bug --- src/propeller/problems/PSB2/find_pair.cljc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/propeller/problems/PSB2/find_pair.cljc b/src/propeller/problems/PSB2/find_pair.cljc index 34d7867..34fffd5 100644 --- a/src/propeller/problems/PSB2/find_pair.cljc +++ b/src/propeller/problems/PSB2/find_pair.cljc @@ -30,16 +30,15 @@ (fn [state] (if (empty? (:integer state)) state - (let [top-int (state/peek-stack state :input)] + (let [top-int (state/peek-stack state :integer)] (assoc-in state [:output :out1] top-int))))) - (def-instruction :output-two ^{:stacks #{:integer :output}} (fn [state] (if (empty? (:integer state)) state - (let [top-int (state/peek-stack state :input)] + (let [top-int (state/peek-stack state :integer)] (assoc-in state [:output :out2] top-int))))) (def instructions @@ -70,7 +69,7 @@ inputs) outputs-1 (map #(:out1 %) outputs) outputs-2 (map #(:out2 %) outputs) - _ (prn {:o1 outputs-1 :o2 outputs-2}) + ;_ (prn {:o1 outputs-1 :o2 outputs-2}) errors (map (fn [correct-output output-1 output-2] (if (not (and (number? output-2) (number? output-1))) 100000