Skip to content

Commit

Permalink
Merge pull request #230 from julianoks/master
Browse files Browse the repository at this point in the history
String generation, :exit-on-success, typos
lein release :patch
  • Loading branch information
lspector committed Jan 17, 2017
2 parents 00b415a + 252e0d3 commit 9bb7471
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 6 deletions.
3 changes: 3 additions & 0 deletions src/clojush/args.clj
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,9 @@

:print-homology-data false
;; If true, prints the homology statistics.

:exit-on-success true
;; When true, will exit the run when there is an individual with a zero-error vector

;;----------------------------------------
;; Arguments related to printing JSON, EDN, or CSV logs
Expand Down
2 changes: 1 addition & 1 deletion src/clojush/instructions/string.clj
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@
(pop-item :char (pop-item :string state))))
state)))

(define-registered
(define-registered
string_setchar ; Returns a function that sets char at index in string
^{:stack-types [:string :char :integer]}
(fn [state]
Expand Down
102 changes: 102 additions & 0 deletions src/clojush/problems/synthetic/string_generation.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
(ns clojush.problems.synthetic.string-generation
(:use [clojush.pushgp.pushgp]
[clojush util pushstate interpreter random])
(:require [clojure.java.io :as io]))

#_"
The string generation problem asks for a mapping from an index to a character in a string.
The string is 15 characters long, containing only uppercase letters.
You can make the string dynamic by setting 'dynamic-string?' to true.
In this setting, the target string is dynamic, changing every 50 generations.
We calculate the difference in the number of zero error cases between the last generation of using a target string and the first generation of its use.
We keep a record of the differences in the 'improvement-vector' atom, which is displayed in every generation's problem-specific-report.
"

(def target-string-length 15)

(def dynamic-string? true)
(def new-string-every 50)
(def beginning-num-of-zero-cases (atom 0))
(def improvement-vector (atom []))

(def spit-improvement-vector? false)
(def output_folder "/home/juao15/autoconstruction/string-generation/improvement_logs")

(if (and spit-improvement-vector?
(not (.exists (io/file output_folder))))
(.mkdir (io/file output_folder)))

(def log-file
(if spit-improvement-vector?
(loop [i 0]
(let [file (io/file output_folder (str i ".log"))]
(if (.exists file)
(recur (inc i))
(do
(spit file [])
file))))))

(defn generate-target-string
"Random string of uppercase letters"
[]
(apply str (map char
(repeatedly target-string-length
#(+ 65 (rand-int 26))))))

(def target-string (atom (generate-target-string)))

(defn get-output-on-cases
[program]
(for [index (range target-string-length)]
(let [state (run-push program
(push-item index :input
(push-item index :integer
(make-push-state))))]
(top-item :char state))))

(defn string-generation-error-fn
[program]
(mapv
(fn [output target]
(cond
(= output :no-stack-item) 1000
(= output target) 0
:else 1))
(get-output-on-cases program)
@target-string))

(defn report
[best _ generation error-fn _]
(print "\n******************************\n")
(if dynamic-string?
(let [effective-generation (mod generation new-string-every)]
(if (zero? effective-generation)
(reset! beginning-num-of-zero-cases (count (filter zero? (error-fn (not-lazy (:program best)))))))
(if (= (dec new-string-every) effective-generation)
(let [n-zero-cases (count (filter zero? (error-fn (not-lazy (:program best)))))]
(swap! improvement-vector conj (- n-zero-cases @beginning-num-of-zero-cases))
(reset! target-string (generate-target-string))
(if spit-improvement-vector? (spit log-file @improvement-vector))
(print "Replaced target string\n")))
(print (str "Improvement vector: " @improvement-vector "\n"))))
(print (str "Target string: \"" @target-string "\"\n"))
(print (str "Best string generated: \"" (apply str (get-output-on-cases (not-lazy (:program best)))) "\"\n"))
(print "******************************\n\n"))

(def argmap
{:error-function string-generation-error-fn
:parent-selection :lexicase
:max-points 500
:atom-generators (cons (fn [] (+ 65 (int (lrand 26))))
(registered-for-stacks [:integer :boolean :char :exec]))
:genetic-operator-probabilities {:alternation 0.2
:uniform-mutation 0.2
:uniform-close-mutation 0.1
[:alternation :uniform-mutation] 0.5}
:alternation-rate 0.05
:alignment-deviation 10
:uniform-mutation-rate 0.05
:uniform-mutation-constant-tweak-rate 0.95
:max-generations 100000
:problem-specific-report report
:exit-on-success false})
11 changes: 6 additions & 5 deletions src/clojush/pushgp/report.clj
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@
population)
count-zero-by-case (map #(apply + %) (apply mapv vector pop-zero-by-case))]

(println "--- Lexicse Program with Most Elite Cases Statistics ---")
(println "--- Lexicase Program with Most Elite Cases Statistics ---")
(println "Lexicase best genome:" (print-genome lex-best))
(println "Lexicase best program:" (pr-str (not-lazy (:program lex-best))))
(when (> report-simplifications 0)
Expand All @@ -219,7 +219,7 @@
(when print-history (println "Lexicase best history:" (not-lazy (:history lex-best))))
(println "Lexicase best size:" (count-points (:program lex-best)))
(printf "Percent parens: %.3f\n" (double (/ (count-parens (:program lex-best)) (count-points (:program lex-best))))) ;Number of (open) parens / points
(println "--- Lexicse Program with Most Zero Cases Statistics ---")
(println "--- Lexicase Program with Most Zero Cases Statistics ---")
(println "Zero cases best genome:" (print-genome most-zero-cases-best))
(println "Zero cases best program:" (pr-str (not-lazy (:program most-zero-cases-best))))
(when (> report-simplifications 0)
Expand Down Expand Up @@ -274,7 +274,7 @@
problem-specific-report total-error-method
parent-selection print-homology-data max-point-evaluations
print-error-frequencies-by-case normalization autoconstructive
print-selection-counts
print-selection-counts exit-on-success
;; The following are for CSV or JSON logs
print-csv-logs print-json-logs csv-log-filename json-log-filename
log-fitnesses-for-all-cases json-log-program-strings
Expand Down Expand Up @@ -428,8 +428,9 @@
(when print-json-logs (json-print population generation json-log-filename
log-fitnesses-for-all-cases json-log-program-strings))
(when print-edn-logs (edn-print population generation edn-log-filename edn-keys edn-additional-keys))
(cond (or (<= (:total-error best) error-threshold)
(:success best)) [:success best]
(cond (and exit-on-success
(or (<= (:total-error best) error-threshold)
(:success best))) [:success best]
(>= generation max-generations) [:failure best]
(>= @point-evaluations-count max-point-evaluations) [:failure best]
:else [:continue best])))
Expand Down

0 comments on commit 9bb7471

Please sign in to comment.