Skip to content

Commit

Permalink
Added functionality for printing json formatted logs.
Browse files Browse the repository at this point in the history
Also added a odd problem example that includes log printing.
  • Loading branch information
thelmuth committed Sep 27, 2012
1 parent fafef03 commit c869dcd
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 44 deletions.
Binary file added lib/data.json-0.1.3.jar
Binary file not shown.
3 changes: 2 additions & 1 deletion project.clj
Expand Up @@ -5,5 +5,6 @@
:dependencies [[org.clojure/clojure "1.3.0"] :dependencies [[org.clojure/clojure "1.3.0"]
[org.clojure/math.numeric-tower "0.0.1"] [org.clojure/math.numeric-tower "0.0.1"]
[local-file "0.0.4"] [local-file "0.0.4"]
[clojure-csv "2.0.0-alpha2"]] [clojure-csv "2.0.0-alpha2"]
[org.clojure/data.json "0.1.3"]]
:main clojush.core) :main clojush.core)
43 changes: 43 additions & 0 deletions src/clojush/examples/odd_csv_and_json.clj
@@ -0,0 +1,43 @@
;; odd.clj
;; an example problem for clojush, a Push/PushGP system written in Clojure
;; Lee Spector, lspector@hampshire.edu, 2010

(ns clojush.examples.odd-csv-and-json
(:use [clojush.pushgp.pushgp]
[clojush.pushstate]
[clojush.interpreter]))

;;;;;;;;;;;;
;; The "odd" problem: take a positive integer input and push a Boolean indicating
;; whether or not the input is an odd number. There are many ways to compute this
;; and PushGP sometimes finds unusual methods.

;; This version shows how you can print csv and json log files.

(define-registered
in
(fn [state] (push-item (stack-ref :auxiliary 0 state) :integer state)))

