implemented elite/not elite vector tracking, moved tests
This commit is contained in:
parent
e011fa7892
commit
b4e4552acb
@ -85,13 +85,13 @@
|
|||||||
(if (sequential? (:input1 (first new-downsample)))
|
(if (sequential? (:input1 (first new-downsample)))
|
||||||
(prn {:cases-in-ds (map #(first (:input1 %)) new-downsample) :cases-in-tourn (map #(first (:input1 %)) tournament)})
|
(prn {:cases-in-ds (map #(first (:input1 %)) new-downsample) :cases-in-tourn (map #(first (:input1 %)) tournament)})
|
||||||
(prn {:cases-in-ds (map #(:input1 %) new-downsample) :cases-in-tourn (map #(:input1 %) tournament)}))
|
(prn {:cases-in-ds (map #(:input1 %) new-downsample) :cases-in-tourn (map #(:input1 %) tournament)}))
|
||||||
;(prn {:min-case-distances min-case-distances :selected-case-index selected-case-index})
|
;(prn {:min-case-distances min-case-distances :selected-case-index selected-case-index})
|
||||||
(recur (conj new-downsample (nth tournament selected-case-index))
|
(recur (conj new-downsample (nth tournament selected-case-index))
|
||||||
(shuffle (utils/drop-nth selected-case-index tournament)))))))))
|
(shuffle (utils/drop-nth selected-case-index tournament)))))))))
|
||||||
|
|
||||||
(defn get-distance-between-cases
|
(defn get-distance-between-cases
|
||||||
"returns the distance between two cases given a list of individual error vectors, and the index these
|
"returns the distance between two cases given a list of individual error vectors, and the index these
|
||||||
cases exist in the error vector"
|
cases exist in the error vector. Only makes the distinction between zero and nonzero errors"
|
||||||
[error-lists case-index-1 case-index-2]
|
[error-lists case-index-1 case-index-2]
|
||||||
(if (or (< (count (first error-lists)) case-index-1)
|
(if (or (< (count (first error-lists)) case-index-1)
|
||||||
(< (count (first error-lists)) case-index-2)
|
(< (count (first error-lists)) case-index-2)
|
||||||
@ -119,15 +119,34 @@
|
|||||||
(if (nil? corresponding-small) % corresponding-small))
|
(if (nil? corresponding-small) % corresponding-small))
|
||||||
big-list))
|
big-list))
|
||||||
|
|
||||||
|
(defn replace-mins-with-zero
|
||||||
|
"replaces the minimum value(s) in a list with zero"
|
||||||
|
[coll]
|
||||||
|
(if (empty? coll)
|
||||||
|
'()
|
||||||
|
(let [m (apply min coll)]
|
||||||
|
(map #(if (= m %) 0 %) coll))))
|
||||||
|
|
||||||
|
(defn convert-to-elite-error
|
||||||
|
"converts a set of errors into a list where all the elite errors are replaced with 0s so that we can use
|
||||||
|
it in the selection of down-samples with elite/not-elite selection"
|
||||||
|
[errors]
|
||||||
|
(map #(replace-mins-with-zero %) errors))
|
||||||
|
|
||||||
(defn update-case-distances
|
(defn update-case-distances
|
||||||
"updates the case distance field of training-data list, should be called after evaluation of individuals
|
"updates the case distance field of training-data list, should be called after evaluation of individuals
|
||||||
evaluated-pop should be a list of individuals that all have the :errors field with a list of this
|
evaluated-pop should be a list of individuals that all have the :errors field with a list of this
|
||||||
individuals performance on the each case in the ds-data, in order"
|
individuals performance on the each case in the training-data, in order. ids-type is :elite to use elite/not-elite
|
||||||
[evaluated-pop ds-data training-data]
|
or :solved to use solve/not-solved"
|
||||||
(let [ds-indices (map #(:index %) ds-data) errors (map #(:errors %) evaluated-pop)]
|
|
||||||
|
[evaluated-pop ds-data training-data ids-type]
|
||||||
|
(flush)
|
||||||
|
(let [ds-indices (map #(:index %) ds-data)
|
||||||
|
errors (map #(:errors %) evaluated-pop)
|
||||||
|
corr-errors (if (= ids-type :elite) (convert-to-elite-error errors) errors)] ;errors, including elite/not-elite distinction
|
||||||
(merge-map-lists-at-index
|
(merge-map-lists-at-index
|
||||||
training-data (map-indexed
|
training-data (map-indexed
|
||||||
(fn [idx d-case] (update-in d-case
|
(fn [idx d-case] (update-in d-case
|
||||||
[:distances] #(update-at-indices
|
[:distances] #(update-at-indices
|
||||||
% (map (fn [other] (get-distance-between-cases errors idx other))
|
% (map (fn [other] (get-distance-between-cases corr-errors idx other))
|
||||||
(range (count ds-indices))) ds-indices))) ds-data))))
|
(range (count ds-indices))) ds-indices))) ds-data))))
|
@ -35,11 +35,12 @@
|
|||||||
(defn gp
|
(defn gp
|
||||||
"Main GP loop."
|
"Main GP loop."
|
||||||
[{:keys [population-size max-generations error-function instructions
|
[{:keys [population-size max-generations error-function instructions
|
||||||
max-initial-plushy-size solution-error-threshold mapper ds-parent-rate ds-parent-gens dont-end]
|
max-initial-plushy-size solution-error-threshold mapper ds-parent-rate ds-parent-gens dont-end ids-type]
|
||||||
:or {solution-error-threshold 0.0
|
:or {solution-error-threshold 0.0
|
||||||
dont-end false
|
dont-end false
|
||||||
ds-parent-rate 0
|
ds-parent-rate 0
|
||||||
ds-parent-gens 1
|
ds-parent-gens 1
|
||||||
|
ids-type :solved ; :solved or :elite
|
||||||
;; The `mapper` will perform a `map`-like operation to apply a function to every individual
|
;; The `mapper` will perform a `map`-like operation to apply a function to every individual
|
||||||
;; in the population. The default is `map` but other options include `mapv`, or `pmap`.
|
;; in the population. The default is `map` but other options include `mapv`, or `pmap`.
|
||||||
mapper #?(:clj pmap :cljs map)}
|
mapper #?(:clj pmap :cljs map)}
|
||||||
@ -118,6 +119,6 @@
|
|||||||
#(variation/new-individual reindexed-pop argmap)))))
|
#(variation/new-individual reindexed-pop argmap)))))
|
||||||
(if (= (:parent-selection argmap) :ds-lexicase)
|
(if (= (:parent-selection argmap) :ds-lexicase)
|
||||||
(if (zero? (mod generation ds-parent-gens))
|
(if (zero? (mod generation ds-parent-gens))
|
||||||
(downsample/update-case-distances rep-evaluated-pop indexed-training-data indexed-training-data) ; update distances every ds-parent-gens generations
|
(downsample/update-case-distances rep-evaluated-pop indexed-training-data indexed-training-data ids-type) ; update distances every ds-parent-gens generations
|
||||||
indexed-training-data)
|
indexed-training-data)
|
||||||
indexed-training-data))))))
|
indexed-training-data))))))
|
155
test/propeller/push/downsample_test.cljc
Normal file
155
test/propeller/push/downsample_test.cljc
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
(ns propeller.push.downsample-test
|
||||||
|
(:require [clojure.test :as t]
|
||||||
|
[propeller.utils :as u]
|
||||||
|
[propeller.simplification :as s]
|
||||||
|
[propeller.downsample :as ds]
|
||||||
|
[propeller.hyperselection :as hs]))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest assign-indices-to-data-test
|
||||||
|
(t/testing "assign-indices-to-data"
|
||||||
|
(t/testing "should return a map of the same length"
|
||||||
|
(t/is (= (count (ds/assign-indices-to-data (range 10))) 10))
|
||||||
|
(t/is (= (count (ds/assign-indices-to-data (range 0))) 0)))
|
||||||
|
(t/testing "should return a map where each element has an index key"
|
||||||
|
(t/is (every? #(:index %) (ds/assign-indices-to-data (map #(assoc {} :input %) (range 10))))))
|
||||||
|
(t/testing "should return distinct indices"
|
||||||
|
(t/is (= (map #(:index %) (ds/assign-indices-to-data (range 10))) (range 10))))))
|
||||||
|
|
||||||
|
(t/deftest select-downsample-random-test
|
||||||
|
(t/testing "select-downsample-random"
|
||||||
|
(t/testing "should select the correct amount of elements"
|
||||||
|
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 0.1})) 1))
|
||||||
|
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 0.2})) 2))
|
||||||
|
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 0.5})) 5)))
|
||||||
|
(t/testing "should not return duplicate items (when called with set of numbers)"
|
||||||
|
(t/is (= (count (set (ds/select-downsample-random (range 10) {:downsample-rate 0.1}))) 1))
|
||||||
|
(t/is (= (count (set (ds/select-downsample-random (range 10) {:downsample-rate 0.2}))) 2))
|
||||||
|
(t/is (= (count (set (ds/select-downsample-random (range 10) {:downsample-rate 0.5}))) 5)))
|
||||||
|
(t/testing "should round down the number of elements selected if not whole"
|
||||||
|
(t/is (= (count (ds/select-downsample-random (range 3) {:downsample-rate 0.5})) 1))
|
||||||
|
(t/is (= (count (ds/select-downsample-random (range 1) {:downsample-rate 0.5})) 0)))
|
||||||
|
(t/testing "should not return more elements than available"
|
||||||
|
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 2})) 10))
|
||||||
|
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 1.5})) 10)))))
|
||||||
|
|
||||||
|
(t/deftest get-distance-between-cases-test
|
||||||
|
(t/testing "get-distance-between-cases"
|
||||||
|
(t/testing "should return correct distance"
|
||||||
|
(t/is (= 3 (ds/get-distance-between-cases '((0 1 1) (0 1 1) (1 0 1)) 0 1))))
|
||||||
|
(t/testing "should return 0 for the distance of a case to itself"
|
||||||
|
(t/is (= 0 (ds/get-distance-between-cases '((0 1 1) (0 1 1) (1 0 1)) 0 0))))
|
||||||
|
(t/testing "should work for non binary values (0 is solved)"
|
||||||
|
(t/is (= 1 (ds/get-distance-between-cases '((0 2 2) (0 2 2) (1 0 50)) 1 2))))
|
||||||
|
(t/testing "should return the max distance if one of the cases does not exist"
|
||||||
|
(t/is (= 3 (ds/get-distance-between-cases '((0 1 1) (0 1 1) (1 0 1)) 0 4))))))
|
||||||
|
|
||||||
|
(t/deftest merge-map-lists-at-index-test
|
||||||
|
(t/testing "merge-map-lists-at-index"
|
||||||
|
(t/testing "works properly"
|
||||||
|
(t/is (= '({:index 0 :a 3 :b 2} {:index 1 :a 2 :b 3}) (ds/merge-map-lists-at-index '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) '({:index 1 :a 2 :b 3})))))
|
||||||
|
(t/testing "doesn't change big list if no indices match"
|
||||||
|
(t/is (= '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) (ds/merge-map-lists-at-index '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) '({:index 3 :a 2 :b 3})))))
|
||||||
|
(t/testing "doesn't fail on empty list"
|
||||||
|
(t/is (= '() (ds/merge-map-lists-at-index '() '()))))
|
||||||
|
(t/testing "shouldn't fail merging non-empty with empty"
|
||||||
|
(t/is (= '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) (ds/merge-map-lists-at-index '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) '()))))))
|
||||||
|
|
||||||
|
(t/deftest update-at-indices-test
|
||||||
|
(t/testing "update-at-indices"
|
||||||
|
(t/testing "should update at correct indices"
|
||||||
|
(t/is (= (ds/update-at-indices [1 2 3 4] [5] [0]) [5 2 3 4]))
|
||||||
|
(t/is (= (ds/update-at-indices [1 2 3 4] [5] [0]) [5 2 3 4])))
|
||||||
|
(t/testing "should update nothing if index list is empty"
|
||||||
|
(t/is (= (ds/update-at-indices [6 5 4 0 0] [] []) [6 5 4 0 0])))
|
||||||
|
(t/testing "should update nothing if index list is out of bounds"
|
||||||
|
(t/is (= (ds/update-at-indices [6 5 4 0 0] [4 5 1] [-1 5 6]) [6 5 4 0 0])))
|
||||||
|
(t/testing "should update only when indices are available (length mismatch)"
|
||||||
|
(t/is (= (ds/update-at-indices [6 5 4 0 0] [1 2 3 4] [0 1]) [1 2 4 0 0])))
|
||||||
|
(t/testing "should not care about index order"
|
||||||
|
(t/is (= (ds/update-at-indices [6 5 4 0 0] [2 1] [1 0]) [1 2 4 0 0])))
|
||||||
|
(t/testing "should work when input is a list"
|
||||||
|
(t/is (= (ds/update-at-indices '(6 5 4 0 0) '(2 1) '(1 0)) [1 2 4 0 0])))))
|
||||||
|
|
||||||
|
(t/deftest update-case-distances-test
|
||||||
|
(t/testing "update-case-distances"
|
||||||
|
(t/testing "should update correctly when fewer errors than all"
|
||||||
|
(t/is (= (ds/update-case-distances '({:errors (0 0)} {:errors (0 0)})
|
||||||
|
'({:index 3 :distances [2 2 2 2 2]} {:index 4 :distances [2 2 2 2 2]})
|
||||||
|
'({:index 0 :distances [2 2 2 2 2]} {:index 1 :distances [2 2 2 2 2]} {:index 2 :distances [2 2 2 2 2]} {:index 3 :distances [2 2 2 2 2]} {:index 4 :distances [2 2 2 2 2]})
|
||||||
|
:solved)
|
||||||
|
'({:index 0 :distances [2 2 2 2 2]} {:index 1 :distances [2 2 2 2 2]} {:index 2 :distances [2 2 2 2 2]}
|
||||||
|
{:index 3 :distances [2 2 2 0 0]} {:index 4 :distances [2 2 2 0 0]}))))
|
||||||
|
(t/testing "should update correctly when same errors as all"
|
||||||
|
(t/is (= (ds/update-case-distances '({:errors (0 0 0 0 0)} {:errors (0 0 0 0 0)})
|
||||||
|
'({:index 0 :distances [2 2 2 2 2]} {:index 1 :distances [2 2 2 2 2]} {:index 2 :distances [2 2 2 2 2]} {:index 3 :distances [2 2 2 2 2]} {:index 4 :distances [2 2 2 2 2]})
|
||||||
|
'({:index 0 :distances [2 2 2 2 2]} {:index 1 :distances [2 2 2 2 2]} {:index 2 :distances [2 2 2 2 2]} {:index 3 :distances [2 2 2 2 2]} {:index 4 :distances [2 2 2 2 2]})
|
||||||
|
:solved)
|
||||||
|
'({:index 0 :distances [0 0 0 0 0]} {:index 1 :distances [0 0 0 0 0]} {:index 2 :distances [0 0 0 0 0]}
|
||||||
|
{:index 3 :distances [0 0 0 0 0]} {:index 4 :distances [0 0 0 0 0]}))))
|
||||||
|
(t/testing "should update correctly for elite/not-elite"
|
||||||
|
(t/is (= (ds/update-case-distances '({:errors (1 1 1 2 2)} {:errors (2 2 2 1 1)})
|
||||||
|
'({:index 0 :distances [2 2 2 2 2]} {:index 1 :distances [2 2 2 2 2]} {:index 2 :distances [2 2 2 2 2]} {:index 3 :distances [2 2 2 2 2]} {:index 4 :distances [2 2 2 2 2]})
|
||||||
|
'({:index 0 :distances [2 2 2 2 2]} {:index 1 :distances [2 2 2 2 2]} {:index 2 :distances [2 2 2 2 2]} {:index 3 :distances [2 2 2 2 2]} {:index 4 :distances [2 2 2 2 2]})
|
||||||
|
:elite)
|
||||||
|
'({:index 0 :distances [0 0 0 2 2]} {:index 1 :distances [0 0 0 2 2]} {:index 2 :distances [0 0 0 2 2]}
|
||||||
|
{:index 3 :distances [2 2 2 0 0]} {:index 4 :distances [2 2 2 0 0]})))
|
||||||
|
)))
|
||||||
|
|
||||||
|
(t/deftest case-maxmin-test
|
||||||
|
(t/testing "case-maxmin selects correct downsample"
|
||||||
|
(let [selected (ds/select-downsample-maxmin
|
||||||
|
'({:input1 [0] :output1 [10] :index 0 :distances [0 5 0 0 0]}
|
||||||
|
{:input1 [1] :output1 [11] :index 1 :distances [5 0 5 5 5]}
|
||||||
|
{:input1 [2] :output1 [12] :index 2 :distances [0 5 0 0 0]}
|
||||||
|
{:input1 [3] :output1 [13] :index 3 :distances [0 5 0 0 0]}
|
||||||
|
{:input1 [4] :output1 [14] :index 4 :distances [0 5 0 0 0]})
|
||||||
|
{:downsample-rate 0.4})]
|
||||||
|
(prn {:selected selected})
|
||||||
|
(t/is (or (= (:index (first selected)) 1) (= (:index (second selected)) 1))))))
|
||||||
|
|
||||||
|
(t/deftest case-maxmin-adaptive
|
||||||
|
(t/testing "case-maxmin-adaptive selects correct downsample simple"
|
||||||
|
(let [selected (ds/select-downsample-maxmin-adaptive
|
||||||
|
'({:input1 [0] :output1 [10] :index 0 :distances [0 5 0 0 0]}
|
||||||
|
{:input1 [1] :output1 [11] :index 1 :distances [5 0 5 5 5]}
|
||||||
|
{:input1 [2] :output1 [12] :index 2 :distances [0 5 0 0 0]}
|
||||||
|
{:input1 [3] :output1 [13] :index 3 :distances [0 5 0 0 0]}
|
||||||
|
{:input1 [4] :output1 [14] :index 4 :distances [0 5 0 0 0]})
|
||||||
|
{:case-delta 0})]
|
||||||
|
(prn {:selected selected})
|
||||||
|
(t/is (or (= (:index (first selected)) 1) (= (:index (second selected)) 1)))
|
||||||
|
(t/is (= 2 (count selected)))))
|
||||||
|
(t/testing "case-maxmin-adaptive selects correct downsample when all identical"
|
||||||
|
(let [selected (ds/select-downsample-maxmin-adaptive
|
||||||
|
'({:input1 [0] :output1 [10] :index 0 :distances [0 0 0 0 0]}
|
||||||
|
{:input1 [1] :output1 [11] :index 1 :distances [0 0 0 0 0]}
|
||||||
|
{:input1 [2] :output1 [12] :index 2 :distances [0 0 0 0 0]}
|
||||||
|
{:input1 [3] :output1 [13] :index 3 :distances [0 0 0 0 0]}
|
||||||
|
{:input1 [4] :output1 [14] :index 4 :distances [0 0 0 0 0]})
|
||||||
|
{:case-delta 0})]
|
||||||
|
(prn {:selected selected})
|
||||||
|
(t/is (= 1 (count selected))))))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest hyperselection-test
|
||||||
|
(let [parents1 '({:blah 3 :index 1} {:blah 3 :index 1}
|
||||||
|
{:blah 3 :index 1} {:blah 3 :index 2})
|
||||||
|
parents2 '({:plushy 2 :index 0} {:blah 3 :index 2}
|
||||||
|
{:blah 3 :index 3} {:index 4})
|
||||||
|
emptyparents '({:blah 1} {:blah 1} {:blah 1})]
|
||||||
|
(t/testing "sum-list-map-indices function works correctly"
|
||||||
|
(t/is (= {1 3, 2 1} (hs/sum-list-map-indices parents1)))
|
||||||
|
(t/is (= {0 1, 2 1, 3 1, 4 1} (hs/sum-list-map-indices parents2))))
|
||||||
|
(t/testing "ordered-freqs function works correctly"
|
||||||
|
(t/is (= '(3 1) (hs/ordered-freqs (hs/sum-list-map-indices parents1))))
|
||||||
|
(t/is (= '(1 1 1 1) (hs/ordered-freqs (hs/sum-list-map-indices parents2)))))
|
||||||
|
(t/testing "hyperselection-track works correctly"
|
||||||
|
(t/is (= '(0.75 0.25) (hs/hyperselection-track parents1)))
|
||||||
|
(t/is (= '(0.25 0.25 0.25 0.25) (hs/hyperselection-track parents2))))
|
||||||
|
(t/testing "reindex-pop works correctly"
|
||||||
|
(t/is (= '({:blah 3 :index 0} {:blah 3 :index 1}
|
||||||
|
{:blah 3 :index 2} {:blah 3 :index 3}) (hs/reindex-pop parents1)))
|
||||||
|
(t/is (= '({:plushy 2 :index 0} {:blah 3 :index 1}
|
||||||
|
{:blah 3 :index 2} {:index 3}) (hs/reindex-pop parents2)))
|
||||||
|
(t/is (= '({:blah 1 :index 0} {:blah 1 :index 1} {:blah 1 :index 2}) (hs/reindex-pop emptyparents))))))
|
@ -83,135 +83,3 @@
|
|||||||
(t/testing "should decrease size of plushy that always has perfect scores"
|
(t/testing "should decrease size of plushy that always has perfect scores"
|
||||||
(t/is (< (count (s/auto-simplify-plushy plushy (fn [argmap data plushy] 0) {:simplification-steps 100 :simplification-k 4 :simplification-verbose? false})) (count plushy)))
|
(t/is (< (count (s/auto-simplify-plushy plushy (fn [argmap data plushy] 0) {:simplification-steps 100 :simplification-k 4 :simplification-verbose? false})) (count plushy)))
|
||||||
(t/is (< (count (s/auto-simplify-plushy plushy (fn [argmap data plushy] 0) {:simplification-steps 100 :simplification-k 10 :simplification-verbose? false})) (count plushy)))))))
|
(t/is (< (count (s/auto-simplify-plushy plushy (fn [argmap data plushy] 0) {:simplification-steps 100 :simplification-k 10 :simplification-verbose? false})) (count plushy)))))))
|
||||||
|
|
||||||
(t/deftest assign-indices-to-data-test
|
|
||||||
(t/testing "assign-indices-to-data"
|
|
||||||
(t/testing "should return a map of the same length"
|
|
||||||
(t/is (= (count (ds/assign-indices-to-data (range 10))) 10))
|
|
||||||
(t/is (= (count (ds/assign-indices-to-data (range 0))) 0)))
|
|
||||||
(t/testing "should return a map where each element has an index key"
|
|
||||||
(t/is (every? #(:index %) (ds/assign-indices-to-data (map #(assoc {} :input %) (range 10))))))
|
|
||||||
(t/testing "should return distinct indices"
|
|
||||||
(t/is (= (map #(:index %) (ds/assign-indices-to-data (range 10))) (range 10))))))
|
|
||||||
|
|
||||||
(t/deftest select-downsample-random-test
|
|
||||||
(t/testing "select-downsample-random"
|
|
||||||
(t/testing "should select the correct amount of elements"
|
|
||||||
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 0.1})) 1))
|
|
||||||
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 0.2})) 2))
|
|
||||||
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 0.5})) 5)))
|
|
||||||
(t/testing "should not return duplicate items (when called with set of numbers)"
|
|
||||||
(t/is (= (count (set (ds/select-downsample-random (range 10) {:downsample-rate 0.1}))) 1))
|
|
||||||
(t/is (= (count (set (ds/select-downsample-random (range 10) {:downsample-rate 0.2}))) 2))
|
|
||||||
(t/is (= (count (set (ds/select-downsample-random (range 10) {:downsample-rate 0.5}))) 5)))
|
|
||||||
(t/testing "should round down the number of elements selected if not whole"
|
|
||||||
(t/is (= (count (ds/select-downsample-random (range 3) {:downsample-rate 0.5})) 1))
|
|
||||||
(t/is (= (count (ds/select-downsample-random (range 1) {:downsample-rate 0.5})) 0)))
|
|
||||||
(t/testing "should not return more elements than available"
|
|
||||||
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 2})) 10))
|
|
||||||
(t/is (= (count (ds/select-downsample-random (range 10) {:downsample-rate 1.5})) 10)))))
|
|
||||||
|
|
||||||
(t/deftest get-distance-between-cases-test
|
|
||||||
(t/testing "get-distance-between-cases"
|
|
||||||
(t/testing "should return correct distance"
|
|
||||||
(t/is (= 3 (ds/get-distance-between-cases '((0 1 1) (0 1 1) (1 0 1)) 0 1))))
|
|
||||||
(t/testing "should return 0 for the distance of a case to itself"
|
|
||||||
(t/is (= 0 (ds/get-distance-between-cases '((0 1 1) (0 1 1) (1 0 1)) 0 0))))
|
|
||||||
(t/testing "should work for non binary values (0 is solved)"
|
|
||||||
(t/is (= 1 (ds/get-distance-between-cases '((0 2 2) (0 2 2) (1 0 50)) 1 2))))
|
|
||||||
(t/testing "should return the max distance if one of the cases does not exist"
|
|
||||||
(t/is (= 3 (ds/get-distance-between-cases '((0 1 1) (0 1 1) (1 0 1)) 0 4))))))
|
|
||||||
|
|
||||||
(t/deftest merge-map-lists-at-index-test
|
|
||||||
(t/testing "merge-map-lists-at-index"
|
|
||||||
(t/testing "works properly"
|
|
||||||
(t/is (= '({:index 0 :a 3 :b 2} {:index 1 :a 2 :b 3}) (ds/merge-map-lists-at-index '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) '({:index 1 :a 2 :b 3})))))
|
|
||||||
(t/testing "doesn't change big list if no indices match"
|
|
||||||
(t/is (= '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) (ds/merge-map-lists-at-index '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) '({:index 3 :a 2 :b 3})))))
|
|
||||||
(t/testing "doesn't fail on empty list"
|
|
||||||
(t/is (= '() (ds/merge-map-lists-at-index '() '()))))
|
|
||||||
(t/testing "shouldn't fail merging non-empty with empty"
|
|
||||||
(t/is (= '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) (ds/merge-map-lists-at-index '({:index 0 :a 3 :b 2} {:index 1 :a 1 :b 2}) '()))))))
|
|
||||||
|
|
||||||
(t/deftest update-at-indices-test
|
|
||||||
(t/testing "update-at-indices"
|
|
||||||
(t/testing "should update at correct indices"
|
|
||||||
(t/is (= (ds/update-at-indices [1 2 3 4] [5] [0]) [5 2 3 4]))
|
|
||||||
(t/is (= (ds/update-at-indices [1 2 3 4] [5] [0]) [5 2 3 4])))
|
|
||||||
(t/testing "should update nothing if index list is empty"
|
|
||||||
(t/is (= (ds/update-at-indices [6 5 4 0 0] [] []) [6 5 4 0 0])))
|
|
||||||
(t/testing "should update nothing if index list is out of bounds"
|
|
||||||
(t/is (= (ds/update-at-indices [6 5 4 0 0] [4 5 1] [-1 5 6]) [6 5 4 0 0])))
|
|
||||||
(t/testing "should update only when indices are available (length mismatch)"
|
|
||||||
(t/is (= (ds/update-at-indices [6 5 4 0 0] [1 2 3 4] [0 1]) [1 2 4 0 0])))
|
|
||||||
(t/testing "should not care about index order"
|
|
||||||
(t/is (= (ds/update-at-indices [6 5 4 0 0] [2 1] [1 0]) [1 2 4 0 0])))
|
|
||||||
(t/testing "should work when input is a list"
|
|
||||||
(t/is (= (ds/update-at-indices '(6 5 4 0 0) '(2 1) '(1 0)) [1 2 4 0 0])))))
|
|
||||||
|
|
||||||
(t/deftest update-case-distances-test
|
|
||||||
(t/testing "update-case-distances"
|
|
||||||
(t/testing "should ..."
|
|
||||||
(t/is (= (ds/update-case-distances '({:errors (0 0)} {:errors (0 0)})
|
|
||||||
'({:index 3 :distances [2 2 2 2 2]} {:index 4 :distances [2 2 2 2 2]})
|
|
||||||
'({:index 0 :distances [2 2 2 2 2]} {:index 1 :distances [2 2 2 2 2]} {:index 2 :distances [2 2 2 2 2]} {:index 3 :distances [2 2 2 2 2]} {:index 4 :distances [2 2 2 2 2]}))
|
|
||||||
'({:index 0 :distances [2 2 2 2 2]} {:index 1 :distances [2 2 2 2 2]} {:index 2 :distances [2 2 2 2 2]}
|
|
||||||
{:index 3 :distances [2 2 2 0 0]} {:index 4 :distances [2 2 2 0 0]}))))))
|
|
||||||
|
|
||||||
(t/deftest case-maxmin-test
|
|
||||||
(t/testing "case-maxmin selects correct downsample"
|
|
||||||
(let [selected (ds/select-downsample-maxmin
|
|
||||||
'({:input1 [0] :output1 [10] :index 0 :distances [0 5 0 0 0]}
|
|
||||||
{:input1 [1] :output1 [11] :index 1 :distances [5 0 5 5 5]}
|
|
||||||
{:input1 [2] :output1 [12] :index 2 :distances [0 5 0 0 0]}
|
|
||||||
{:input1 [3] :output1 [13] :index 3 :distances [0 5 0 0 0]}
|
|
||||||
{:input1 [4] :output1 [14] :index 4 :distances [0 5 0 0 0]})
|
|
||||||
{:downsample-rate 0.4})]
|
|
||||||
(prn {:selected selected})
|
|
||||||
(t/is (or (= (:index (first selected)) 1) (= (:index (second selected)) 1))))))
|
|
||||||
|
|
||||||
(t/deftest case-maxmin-adaptive
|
|
||||||
(t/testing "case-maxmin-adaptive selects correct downsample simple"
|
|
||||||
(let [selected (ds/select-downsample-maxmin-adaptive
|
|
||||||
'({:input1 [0] :output1 [10] :index 0 :distances [0 5 0 0 0]}
|
|
||||||
{:input1 [1] :output1 [11] :index 1 :distances [5 0 5 5 5]}
|
|
||||||
{:input1 [2] :output1 [12] :index 2 :distances [0 5 0 0 0]}
|
|
||||||
{:input1 [3] :output1 [13] :index 3 :distances [0 5 0 0 0]}
|
|
||||||
{:input1 [4] :output1 [14] :index 4 :distances [0 5 0 0 0]})
|
|
||||||
{:case-delta 0})]
|
|
||||||
(prn {:selected selected})
|
|
||||||
(t/is (or (= (:index (first selected)) 1) (= (:index (second selected)) 1)))
|
|
||||||
(t/is (= 2 (count selected)))))
|
|
||||||
(t/testing "case-maxmin-adaptive selects correct downsample when all identical"
|
|
||||||
(let [selected (ds/select-downsample-maxmin-adaptive
|
|
||||||
'({:input1 [0] :output1 [10] :index 0 :distances [0 0 0 0 0]}
|
|
||||||
{:input1 [1] :output1 [11] :index 1 :distances [0 0 0 0 0]}
|
|
||||||
{:input1 [2] :output1 [12] :index 2 :distances [0 0 0 0 0]}
|
|
||||||
{:input1 [3] :output1 [13] :index 3 :distances [0 0 0 0 0]}
|
|
||||||
{:input1 [4] :output1 [14] :index 4 :distances [0 0 0 0 0]})
|
|
||||||
{:case-delta 0})]
|
|
||||||
(prn {:selected selected})
|
|
||||||
(t/is (= 1 (count selected))))))
|
|
||||||
|
|
||||||
|
|
||||||
(t/deftest hyperselection-test
|
|
||||||
(let [parents1 '({:blah 3 :index 1} {:blah 3 :index 1}
|
|
||||||
{:blah 3 :index 1} {:blah 3 :index 2})
|
|
||||||
parents2 '({:plushy 2 :index 0} {:blah 3 :index 2}
|
|
||||||
{:blah 3 :index 3} {:index 4})
|
|
||||||
emptyparents '({:blah 1} {:blah 1} {:blah 1})]
|
|
||||||
(t/testing "sum-list-map-indices function works correctly"
|
|
||||||
(t/is (= {1 3, 2 1} (hs/sum-list-map-indices parents1)))
|
|
||||||
(t/is (= {0 1, 2 1, 3 1, 4 1} (hs/sum-list-map-indices parents2))))
|
|
||||||
(t/testing "ordered-freqs function works correctly"
|
|
||||||
(t/is (= '(3 1) (hs/ordered-freqs (hs/sum-list-map-indices parents1))))
|
|
||||||
(t/is (= '(1 1 1 1) (hs/ordered-freqs (hs/sum-list-map-indices parents2)))))
|
|
||||||
(t/testing "hyperselection-track works correctly"
|
|
||||||
(t/is (= '(0.75 0.25) (hs/hyperselection-track parents1)))
|
|
||||||
(t/is (= '(0.25 0.25 0.25 0.25) (hs/hyperselection-track parents2))))
|
|
||||||
(t/testing "reindex-pop works correctly"
|
|
||||||
(t/is (= '({:blah 3 :index 0} {:blah 3 :index 1}
|
|
||||||
{:blah 3 :index 2} {:blah 3 :index 3}) (hs/reindex-pop parents1)))
|
|
||||||
(t/is (= '({:plushy 2 :index 0} {:blah 3 :index 1}
|
|
||||||
{:blah 3 :index 2} {:index 3}) (hs/reindex-pop parents2)))
|
|
||||||
(t/is (= '({:blah 1 :index 0} {:blah 1 :index 1} {:blah 1 :index 2}) (hs/reindex-pop emptyparents))))))
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user