Revision 6639f96c2ca23a85ec6ffca0cfea40204a357f14 authored by Lee Spector on 04 May 2018, 17:08:28 UTC, committed by Lee Spector on 04 May 2018, 17:08:28 UTC
1 parent bf84d37
evaluate.clj
(ns clojush.evaluate
(:use [clojush util pushstate random globals individual]
clojush.pushgp.genetic-operators)
(:require [clojure.math.numeric-tower :as math]
[clj-random.core :as random]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; calculate the solution rates (only called from pushgp)
(defn calculate-hah-solution-rates
[pop-agents {:keys [total-error-method error-threshold population-size]}]
(when (= total-error-method :hah)
(reset! solution-rates
(let [error-seqs (map :errors (map deref pop-agents))
num-cases (count (first error-seqs))]
(doall (for [i (range num-cases)]
(/ (count (filter #(<= % error-threshold)
(map #(nth % i) error-seqs)))
population-size)))))
(printf "\nSolution rates: ")
(println (doall (map float @solution-rates)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; calculate meta-errors
(defn evaluate-individual-meta-errors
"Calculates one meta-error for each meta-error category provided. Each
meta-error-category should either be a keyword for a built-in meta category
or a function that takes an individual and an argmap and returns a meta error value.
The built-in meta categories include:
:size (minimize size of program)
:compressibility (minimize ammount a program compresses compared to itself)
:total-error (minimize total error)
:unsolved-cases (maximize number of cases with zero error)
:rand (a random floating-point value)
:rand-bit (randomly 0 or 1)
:age (minimize genealogical age of program)"
[ind evaluated-population rand-gen
{:keys [meta-error-categories error-threshold improvement-discount] :as argmap}]
(random/with-rng
rand-gen
(let [meta-error-fn
(fn [cat]
(cond
(fn? cat) (cat ind argmap)
(= cat :size) (count (:genome ind))
;(= cat :compressibility) 555 ;;TMH fix later
(= cat :total-error) (:total-error ind)
(= cat :unsolved-cases) (count (filter #(> % error-threshold)
(:errors ind)))
(= cat :rand) (lrand)
(= cat :rand-bit) (lrand-nth [0 1])
(= cat :age) (:age ind)
(= cat :novelty) :novelty ; Keyword will be replaced later,
; ; needs entire population to compute novelty
;
(= cat :amorphousness)
(- 1 (double (/ (count-parens (:program ind))
(count-points (:program ind))))) ;Number of (open) parens / points
;
(= cat :gens-since-total-error-change)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :gens-since-total-error-change"))
(let [hist (mapv (partial reduce +) (:history ind))]
(if (or (empty? hist)
(apply = hist))
1000000
(dec (count (take-while #(= % (first hist)) (rest hist)))))))
;
(= cat :gens-since-error-change)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :gens-since-total-error-change"))
(let [hist (:history ind)]
(if (or (empty? hist)
(apply = hist))
1000000
(dec (count (take-while #(= % (first hist)) (rest hist)))))))
;
(= cat :gens-since-total-error-improvement)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :gens-since-total-error-improvement"))
(let [diffs (mapv (fn [[a b]] (- a b))
(partition 2 1 (mapv (partial reduce +)
(:history ind))))]
(if (or (empty? diffs)
(not (some neg? diffs)))
1000000
(count (take-while #(>= % 0) diffs)))))
;
(= cat :total-error-improvement-ratio)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :total-error-improvement-ratio"))
(let [diffs (mapv (fn [[a b]] (- a b))
(partition 2 1 (mapv (partial reduce +)
(:history ind))))]
(if (empty? diffs)
1000000
(- 1 (/ (count (filter neg? diffs))
(count diffs))))))
;
(= cat :total-error-new-best-ratio)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :total-error-new-best-ratio"))
(let [hist (mapv (partial reduce +) (:history ind))]
(if (empty? (rest hist))
1000000
(loop [remaining hist
new-best-count 0]
(if (empty? (rest remaining))
(- 1 (/ new-best-count (dec (count hist))))
(recur (rest remaining)
(+ new-best-count
(if (every? #(> % (first remaining))
(rest remaining))
1
0))))))))
;
(= cat :discounted-total-error-new-best-ratio)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :discounted-total-error-new-best-ratio"))
(let [hist (mapv (partial reduce +) (:history ind))]
(if (empty? (rest hist))
1000000
(loop [remaining hist
new-best-count 0
scale 1
max-total 0]
(if (empty? (rest remaining))
(- 1.0 (/ new-best-count max-total))
(recur (rest remaining)
(+ new-best-count
(if (every? #(> % (first remaining))
(rest remaining))
(/ 1 scale)
0))
(* 2.0 scale)
(+ max-total (/ 1 scale))))))))
;
(= cat :discounted-total-error-improvement)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true, :discounted-total-error-improvement-ratio"))
(if (empty? (rest (:history ind)))
1000000
(let [diffs (mapv (fn [[a b]] (- a b))
(partition 2 1 (mapv (partial reduce +) (:history ind))))
improvements (mapv #(if (neg? %) 1.0 0.0)
diffs)
persistence 0.5
weights (take (count diffs)
(iterate (partial * persistence) 0.5))
sum (reduce + (mapv * improvements weights))]
(if (<= sum 0)
1.0E100
(- 1.0 sum)))))
;
(= cat :case-stagnation) ;; formerly :discounted-case-improvements
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-stagnation"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1000000))
(vec (for [case-history (apply map list (:history ind))]
(if (zero? (first case-history))
-100000 ;; solved, improvement doesn't matter
(let [improvements (mapv (fn [[newer-error older-error]]
(if (< newer-error older-error)
1.0
(if true ;(= newer-error older-error) ;for now only improvement counts
0.0
-1.0)))
(partition 2 1 case-history))
weights (take (count improvements)
(iterate (partial * (- 1 improvement-discount)) 1))
sum (reduce + (mapv * improvements weights))]
(- sum)))))))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-stagnation"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1000000))
(vec (for [case-history (apply map list (:history ind))]
(if (zero? (first case-history))
-100000 ;; solved, improvement doesn't matter
(let [improvements (mapv (fn [[newer-error older-error]]
(if (< newer-error older-error)
1.0
(if (= newer-error older-error)
0.0
-1.0)))
(partition 2 1 case-history))
weights (take (count improvements)
(iterate (partial * (- 1 improvement-discount)) 1))
sum (reduce + (mapv * improvements weights))]
(- sum)))))))
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-stagnation"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1000000))
(vec (for [case-history (apply map list (:history ind))]
(if (zero? (first case-history))
-100000 ;; solved, improvement doesn't matter
(let [improvements (mapv (fn [[newer-error older-error]]
(if (< newer-error older-error)
1.0
(if (= newer-error older-error)
-1.0
0.0)))
(partition 2 1 case-history))
weights (take (count improvements)
(iterate (partial * (- 1 improvement-discount)) 1))
sum (reduce + (mapv * improvements weights))]
(- sum)))))))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-stagnation"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1000000))
(vec (for [case-history (apply map list (:history ind))]
(let [improvements (mapv (fn [[newer-error older-error]]
(if (< newer-error older-error)
1.0
(if (= newer-error older-error)
-1.0
0.0)))
(partition 2 1 case-history))
weights (take (count improvements)
(iterate (partial * (- 1 improvement-discount)) 1))
sum (reduce + (mapv * improvements weights))]
(- sum))))))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-stagnation"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1000000))
(vec (for [case-history (apply map list (:history ind))]
(let [improvements (mapv (fn [[newer-error older-error]]
(if (or (zero? newer-error)
(< newer-error older-error))
1.0
(if (= newer-error older-error)
-1.0
0.0)))
(partition 2 1 case-history))
weights (take (count improvements)
(iterate (partial * (- 1 improvement-discount)) 1))
sum (reduce + (mapv * improvements weights))]
(- sum))))))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-stagnation"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1000000))
(vec (for [case-history (apply map list (:history ind))]
(if (zero? (first case-history))
-100000 ;; solved, improvement doesn't matter
(let [improvements (mapv (fn [[newer-error older-error]]
(if (< newer-error older-error)
1.0
(if (= newer-error older-error)
1.0
0.0)))
(partition 2 1 case-history))
weights (take (count improvements)
(iterate (partial * (- 1 improvement-discount)) 1))
sum (reduce + (mapv * improvements weights))]
(- sum)))))))
;
(= cat :case-gens-since-improvement)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-gens-since-improvement"))
(let [huge 1000000]
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) huge))
(vec (for [case-history (apply map list (:history ind))]
(if (zero? (first case-history))
(- huge) ;; solved, improvement doesn't matter
(let [improved? (mapv (fn [[newer-error older-error]]
(< newer-error older-error))
(partition 2 1 case-history))
gens (take-while not improved?)]
(if (= (count gens)
(count improved?))
huge
(count gens)))))))))
(= cat :case-gens-since-change)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-gens-since-change"))
(let [huge 1000000]
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) huge))
(vec (for [case-history (apply map list (:history ind))]
(if (zero? (first case-history))
(- huge) ;; solved, improvement doesn't matter
(let [changed? (mapv (fn [[newer-error older-error]]
(not= newer-error older-error))
(partition 2 1 case-history))
gens (take-while not changed?)]
(if (= (count gens)
(count changed?))
huge
(count gens)))))))))
;
(= cat :case-sibling-uniformity)
(if (empty? (:parent-uuids ind))
(vec (repeat (count (:errors ind)) 1))
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (:is-random-replacement %))) ; new random sibs don't count
evaluated-population)]
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(if (or (empty? siblings)
(apply = (mapv #(nth (:errors %) case-index)
siblings)))
1
0))))))
;
(= cat :case-family-uniformity)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-family-uniformity"))
(if (or (empty? (:parent-uuids ind))
(empty? (rest (:history ind))))
(vec (repeat (count (:errors ind)) 1))
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (empty? (rest (:history %))))) ; new random sibs don't count
evaluated-population)]
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(if
(some (fn [sib]
(or (zero? (-> (:history sib) ;; sib solved
(first)
(nth case-index)))
(not= (-> (:history sib) ;; sib error different than mom's
(first)
(nth case-index))
(-> (:history sib)
(second)
(nth case-index)))))
siblings)
1
2)))))))
;
(= cat :mom-doesnt-change-behavior)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-family-uniformity"))
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (empty? (rest (:history %))))) ; new random sibs don't count
evaluated-population)]
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index))
0 ;; solved
(if (or (empty? (:parent-uuids ind))
(empty? (rest (:history ind))))
2 ;; not solved, no mom who might have produced diff behaviors
(if
(some (fn [sib]
(not= (-> (:history sib) ;; sib error different than mom's
(first)
(nth case-index))
(-> (:history sib)
(second)
(nth case-index))))
siblings)
1 ;; not solved, mom did produce diff behaviors
3 ;; not solved, mom didn't produce diff behaviors
)))))))
;
(= cat :case-appropriate-family-uniformity)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-appropriate-family-uniformity"))
(if (or (empty? (:parent-uuids ind))
(empty? (rest (:history ind))))
(vec (repeat (count (:errors ind)) 1))
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (empty? (rest (:history %))))) ; new random sibs don't count
evaluated-population)]
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (second (:history ind)) case-index))
(if ;; mom solved, error for any child to be different
(some (fn [sib]
(not= (-> (:history sib) ;; sib error different than mom's
(first)
(nth case-index))
(-> (:history sib)
(second)
(nth case-index))))
siblings)
1
0)
(if ;; mom unsolved, error if there's not a different child
(some (fn [sib]
(not= (-> (:history sib) ;; sib error different than mom's
(first)
(nth case-index))
(-> (:history sib)
(second)
(nth case-index))))
siblings)
0
1)))))))
;
(= cat :case-scaled-error-plus-change)
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(+ (* e 1000000) (- e (min p1e p2e)))))
(:errors ind))
(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(+' (*' e 1000000)
(#(cond
(neg? %) -1
(pos? %) 1
:else 0)
(- e (min p1e p2e))))))
(mapv #(*' % 1000000) (:errors ind)))
;
(= cat :case-family-non-improvement)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-family-non-improvement"))
(if (or (empty? (:parent-uuids ind))
(empty? (rest (:history ind))))
(vec (repeat (count (:errors ind)) 1))
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (empty? (rest (:history %))))) ; new random sibs don't count
evaluated-population)]
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(if
(some (fn [sib]
(or (zero? (-> (:history sib) ;; sib solved
(first)
(nth case-index)))
(< (-> (:history sib) ;; sib error better than mom's
(first)
(nth case-index))
(-> (:history sib)
(second)
(nth case-index)))))
siblings)
1
2)))))))
;
(= cat :case-family-non-improvement-or-uniformity)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-family-non-improvement"))
(if (or (empty? (:parent-uuids ind))
(empty? (rest (:history ind))))
(vec (repeat (count (:errors ind)) 1))
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (empty? (rest (:history %))))) ; new random sibs don't count
evaluated-population)]
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(if
(some (fn [sib]
(or (zero? (-> (:history sib) ;; sib solved
(first)
(nth case-index)))
(< (-> (:history sib) ;; sib error better than mom's
(first)
(nth case-index))
(-> (:history sib)
(second)
(nth case-index)))))
siblings)
1
(if (some (fn [sib]
(not= (-> (:history sib) ;; sib error different than mom's
(first)
(nth case-index))
(-> (:history sib)
(second)
(nth case-index))))
siblings)
2
3))))))))
;
(= cat :case-family-certainty)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-family-certainty"))
(if (or (empty? (:parent-uuids ind))
(empty? (rest (:history ind))))
(vec (repeat (count (:errors ind)) 1))
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (empty? (rest (:history %))))) ; new random sibs don't count
evaluated-population)]
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(/ 1 (count
(distinct
(for [s siblings]
(nth (first (:history s))
case-index)))))))))))
;
(= cat :family-uniformity)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :family-variation"))
(if (or (empty? (:parent-uuids ind))
(empty? (rest (:history ind))))
1
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (empty? (rest (:history %))))) ; new random sibs don't count
evaluated-population)]
(if (some (fn [sib]
(not= (first (:history sib))
(second (:history sib))))
siblings)
0
1))))
;
(= cat :repeated-errors)
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (or (empty? (rest (:history ind)))
(some #{(first (:history ind))}
(set (rest (:history ind)))))
1
0))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (some #{(first (:history ind))}
(set (rest (:history ind))))
1
0))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (or (empty? (rest (:history ind)))
(some #{(first (:history ind))}
(set (take 3 (rest (:history ind))))))
1
0))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (empty? (rest (:history ind)))
1
(if (some #{(first (:history ind))}
(set (rest (:history ind))))
(/ 1 (inc (count (take-while #(not= % (first (:history ind)))
(rest (:history ind))))))
0)))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1))
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(let [latest (nth (first (:history ind)) case-index)
olders (map #(nth % case-index) (rest (:history ind)))]
(if (some #{latest} (set olders))
(/ 1 (inc (count (take-while #(not= % latest) olders))))
0)))))))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 2))
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(let [latest (nth (first (:history ind)) case-index)
olders (map #(nth % case-index) (rest (:history ind)))]
(if (some #{latest} (set olders))
2
1)))))))
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 2))
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(let [latest (nth (first (:history ind)) case-index)
olders (map #(nth % case-index) (rest (:history ind)))]
(if (some #{latest} (set olders))
3
1)))))))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (empty? (rest (:history ind)))
1
(let [latest (first (:history ind))
olders (rest (:history ind))]
(if (some #{latest} (set olders))
2
0))))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1))
(vec (for [case-index (range (count (:errors ind)))]
(let [latest (nth (first (:history ind)) case-index)
olders (map #(nth % case-index) (rest (:history ind)))]
(if (some #{latest} (set olders))
2
0))))))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1))
(vec (for [case-index (range (count (:errors ind)))]
(let [latest (nth (first (:history ind)) case-index)
olders (map #(nth % case-index) (take 3 (rest (:history ind))))]
(if (some #{latest} (set olders))
2
0))))))
#_(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :repeated-errors"))
(if (empty? (rest (:history ind)))
(vec (repeat (count (:errors ind)) 1))
(vec (for [case-index (range (count (:errors ind)))]
(let [latest (nth (first (:history ind)) case-index)
olders (map #(nth % case-index) (rest (:history ind)))]
(if (some #{latest} (set olders))
2
0))))))
;
(= cat :error-favoritism)
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(math/abs (- (sequence-similarity (:errors ind) (:parent1-errors ind))
(sequence-similarity (:errors ind) (:parent2-errors ind))))
1.0)
#_(let [p1e (:parent1-errors ind)
p2e (:parent2-errors ind)
e (:errors ind)]
(if (and p1e p2e)
(let [p1-shortfall (count (filter #(apply > %) (map list e p1e)))
p2-shortfall (count (filter #(apply > %) (map list e p2e)))]
(Math/abs (- p1-shortfall p2-shortfall)))
(count e)))
(if (and (:parent1-errors ind) (:parent2-errors ind))
(let [all (map list
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))
diff-parents (filter (fn [[e p1e p2e]] (not= p1e p2e)) all)
from-p1 (count (filter (fn [[e p1e p2e]] (= e p1e)) diff-parents))
from-p2 (count (filter (fn [[e p1e p2e]] (= e p2e)) diff-parents))]
(if (empty? diff-parents)
0
(/ (Math/abs (- from-p1 from-p2))
(count diff-parents))))
1)
;
(= cat :case-error-neglect)
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(if (== e (min p1e p2e))
0
1)))
(vec (repeat (count (:errors ind)) 1)))
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(if (and (not= p1e p2e)
(== e (min p1e p2e)))
0
1)))
(vec (repeat (count (:errors ind)) 1)))
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(if (< e (max p1e p2e))
0
1)))
(vec (repeat (count (:errors ind)) 1)))
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(< e (min p1e p2e)) 0
(= e (min p1e p2e)) 1
(< e (max p1e p2e)) 2
(= e (max p1e p2e)) 3
:else 4)))
(vec (repeat (count (:errors ind)) 5)))
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(= e (min p1e p2e)) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5)))
(vec (repeat (count (:errors ind)) 6)))
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 6
(< e (min p1e p2e)) 0
(= e (min p1e p2e)) 1
(< e (max p1e p2e)) 2
(= e (max p1e p2e)) 3
:else 4)))
(vec (repeat (count (:errors ind)) 5)))
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(< e (min p1e p2e)) 0
(= e (min p1e p2e)) 2
(< e (max p1e p2e)) 1
(= e (max p1e p2e)) 4
:else 3)))
(vec (repeat (count (:errors ind)) 5)))
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(= e (min p1e p2e)) 3
(< e (max p1e p2e)) 2
(= e (max p1e p2e)) 5
:else 4)))
(vec (repeat (count (:errors ind)) 6)))
(if (and (:parent1-errors ind) (:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(and (not= p1e p2e) (= e (min p1e p2e))) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5)))
(vec (repeat (count (:errors ind)) 6)))
;
(= cat :devolution)
#_(if (and (:parent1-errors ind)
(:parent2-errors ind)
(not= (:errors ind) (:parent1-errors ind))
(not= (:errors ind) (:parent2-errors ind)))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(and (not= p1e p2e) (= e (min p1e p2e))) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5)))
(vec (repeat (count (:errors ind)) 6)))
(if (and (:parent1-errors ind)
(:parent2-errors ind))
(if (or (= (:errors ind) (:parent1-errors ind))
(= (:errors ind) (:parent2-errors ind)))
(vec (repeat (count (:errors ind)) 7))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(and (not= p1e p2e) (= e (min p1e p2e))) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5))))
(vec (repeat (count (:errors ind)) 6)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(if (or (= (:errors ind) (:parent1-errors ind))
(= (:errors ind) (:parent2-errors ind)))
(vec (repeat (count (:errors ind)) 7))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
;(zero? e) 0
(< e (min p1e p2e)) 1
(and (not= p1e p2e) (= e (min p1e p2e))) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5))))
(vec (repeat (count (:errors ind)) 6)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(if (or (= (:errors ind) (:parent1-errors ind))
(= (:errors ind) (:parent2-errors ind)))
(vec (repeat (count (:errors ind)) 7))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 1
(< e (min p1e p2e)) 1
(and (not= p1e p2e) (= e (min p1e p2e))) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5))))
(vec (repeat (count (:errors ind)) 6)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(if (or (= (:errors ind) (:parent1-errors ind))
(= (:errors ind) (:parent2-errors ind)))
(vec (repeat (count (:errors ind)) 5))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(or (zero? e) (< e (min p1e p2e))) 0
(some #{e} [p1e p2e]) 3
(< e (max p1e p2e)) 1
:else 2))))
(vec (repeat (count (:errors ind)) 4)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(and (not= p1e p2e) (= e (min p1e p2e))) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5)))
(vec (repeat (count (:errors ind)) 6)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 1
(< e (min p1e p2e)) 1
(and (not= p1e p2e) (= e (min p1e p2e))) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5)))
(vec (repeat (count (:errors ind)) 6)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(or (zero? e) (< e (min p1e p2e))) 0
(some #{e} [p1e p2e]) 3
(< e (max p1e p2e)) 1
:else 2)))
(vec (repeat (count (:errors ind)) 3)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(some #{e} [p1e p2e]) 4
(< e (max p1e p2e)) 2
:else 3)))
(vec (repeat (count (:errors ind)) 4)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(some #{e} [p1e p2e]) 3
(< e (max p1e p2e)) 2
:else 4)))
(vec (repeat (count (:errors ind)) 4)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 1
(< e (min p1e p2e)) 1
(some #{e} [p1e p2e]) 3
(< e (max p1e p2e)) 2
:else 4)))
(vec (repeat (count (:errors ind)) 4)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(< e (max p1e p2e)) 2
:else 3)))
(vec (repeat (count (:errors ind)) 3)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(< e (min p1e p2e)) 0
(< e (max p1e p2e)) 1
:else 2)))
(vec (repeat (count (:errors ind)) 2)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(= e (min p1e p2e)) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5)))
(vec (repeat (count (:errors ind)) 5)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 1
(< e (min p1e p2e)) 1
(= e (min p1e p2e)) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 4
:else 5)))
(vec (repeat (count (:errors ind)) 5)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(= e (min p1e p2e)) 2
(< e (max p1e p2e)) 3
(= e (max p1e p2e)) 5
:else 4)))
(vec (repeat (count (:errors ind)) 5)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(= e (min p1e p2e)) 2
(< e (max p1e p2e)) 2
(= e (max p1e p2e)) 2
:else 3)))
(vec (repeat (count (:errors ind)) 3)))
#_(if (:parent1-errors ind)
(vec (for [[e p1e] (mapv #(vector %1 %2)
(:errors ind)
(:parent1-errors ind))]
(cond
(zero? e) 0
(< e p1e) 1
(= e p1e) 2
:else 3)))
(vec (repeat (count (:errors ind)) 3)))
#_(if (:parent1-errors ind)
(vec (for [[e p1e] (mapv #(vector %1 %2)
(:errors ind)
(:parent1-errors ind))]
(cond
(zero? e) 0
(< e p1e) 1
(= e p1e) 3
:else 2)))
(vec (repeat (count (:errors ind)) 2)))
#_(if (:parent1-errors ind)
(vec (for [[e p1e] (mapv #(vector %1 %2)
(:errors ind)
(:parent1-errors ind))]
(cond
(zero? e) 0
(< e p1e) 1
(= e p1e) 2
:else 2)))
(vec (repeat (count (:errors ind)) 2)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 1
(< e (max p1e p2e)) 2
(not (some #{e} [p1e p2e])) 3
:else 4)))
(vec (repeat (count (:errors ind)) 4)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
;(zero? e) 0
(< e (min p1e p2e)) 1
(< e (max p1e p2e)) 2
(not (some #{e} [p1e p2e])) 3
:else 4)))
(vec (repeat (count (:errors ind)) 4)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
;(zero? e) 0
(< e (min p1e p2e)) 1
(< e (max p1e p2e)) 2
(some #{e} [p1e p2e]) 3
:else 4)))
(vec (repeat (count (:errors ind)) 4)))
#_(if (and (:parent1-errors ind)
(:parent2-errors ind))
(vec (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(cond
(zero? e) 0
(< e (min p1e p2e)) 0
(< e (max p1e p2e)) 1
(some #{e} [p1e p2e]) 2
:else 3)))
(vec (repeat (count (:errors ind)) 3)))
;
(= cat :error-neglect)
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(reduce + (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(if (and (not= p1e p2e)
(== e (min p1e p2e)))
0
1)))
(count (:errors ind)))
#_(if (and (:parent1-errors ind) (:parent2-errors ind))
(reduce + (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(if (< e (max p1e p2e))
0
1)))
(count (:errors ind)))
(if (and (:parent1-errors ind) (:parent2-errors ind))
(reduce + (for [[e p1e p2e] (mapv #(vector %1 %2 %3)
(:errors ind)
(:parent1-errors ind)
(:parent2-errors ind))]
(if (<= e (min p1e p2e))
0
1)))
(count (:errors ind)))
;
(= cat :case-family-variation)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :case-family-variation"))
(if (or (empty? (:parent-uuids ind))
(empty? (rest (:history ind))))
(vec (repeat (count (:errors ind)) 1))
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (empty? (rest (:history %))))) ; new random sibs don't count
evaluated-population)]
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(if
(some (fn [sib] ;; sibling solved
(zero? (-> (:history sib)
(first)
(nth case-index))))
siblings)
0
(if (some (fn [sib] ;; sib error different than mom's
(not= (-> (:history sib)
(first)
(nth case-index))
(-> (:history sib)
(second)
(nth case-index))))
siblings)
1
0))))))))
;
(= cat :washout-mother)
(if (not (:print-history argmap))
(throw
(Exception.
":print-history must be true for :washout-mother"))
(if (or (empty? (:parent-uuids ind))
(empty? (rest (:history ind))))
(vec (repeat (count (:errors ind)) 1))
(let [siblings (filter #(and (= (first (:parent-uuids ind))
(first (:parent-uuids %)))
(not (empty? (rest (:history %))))) ; new random sibs don't count
evaluated-population)]
(vec (for [case-index (range (count (:errors ind)))]
(if (zero? (nth (:errors ind) case-index)) ;; solved
0
(if
(some (fn [sib]
(or (zero? (-> (:history sib)
(first)
(nth case-index)))
(< (-> (:history sib)
(first)
(nth case-index))
(-> (:history sib)
(second)
(nth case-index)))))
siblings)
0
1)))))))
;
(= cat :clone-distance)
(/ 1 (let [limit 100]
(loop [step 1
genomes (list (:genome ind))]
(if (>= step limit)
step
(let [child (produce-child-genome-by-autoconstruction
(first genomes)
(first genomes)
argmap)]
(if (some #{child} (set genomes))
step
(recur (inc step) (cons child genomes))))))))
;
(= cat :reproductive-infidelity)
(let [g (:genome ind)]
(- 1.0
(sequence-similarity
g
(produce-child-genome-by-autoconstruction g g argmap))))
;
(= cat :reproductive-fidelity)
(let [g (:genome ind)]
(sequence-similarity
g
(produce-child-genome-by-autoconstruction g g argmap)))
;
(= cat :reproductive-inconsistency)
(let [g (:genome ind)]
(- 1.0
(sequence-similarity
(produce-child-genome-by-autoconstruction g g argmap)
(produce-child-genome-by-autoconstruction g g argmap))))
;
(= cat :reproductive-consistency)
(let [g (:genome ind)]
(sequence-similarity
(produce-child-genome-by-autoconstruction g g argmap)
(produce-child-genome-by-autoconstruction g g argmap)))
;
(= cat :similarity-to-most-similar-parent)
(if (and (:parent1-genome ind) (:parent2-genome ind))
(max (sequence-similarity (:genome ind) (:parent1-genome ind))
(sequence-similarity (:genome ind) (:parent2-genome ind)))
1.0)
;
(= cat :difference-from-most-similar-parent)
(- 1.0 (if (and (:parent1-genome ind) (:parent2-genome ind))
(max (sequence-similarity (:genome ind) (:parent1-genome ind))
(sequence-similarity (:genome ind) (:parent2-genome ind)))
0.0))
;
(= cat :difference-from-least-similar-parent)
(- 1.0 (if (and (:parent1-genome ind) (:parent2-genome ind))
(min (sequence-similarity (:genome ind) (:parent1-genome ind))
(sequence-similarity (:genome ind) (:parent2-genome ind)))
0.0))
;
(= cat :difference-from-mate)
(- 1.0 (if (:parent2-genome ind)
(sequence-similarity (:genome ind) (:parent2-genome ind))
0.0))
;
(= cat :parent2-irrelevance)
(if (and (:parent1-genome ind) (:parent2-genome ind))
(let [similarity-to-p2 (sequence-similarity (:genome ind) (:parent2-genome ind))
p1-similarity-to-p2 (sequence-similarity (:parent1-genome ind) (:parent2-genome ind))]
(- 1.0 (max 0.0 (- similarity-to-p2 p1-similarity-to-p2))))
1.0)
;
(= cat :reproductive-convergence)
(if (and (:parent1-genome ind) (:parent2-genome ind))
(let [g (:genome ind)
child1-genome (produce-child-genome-by-autoconstruction g g argmap)
child2-genome (produce-child-genome-by-autoconstruction g g argmap)]
(max (sequence-similarity g child1-genome)
(sequence-similarity g child2-genome)
(sequence-similarity child1-genome child2-genome)))
1.0)
(= cat :favoritism)
#_(if (and (:parent1-genome ind) (:parent2-genome ind))
(math/abs (- (sequence-similarity (:genome ind) (:parent1-genome ind))
(sequence-similarity (:genome ind) (:parent2-genome ind))))
1.0)
(if (and (:parent1-genome ind)
(:parent2-genome ind)
(not= (:parent1-genome ind) (:parent2-genome ind)))
(/ (math/abs (- (sequence-similarity (:genome ind) (:parent1-genome ind))
(sequence-similarity (:genome ind) (:parent2-genome ind))))
(- 1 (sequence-similarity (:parent1-genome ind) (:parent2-genome ind))))
1.0)
;
(= cat :autoconstruction-blindness)
(if (some (fn [instruction-map]
(and (not (:silent instruction-map))
(some #{(:instruction instruction-map)}
#{'genome_autoconstructing 'genome_if_autoconstructing})))
(:genome ind))
0
1)
;
(= cat :no-genesis)
(if (some (fn [instruction-map]
(and (not (:silent instruction-map))
(some #{(:instruction instruction-map)}
#{'genome_genesis})))
(:genome ind))
0
1)
;
(= cat :static-instruction-set)
(if (:parent1-genome ind)
(let [instruction-set (fn [genome]
(hash-set (keys (frequencies (map :instruction genome)))))]
(if (= (instruction-set (:genome ind))
(instruction-set (:parent1-genome ind)))
1
0))
1)
;
(= cat :inherited-errors)
(if (and (:parent1-errors ind)
(:parent2-errors ind)
(not= (:errors ind) (:parent1-errors ind))
(not= (:errors ind) (:parent2-errors ind)))
0
1)
;
:else (throw (Exception. (str "Unrecognized meta category: " cat)))))]
(assoc ind :meta-errors (vec (flatten (mapv meta-error-fn meta-error-categories)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; evaluate individuals
(defn compute-total-error
[errors]
(reduce +' errors))
(defn compute-root-mean-square-error
[errors]
(math/sqrt (/ (apply +' (map #(* % %)
errors))
(count errors))))
(defn compute-hah-error
[errors]
(reduce +' (doall (map (fn [rate e] (*' (- 1.01 rate) e))
@solution-rates
errors))))
(defn normalize-errors
"Normalizes errors to [0,1] if normalize isn't :none."
[errors normalization max-error]
(if (= normalization :none)
errors
(map (fn [err]
(case normalization
:divide-by-max-error (double (if (>= err max-error)
1.0
(/ err max-error)))
:e-over-e-plus-1 (double (/ err (inc err)))
(throw (Exception. (str "Unrecognized argument for normalization: "
normalization)))))
errors)))
(defn evaluate-individual
"Returns the given individual with errors, total-errors, and weighted-errors,
computing them if necessary."
([i error-function rand-gen]
(evaluate-individual i error-function rand-gen
{:reuse-errors true
:print-history false
:total-error-method :sum
:normalization :none
:max-error 1000}))
([i error-function rand-gen
{:keys [reuse-errors print-history total-error-method normalization max-error]
:as argmap}]
(random/with-rng rand-gen
(let [p (:program i)
evaluated-i (if (or (not reuse-errors)
(nil? (:errors i)))
(error-function i)
i)
raw-errors (:errors evaluated-i)
e (vec (if (and reuse-errors (not (nil? (:errors i))))
(:errors i)
(do
(swap! evaluations-count inc)
(normalize-errors raw-errors normalization max-error))))
te (if (and reuse-errors (not (nil? (:total-error i))))
(:total-error i)
(compute-total-error raw-errors))
ne (if (and reuse-errors (not (nil? (:normalized-error i))))
(:normalized-error i)
(compute-total-error e))
we (case total-error-method
:sum nil
:ifs nil
:hah (compute-hah-error e)
:rmse (compute-root-mean-square-error e)
nil)
new-ind (assoc evaluated-i ; Assign errors and history to i
:errors e
:total-error te
:weighted-error we
:normalized-error ne
:history (if print-history (cons e (:history i)) (:history i)))]
new-ind))))
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...