From 883840a564d2984e837d8d623dbc053449ff66ab Mon Sep 17 00:00:00 2001 From: Shuzo Katayama Date: Wed, 14 Jul 2021 14:55:23 -0400 Subject: [PATCH] fizz buzz, gcd, and luhn added --- .idea/misc.xml | 2 +- src/propeller/gp.cljc | 22 ++++--- src/propeller/problems/PSB2/basement.cljc | 1 - src/propeller/problems/PSB2/fizz_buzz.cljc | 70 ++++++++++++++++++++ src/propeller/problems/PSB2/gcd.cljc | 75 ++++++++++++++++++++++ src/propeller/problems/PSB2/luhn.cljc | 69 ++++++++++++++++++++ 6 files changed, 227 insertions(+), 12 deletions(-) create mode 100644 src/propeller/problems/PSB2/fizz_buzz.cljc create mode 100644 src/propeller/problems/PSB2/gcd.cljc create mode 100644 src/propeller/problems/PSB2/luhn.cljc diff --git a/.idea/misc.xml b/.idea/misc.xml index 97e4469..bce9de7 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -7,7 +7,7 @@ - + \ No newline at end of file diff --git a/src/propeller/gp.cljc b/src/propeller/gp.cljc index 1ad3f71..55b026d 100755 --- a/src/propeller/gp.cljc +++ b/src/propeller/gp.cljc @@ -16,18 +16,20 @@ "Reports information each generation." [pop generation argmap] (let [best (first pop)] - (clojure.pprint/pprint {:generation generation - :best-plushy (:plushy best) - :best-program (genome/plushy->push (:plushy best) argmap) - :best-total-error (:total-error best) - :best-errors (:errors best) - :best-behaviors (:behaviors best) - :genotypic-diversity (float (/ (count (distinct (map :plushy pop))) (count pop))) - :behavioral-diversity (float (/ (count (distinct (map :behaviors pop))) (count pop))) - :average-genome-length (float (/ (reduce + (map count (map :plushy pop))) (count pop))) - :average-total-error (float (/ (reduce + (map :total-error pop)) (count pop)))}) + (println {:generation generation + :best-plushy (:plushy best) + :best-program (genome/plushy->push (:plushy best) argmap) + :best-total-error (:total-error best) + :best-errors (:errors best) + :best-behaviors (:behaviors best) + :genotypic-diversity (float (/ (count (distinct (map :plushy pop))) (count pop))) + :behavioral-diversity (float (/ (count (distinct (map :behaviors pop))) (count pop))) + :average-genome-length (float (/ (reduce + (map count (map :plushy pop))) (count pop))) + :average-total-error (float (/ (reduce + (map :total-error pop)) (count pop)))}) (println))) +;; clojure.pprint/pprint + (defn gp "Main GP loop." [{:keys [population-size max-generations error-function instructions diff --git a/src/propeller/problems/PSB2/basement.cljc b/src/propeller/problems/PSB2/basement.cljc index 608d4f3..c89d2ab 100644 --- a/src/propeller/problems/PSB2/basement.cljc +++ b/src/propeller/problems/PSB2/basement.cljc @@ -5,7 +5,6 @@ [propeller.utils :as utils] [propeller.push.utils.helpers :refer [get-stack-instructions]] [propeller.push.state :as state] - [clojure.pprint :as pprint] [propeller.tools.math :as math])) ; =========== PROBLEM DESCRIPTION ============================ diff --git a/src/propeller/problems/PSB2/fizz_buzz.cljc b/src/propeller/problems/PSB2/fizz_buzz.cljc new file mode 100644 index 0000000..33cbb09 --- /dev/null +++ b/src/propeller/problems/PSB2/fizz_buzz.cljc @@ -0,0 +1,70 @@ +(ns propeller.problems.PSB2.fizz-buzz + (:require [psb2.core :as psb2] + [propeller.genome :as genome] + [propeller.push.interpreter :as interpreter] + [propeller.utils :as utils] + [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.state :as state] + [propeller.tools.metrics :as metrics])) + +; =========== PROBLEM DESCRIPTION ========================= +; FIZZ BUZZ from PSB2 +; Given an integer x, return "Fizz" if x is +; divisible by 3, "Buzz" if x is divisible by 5, "FizzBuzz" if x +; is divisible by 3 and 5, and a string version of x if none of +; the above hold. +; +; Source: https://arxiv.org/pdf/2106.06086.pdf +; ============================================================ + +(def train-and-test-data (psb2/fetch-examples "data" "fizz-buzz" 200 2000)) + +(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 "Fizz" "Buzz" "FizzBuzz" 0 3 5)))) + +(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) + parsed-outputs (map (fn [output] + (try (read-string output) + #?(:clj (catch Exception e 1000.0) + :cljs (catch js/Error. e 1000.0)))) + outputs) + errors (map (fn [correct-output output] + (if (= output :no-stack-item) + 10000 + (metrics/levenshtein-distance (str correct-output) (str output)))) + correct-outputs + parsed-outputs)] + (assoc individual + :behaviors parsed-outputs + :errors errors + :total-error #?(:clj (apply +' errors) + :cljs (apply + errors))))) + + +(def arglist + {:instructions instructions + :error-function error-function + :training-data (:train train-and-test-data) + :testing-data (:test train-and-test-data)}) + diff --git a/src/propeller/problems/PSB2/gcd.cljc b/src/propeller/problems/PSB2/gcd.cljc new file mode 100644 index 0000000..5830c20 --- /dev/null +++ b/src/propeller/problems/PSB2/gcd.cljc @@ -0,0 +1,75 @@ +(ns propeller.problems.PSB2.gcd + (:require [psb2.core :as psb2] + [propeller.genome :as genome] + [propeller.push.interpreter :as interpreter] + [propeller.utils :as utils] + [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.state :as state] + [propeller.tools.math :as math])) + +; =========== 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)) + +(defn random-int [] (- (rand-int 201) 100)) + +(defn map-vals-input + "Returns all the input values of a map (specific helper method for bouncing-balls)" + [i] + (vals (select-keys i [:input1 :input2]))) + +(defn map-vals-output + "Returns the output values of a map (specific helper method for bouncing-balls)" + [i] + (get i :output1)) + +(def instructions + (utils/not-lazy + (concat + ;;; stack-specific instructions + (get-stack-instructions #{:exec :integer :boolean :print}) + ;;; input instructions + (list :in1 :in2) + ;;; close + (list 'close) + ;;; ERCs (constants) + (list 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)) + :integer)) + inputs) + errors (map (fn [correct-output output] + (if (= output :no-stack-item) + 1000000.0 + (min 1000.0 (math/abs (- correct-output output))))) + correct-outputs + outputs)] + (assoc individual + :behaviors outputs + :errors errors + :total-error #?(:clj (apply +' errors) + :cljs (apply + errors))))) + +(def arglist + {:instructions instructions + :error-function error-function + :training-data (:train train-and-test-data) + :testing-data (:test train-and-test-data)}) + diff --git a/src/propeller/problems/PSB2/luhn.cljc b/src/propeller/problems/PSB2/luhn.cljc new file mode 100644 index 0000000..009cf18 --- /dev/null +++ b/src/propeller/problems/PSB2/luhn.cljc @@ -0,0 +1,69 @@ +(ns propeller.problems.PSB2.luhn + (:require [psb2.core :as psb2] + [propeller.genome :as genome] + [propeller.push.interpreter :as interpreter] + [propeller.utils :as utils] + [propeller.push.utils.helpers :refer [get-stack-instructions]] + [propeller.push.state :as state] + [propeller.tools.math :as math])) + +; =========== PROBLEM DESCRIPTION ============================ +; LUHN from PSB2 +; Given a vector of 16 digits, implement Luhn’s +; algorithm to verify a credit card number, such that it follows +; the following rules: double every other digit starting with +; the second digit. If any of the results are over 9, subtract 9 +; from them. Return the sum of all of the new digits. +; +; Source: https://arxiv.org/pdf/2106.06086.pdf +; =============================================================== + +(def train-and-test-data (psb2/fetch-examples "data" "luhn" 200 2000)) + +; 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 0 2 9 10 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)) + :integer)) + inputs) + errors (map (fn [correct-output output] + (if (= output :no-stack-item) + 1000000 + (min 1000.0 (math/abs (- correct-output output))))) + correct-outputs + outputs)] + (assoc individual + :behaviors outputs + :errors errors + :total-error #?(:clj (apply +' errors) + :cljs (apply + errors))))) + +(def arglist + {:instructions instructions + :error-function error-function + :training-data (:train train-and-test-data) + :testing-data (:test train-and-test-data)}) + +