From 39aa7a8cf303fb407daed10ee2305f35c2f93c9b Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Thu, 16 Jun 2022 11:14:43 -0400 Subject: [PATCH] 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