From 14f63f880bbcbe1e0e9b9ad775049c3d4dacf11f Mon Sep 17 00:00:00 2001 From: Lee Spector Date: Mon, 7 Dec 2020 13:58:34 -0500 Subject: [PATCH] Fix comment and error message in handle-input-instruction; begin developing valiant problem --- src/propeller/problems/valiant.cljc | 165 ++++++++++++++++++ .../push/instructions/input_output.cljc | 9 +- 2 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 src/propeller/problems/valiant.cljc diff --git a/src/propeller/problems/valiant.cljc b/src/propeller/problems/valiant.cljc new file mode 100644 index 0000000..640bc64 --- /dev/null +++ b/src/propeller/problems/valiant.cljc @@ -0,0 +1,165 @@ +(ns propeller.problems.valiant) + +(defn train-and-test-data + [num-vars num-inputs num-train num-test] + (let [input-indices (take num-inputs (shuffle (range num-vars))) + rand-vars (fn [] (vec (repeatedly num-vars #(< (rand) 0.5)))) + even-parity? (fn [vars] + (even? (count (filter #(= % true) + (map #(nth vars %) + input-indices))))) + train-inputs (repeatedly num-train rand-vars) + test-inputs (repeatedly num-test rand-vars)] + {:train {:inputs train-inputs + :outputs (map even-parity? train-inputs)} + :test {:inputs test-inputs + :outputs (map even-parity? test-inputs)}})) + +(def instructions + (list :in1 + :integer_add + :integer_subtract + :integer_mult + :integer_quot + :integer_eq + :exec_dup + :exec_if + 'close + 0 + 1)) + +boolean_and boolean_or boolean_not exec_if + +;============== NOTE NOTE NOTE ================= +; This file has note been updated for Clojush 2.0, and will likely not work +;============== NOTE NOTE NOTE ================= +; +;(ns clojush.problems.boolean.valiant +; (:use [clojush.pushgp.pushgp] +; [clojush.pushstate] +; [clojush.random] +; [clojush.interpreter] +; [clojure.math.numeric-tower])) +; +;(def numvars 100) ;1000) +;(def numinputs 50) ;500) +;(def numcases 500) ;5000) +; +;(def input-indices +; (vec (take numinputs (shuffle (range numvars))))) +; +;(def cases +; (vec (repeatedly numcases +; (fn [] (let [vars (vec (repeatedly numvars #(< (lrand) 0.5)))] +; [vars (even? (count (filter #(= % true) +; (map #(nth vars %) +; input-indices))))]))))) +; +;(println "input-indices:" input-indices) +; +;;; ugly way to define all of the input instructions, since I haven't fully +;;; grokked Clojure macros +; +;(def n-hack (atom 0)) +; +;(defn define-input [n] +; (reset! n-hack n) +; (eval `(define-registered ~(symbol (str "input" @n-hack)) +; (fn [state#] +; (push-item (nth (first (:auxiliary state#)) ~(+ @n-hack)) +; :boolean +; state#))))) +; +;(dotimes [n numvars] (define-input n)) +; +;;; this gives the instructions: (registered-for-type "input") +; +;(defn rp [prog state] (run-push prog state true)) +; +;(defn valiant-fitness +; [individual] +; (assoc individual +; :errors +; (doall (for [c (range numcases)] +; (let [[inputs answer] (nth cases c) +; output (->> (make-push-state) +; (push-item inputs :auxiliary) +; (run-push (:program individual)) +; ;(rp (:program individual)) +; (top-item :boolean))] +; ;(println "output" output "answer" answer) +; (if (= output answer) 0 1)))))) +; +;;input-indices +; +;;(reduce + (valiant-fitness '(input1 input4 input0 input7 input9 boolean_and boolean_and boolean_and boolean_and))) +; +;;; oversized-offspring-fail-to-random? -- take fail to random code from here and use right +;;; parameters +;;(in-ns 'clojush.pushgp.genetic-operators) +;;(defn crossover +;; "Returns a copy of parent1 with a random subprogram replaced with a random +;; subprogram of parent2." +;; [parent1 parent2 max-points] +;; (let [new-program (case (lrand-int 2) +;; 0 (insert-code-at-point +;; (:program parent1) +;; (select-node-index (:program parent1)) +;; (code-at-point (:program parent2) +;; (select-node-index (:program parent2)))) +;; 1 (list (random-code 10 @global-atom-generators) 'exec_if (:program parent1) (:program parent2)))] +;; (if (> (count-points new-program) max-points) +;; ;parent1 +;; (make-individual :program (random-code 10 @global-atom-generators) :history (:history parent1) +;; :ancestors (if global-maintain-ancestors +;; (cons (:program parent1) (:ancestors parent1)) +;; (:ancestors parent1))) +;; (make-individual :program new-program :history (:history parent1) +;; :ancestors (if global-maintain-ancestors +;; (cons (:program parent1) (:ancestors parent1)) +;; (:ancestors parent1)))))) +;;(in-ns 'experimental.valiant) +;;; +;;; Probabilistic Pseudo Hillclimbing (persistence) +;;; +; +;;(def argmap +;; {:error-function valiant-fitness +;; :atom-generators (concat (vec (registered-for-type "input")) +;; ;) +;; (apply concat +;; (repeat 25 +;; '(boolean_and boolean_or boolean_not exec_if)))) +;; :use-lexicase-selection true +;; :max-points 40000 +;; :max-genome-size-in-initial-program 10 +;; :population-size 100 +;; :evalpush-limit 10000 +;; :mutation-probability 0.4 +;; :mutation-max-points 50 +;; ;:crossover-probability 0.4 +;; :simplification-probability 0.2 +;; :reproduction-simplifications 1 +;; ;:deletion-mutation-probability 0.2 +;; :boolean-gsxover-probability 0.4 +;; :boolean-gsxover-new-code-max-points 10 +;; :parent-reversion-probability 0.95 +;; ;:decimation-ratio 0.01 +;; ;:use-single-thread true +;; }) +; +;(def argmap +; {:error-function valiant-fitness +; :atom-generators (concat (vec (registered-for-type "input")) +; ;) +; (apply concat +; (repeat 25 +; '(boolean_and boolean_or boolean_not exec_if)))) +; :max-points 4000 +; :max-genome-size-in-initial-program 100 +; :population-size 100 +; :evalpush-limit 2000 +; :genetic-operator-probabilities {[:alternation :uniform-mutation] 1.0} ;Somewhat equivalent to normal Push's ULTRA operator +; :alignment-deviation 20 +; ;:use-single-thread true +; }) \ No newline at end of file diff --git a/src/propeller/push/instructions/input_output.cljc b/src/propeller/push/instructions/input_output.cljc index 55db2ee..18d24c7 100755 --- a/src/propeller/push/instructions/input_output.cljc +++ b/src/propeller/push/instructions/input_output.cljc @@ -12,16 +12,15 @@ ;; ============================================================================= ;; Allows Push to handle input instructions of the form :inN, e.g. :in2, taking -;; elements thus labeled from the :input stack and pushing them onto the :exec -;; stack. We can tell whether a particular inN instruction is valid if N-1 -;; values are on the input stack. +;; elements thus labeled from the :input map and pushing them onto the :exec +;; stack. (defn handle-input-instruction [state instruction] (if-let [input (instruction (:input state))] (state/push-to-stack state :exec input) - (throw #?(:clj (Exception. (str "Undefined input instruction " instruction)) + (throw #?(:clj (Exception. (str "Undefined instruction " instruction)) :cljs (js/Error - (str "Undefined input instruction " instruction)))))) + (str "Undefined instruction " instruction)))))) ;; ============================================================================= ;; OUTPUT Instructions