(pushgp
:use-single-thread true
:error-function (fn [program]
(doall
(for [input (range 10)]
(let [state (run-push program
(push-item input :auxiliary
(push-item input :integer
(make-push-state))))
top-bool (top-item :boolean state)]
(if (not (= top-bool :no-stack-item))
(if (= top-bool (odd? input)) 0 1)
1000)))))
:atom-generators (concat (registered-nonrandom)
(list (fn [] (rand-int 100))
'in))
:print-csv-logs true
:print-json-logs true
:csv-log-filename "log.csv"
:json-log-filename "log.json"
:log-fitnesses-for-all-cases false
:json-log-program-strings false
)
41 changes: 28 additions & 13 deletions src/clojush/pushgp/pushgp.clj
Expand Up @@ -36,7 +36,10 @@
gaussian-mutation-standard-deviation reuse-errors gaussian-mutation-standard-deviation reuse-errors
problem-specific-report use-single-thread random-seed problem-specific-report use-single-thread random-seed
use-historically-assessed-hardness use-lexicase-selection use-historically-assessed-hardness use-lexicase-selection
use-rmse] use-rmse print-csv-logs print-json-logs csv-log-filename
json-log-filename log-fitnesses-for-all-cases
json-log-program-strings
]
:or {error-function (fn [p] '(0)) ;; pgm -> list of errors (1 per case) :or {error-function (fn [p] '(0)) ;; pgm -> list of errors (1 per case)
error-threshold 0 error-threshold 0
population-size 1000 population-size 1000
Expand Down Expand Up @@ -69,6 +72,12 @@
gaussian-mutation-standard-deviation 0.1 gaussian-mutation-standard-deviation 0.1
reuse-errors true reuse-errors true
problem-specific-report default-problem-specific-report problem-specific-report default-problem-specific-report
print-csv-logs false
print-json-logs false
csv-log-filename "log.csv"
json-log-filename "log.json"
log-fitnesses-for-all-cases false
json-log-program-strings false
use-single-thread false use-single-thread false
random-seed (System/nanoTime) random-seed (System/nanoTime)
use-historically-assessed-hardness false use-historically-assessed-hardness false
Expand All @@ -91,17 +100,20 @@
(reset! global-use-rmse use-rmse) (reset! global-use-rmse use-rmse)
(initial-report) ;; Print the inital report (initial-report) ;; Print the inital report
(print-params (print-params
(error-function error-threshold population-size max-points max-points-in-initial-program (atom-generators print-csv-logs csv-log-filename print-json-logs
atom-generators max-generations json-log-filename log-fitnesses-for-all-cases
mutation-probability mutation-max-points crossover-probability json-log-program-strings error-function error-threshold
simplification-probability gaussian-mutation-probability population-size max-generations max-points
gaussian-mutation-per-number-mutation-probability gaussian-mutation-standard-deviation max-points-in-initial-program
tournament-size report-simplifications final-report-simplifications mutation-probability mutation-max-points crossover-probability
reproduction-simplifications trivial-geography-radius decimation-ratio simplification-probability gaussian-mutation-probability
decimation-tournament-size evalpush-limit evalpush-time-limit node-selection-method gaussian-mutation-per-number-mutation-probability gaussian-mutation-standard-deviation
node-selection-tournament-size node-selection-leaf-probability pop-when-tagging tournament-size report-simplifications final-report-simplifications
reuse-errors use-single-thread random-seed use-historically-assessed-hardness reproduction-simplifications trivial-geography-radius decimation-ratio
use-lexicase-selection use-rmse)) decimation-tournament-size evalpush-limit evalpush-time-limit node-selection-method
node-selection-tournament-size node-selection-leaf-probability pop-when-tagging
reuse-errors use-single-thread random-seed use-historically-assessed-hardness
use-lexicase-selection use-rmse))
(printf "\nGenerating initial population...\n") (flush) (printf "\nGenerating initial population...\n") (flush)
(let [pop-agents (vec (doall (for [_ (range population-size)] (let [pop-agents (vec (doall (for [_ (range population-size)]
((if use-single-thread atom agent) ((if use-single-thread atom agent)
Expand Down Expand Up @@ -130,7 +142,10 @@
population-size) population-size)
;; report and check for success ;; report and check for success
(let [best (report (vec (doall (map deref pop-agents))) generation error-function (let [best (report (vec (doall (map deref pop-agents))) generation error-function
report-simplifications problem-specific-report)] report-simplifications print-csv-logs print-json-logs
csv-log-filename json-log-filename
log-fitnesses-for-all-cases json-log-program-strings
problem-specific-report)]
(if (<= (:total-error best) error-threshold) (if (<= (:total-error best) error-threshold)
(final-report generation best error-function final-report-simplifications) (final-report generation best error-function final-report-simplifications)
(do (if (>= generation max-generations) (do (if (>= generation max-generations)
Expand Down
109 changes: 79 additions & 30 deletions src/clojush/pushgp/report.clj
@@ -1,10 +1,11 @@
(ns clojush.pushgp.report (ns clojush.pushgp.report
(:require [clojure.string :as string]
[local-file])
(:use [clojush.util] (:use [clojush.util]
[clojush.globals] [clojush.globals]
[clojush.pushstate] [clojush.pushstate]
[clojush.simplification])) [clojush.simplification]
[clojure.data.json :only (json-str)])
(:require [clojure.string :as string]
[local-file]))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; helper functions ;; helper functions
Expand Down Expand Up @@ -33,38 +34,37 @@
(cons 'do (doall (map #(list 'println (str %) "=" %) params)))) (cons 'do (doall (map #(list 'println (str %) "=" %) params))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; report printing functions ;; log printing (csv and json)

(def fname "log.csv")
(def printAllTestCases true)

(defn csv-init
[]
(spit fname "generation,individual,total-error,size\n" :append false))


(defn csv-print (defn csv-print
[population generation] "Prints a csv of the population, with each individual's fitness and size.
(if (not printAllTestCases) If log-fitnesses-for-all-cases is true, it also prints the value
(doseq [[ind p] (map-indexed vector population)] of each fitness case."
(spit fname [population generation csv-log-filename log-fitnesses-for-all-cases]
(format "%s,%s,%s,%s\n" (if (not log-fitnesses-for-all-cases)
generation
ind
(:total-error p)
(count-points (:program p)))
:append true))
(do (do
(when (zero? generation) (when (zero? generation)
(spit fname "generation,individual,total-error,size," :append false) (spit csv-log-filename "generation,individual,total-error,size\n" :append false))
(spit fname (doseq [[ind p] (map-indexed vector population)]
(spit csv-log-filename
(format "%s,%s,%s,%s\n"
generation
ind
(:total-error p)
(count-points (:program p)))
:append true)))
(do
(when (zero? generation)
(spit csv-log-filename "generation,individual,total-error,size," :append false)
(spit csv-log-filename
(format "%s\n" (format "%s\n"
(apply str (apply str
"TC" "TC"
(interpose ",TC" (interpose ",TC"
(range (count (:errors (first population))))))) (range (count (:errors (first population)))))))
:append true)) :append true))
(doseq [[ind p] (map-indexed vector population)] (doseq [[ind p] (map-indexed vector population)]
(spit fname (spit csv-log-filename
(format "%s,%s,%s,%s,%s\n" (format "%s,%s,%s,%s,%s\n"
generation generation
ind ind
Expand All @@ -73,12 +73,59 @@
(apply str (interpose "," (:errors p)))) (apply str (interpose "," (:errors p))))
:append true))))) :append true)))))


(defn jsonize-individual
"Takes an individual and returns it with only the items of interest
for the json logs."
[log-fitnesses-for-all-cases json-log-program-strings generation individual]
(let [part1-ind (-> (if log-fitnesses-for-all-cases
{:error (:errors individual)}
{})
(assoc :total-error (:total-error individual))
(assoc :generation generation)
(assoc :size (count-points (:program individual))))
part2-ind (if json-log-program-strings
(assoc part1-ind :program (str (not-lazy (:program individual))))
part1-ind)
part3-ind (if (:hah-error individual)
(assoc part2-ind :hah-error (:hah-error individual))
part2-ind)]
(if (:rms-error individual)
(assoc part3-ind :rms-error (:rms-error individual))
part3-ind)))

(defn json-print
"Prints a json file of the population, with each individual's fitness and size.
If log-fitnesses-for-all-cases is true, it also prints the value
of each fitness case."
[population generation json-log-filename log-fitnesses-for-all-cases
json-log-program-strings]
(let [pop-json-string (json-str (map #(jsonize-individual
log-fitnesses-for-all-cases
json-log-program-strings
generation
%)
population))]
(if (zero? generation)
(spit json-log-filename (str pop-json-string "\n") :append false)
(spit json-log-filename (str "," pop-json-string "\n") :append true))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; report printing functions

(defn report (defn report
"Reports on the specified generation of a pushgp run. Returns the best "Reports on the specified generation of a pushgp run. Returns the best
individual of the generation." individual of the generation."
([population generation error-function report-simplifications] ([population generation error-function report-simplifications
(report population generation error-function report-simplifications default-problem-specific-report)) print-csv-logs print-json-logs csv-log-filename json-log-filename
([population generation error-function report-simplifications problem-specific-report] log-fitnesses-for-all-cases json-log-program-strings]
(report population generation error-function report-simplifications
print-csv-logs print-json-logs csv-log-filename json-log-filename
log-fitnesses-for-all-cases json-log-program-strings
default-problem-specific-report))
([population generation error-function report-simplifications
print-csv-logs print-json-logs csv-log-filename json-log-filename
log-fitnesses-for-all-cases json-log-program-strings problem-specific-report]
(printf "\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;")(flush) (printf "\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;")(flush)
;(println (map :total-error population))(flush) ;*** ;(println (map :total-error population))(flush) ;***
(printf "\n;; -*- Report at generation %s" generation)(flush) (printf "\n;; -*- Report at generation %s" generation)(flush)
Expand Down Expand Up @@ -112,7 +159,10 @@
(println "Median copy number: " (nth (sort (vals frequency-map)) (Math/floor (/ (count frequency-map) 2))))) (println "Median copy number: " (nth (sort (vals frequency-map)) (Math/floor (/ (count frequency-map) 2)))))
(printf "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n") (printf "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n")
(flush) (flush)
(csv-print population generation) (when print-csv-logs (csv-print population generation csv-log-filename
log-fitnesses-for-all-cases))
(when print-json-logs (json-print population generation json-log-filename
log-fitnesses-for-all-cases json-log-program-strings))
(problem-specific-report best population generation error-function report-simplifications) (problem-specific-report best population generation error-function report-simplifications)
best))) best)))


Expand Down Expand Up @@ -152,8 +202,7 @@
(catch Exception e (catch Exception e
(printf "Hash of last Git commit = unavailable\n") (printf "Hash of last Git commit = unavailable\n")
(printf "GitHub link = unavailable\n") (printf "GitHub link = unavailable\n")
(flush))) (flush))))
(csv-init))


(defn final-report (defn final-report
"Prints the final report of a PushGP run if the run is successful." "Prints the final report of a PushGP run if the run is successful."
Expand Down

0 comments on commit c869dcd

Please sign in to comment.