001  (ns nature.population-operators
002    "Functions that span or operate against entire populations"
003    (:require [nature.population-presets :as pp]
004              [bigml.sampling.simple :as bss]))
005  
006  (defn keep-elite
007    "Find the top `number-to-keep` individuals in `population`, and increment their ages by 1"
008    [population number-to-keep]
009    (map #(update % :age inc) (take number-to-keep (sort-by :fitness-score #(> %1 %2) population))))
010  
011  (defn weighted-selection-of-population
012    "Pick `total-retreived` individuals from `population` with a relative probability of
013    the individual's fitness score divided by the population's aggregate fitness score"
014    ([population total-retrieved]
015     (take total-retrieved (bss/sample population :weigh #(:fitness-score %) :replace true)))
016    ([population total-retrieved replace?]
017     (take total-retrieved (bss/sample population :weigh #(:fitness-score %) :replace replace?))))
018  
019  (defn advance-generation
020    "Apply the functions in `binary-operator-set` until a sufficiently large population is built.
021     Then apply functions in `unary-operator-set` to the result.
022     Optionally, include a map of `settings` to guide overall behavior.
023     If the `:carry-over` setting is added, the elite member `n` of the prior generation will be advanced to the next generation."
024    ([population population-size binary-operator-set unary-operator-set]
025     (let [binary-pop (repeatedly population-size #(apply (rand-nth binary-operator-set) [(weighted-selection-of-population population 2)]))]
026       (map #(apply (rand-nth unary-operator-set) [%]) binary-pop)))
027    ([population population-size binary-operator-set unary-operator-set settings]
028    ;; Currently, :carry-over is the only optional behavior
029     (if (> (:carry-over settings) 0)
030       (concat (advance-generation population (- population-size (:carry-over settings)) binary-operator-set unary-operator-set) (keep-elite population (:carry-over settings)))
031       (advance-generation population population-size binary-operator-set unary-operator-set))))