Permalink
Browse files

Added functionality for printing json formatted logs.

Also added a odd problem example that includes log printing.
  • Loading branch information...
1 parent fafef03 commit c869dcd5bba1565a8fdc7b5c7fec158618eba727 @thelmuth thelmuth committed Sep 27, 2012
View
Binary file not shown.
View
@@ -5,5 +5,6 @@
:dependencies [[org.clojure/clojure "1.3.0"]
[org.clojure/math.numeric-tower "0.0.1"]
[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)
@@ -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
+ )
@@ -36,7 +36,10 @@
gaussian-mutation-standard-deviation reuse-errors
problem-specific-report use-single-thread random-seed
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)
error-threshold 0
population-size 1000
@@ -69,6 +72,12 @@
gaussian-mutation-standard-deviation 0.1
reuse-errors true
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
random-seed (System/nanoTime)
use-historically-assessed-hardness false
@@ -91,17 +100,20 @@
(reset! global-use-rmse use-rmse)
(initial-report) ;; Print the inital report
(print-params
- (error-function error-threshold population-size max-points max-points-in-initial-program
- atom-generators max-generations
- mutation-probability mutation-max-points crossover-probability
- simplification-probability gaussian-mutation-probability
- gaussian-mutation-per-number-mutation-probability gaussian-mutation-standard-deviation
- tournament-size report-simplifications final-report-simplifications
- reproduction-simplifications trivial-geography-radius decimation-ratio
- 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))
+ (atom-generators print-csv-logs csv-log-filename print-json-logs
+ json-log-filename log-fitnesses-for-all-cases
+ json-log-program-strings error-function error-threshold
+ population-size max-generations max-points
+ max-points-in-initial-program
+ mutation-probability mutation-max-points crossover-probability
+ simplification-probability gaussian-mutation-probability
+ gaussian-mutation-per-number-mutation-probability gaussian-mutation-standard-deviation
+ tournament-size report-simplifications final-report-simplifications
+ reproduction-simplifications trivial-geography-radius decimation-ratio
+ 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)
(let [pop-agents (vec (doall (for [_ (range population-size)]
((if use-single-thread atom agent)
@@ -130,7 +142,10 @@
population-size)
;; report and check for success
(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)
(final-report generation best error-function final-report-simplifications)
(do (if (>= generation max-generations)
@@ -1,10 +1,11 @@
(ns clojush.pushgp.report
- (:require [clojure.string :as string]
- [local-file])
(:use [clojush.util]
[clojush.globals]
[clojush.pushstate]
- [clojush.simplification]))
+ [clojush.simplification]
+ [clojure.data.json :only (json-str)])
+ (:require [clojure.string :as string]
+ [local-file]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; helper functions
@@ -33,38 +34,37 @@
(cons 'do (doall (map #(list 'println (str %) "=" %) params))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; report printing functions
-
-(def fname "log.csv")
-(def printAllTestCases true)
-
-(defn csv-init
- []
- (spit fname "generation,individual,total-error,size\n" :append false))
+;; log printing (csv and json)
(defn csv-print
- [population generation]
- (if (not printAllTestCases)
- (doseq [[ind p] (map-indexed vector population)]
- (spit fname
- (format "%s,%s,%s,%s\n"
- generation
- ind
- (:total-error p)
- (count-points (:program p)))
- :append true))
+ "Prints a csv 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 csv-log-filename log-fitnesses-for-all-cases]
+ (if (not log-fitnesses-for-all-cases)
(do
(when (zero? generation)
- (spit fname "generation,individual,total-error,size," :append false)
- (spit fname
+ (spit csv-log-filename "generation,individual,total-error,size\n" :append false))
+ (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"
(apply str
"TC"
(interpose ",TC"
(range (count (:errors (first population)))))))
:append true))
(doseq [[ind p] (map-indexed vector population)]
- (spit fname
+ (spit csv-log-filename
(format "%s,%s,%s,%s,%s\n"
generation
ind
@@ -73,12 +73,59 @@
(apply str (interpose "," (:errors p))))
: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
"Reports on the specified generation of a pushgp run. Returns the best
individual of the generation."
- ([population generation error-function report-simplifications]
- (report population generation error-function report-simplifications default-problem-specific-report))
- ([population generation error-function report-simplifications 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]
+ (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)
;(println (map :total-error population))(flush) ;***
(printf "\n;; -*- Report at generation %s" generation)(flush)
@@ -112,7 +159,10 @@
(println "Median copy number: " (nth (sort (vals frequency-map)) (Math/floor (/ (count frequency-map) 2)))))
(printf "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n")
(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)
best)))
@@ -152,8 +202,7 @@
(catch Exception e
(printf "Hash of last Git commit = unavailable\n")
(printf "GitHub link = unavailable\n")
- (flush)))
- (csv-init))
+ (flush))))
(defn final-report
"Prints the final report of a PushGP run if the run is successful."

0 comments on commit c869dcd

Please sign in to comment.