001  (ns nature.monitors
002    "Helper functions to inspect generations and return run-time information, statistics, etc.")
003  
004  (defn apply-monitors
005    "Apply each function in `monitors` against `population` and `current-generation`"
006    [monitors population current-generation]
007    (let [fns (apply juxt monitors)]
008      (do (fns population current-generation))))
009  
010  (defn mk-monitor
011    "Apply `monitor-fn` to the `population` and `current-generation`, and print the result.
012     If a `format-fn` has been supplied, modify the output before printing.
013     This is useful for separating the monitor code into a separate testable function."
014    ([monitor-fn population current-generation]
015     (println (monitor-fn population current-generation)))
016  
017    ([monitor-fn population current-generation format-fn]
018     (println (format-fn (monitor-fn population current-generation)))))
019  
020  (defn print-best-solution*
021    "Finds the individual with the highest fitness in `population`"
022    [population current-generation]
023    (first (sort-by :fitness-score #(> %1 %2) population)))
024  
025  (defn print-best-solution
026    "Finds the individual with the highest fitness in `population`, and prints it to std-out"
027    [population current-generation]
028    (mk-monitor print-best-solution* population current-generation))
029  
030  (defn print-worst-solution*
031    "Finds the individual with the lowest fitness in `population`"
032    [population current-generation]
033    (first (sort-by :fitness-score #(> %2 %1) population)))
034  
035  (defn print-worst-solution
036    "Finds the individual with the lowest fitness in `population`, and prints it to std-out"
037    [population current-generation]
038    (mk-monitor print-worst-solution* population current-generation))
039  
040  (defn print-solution-frequencies*
041    "Finds how frequently each genetic sequence is repeated across the `population`"
042    [population current-generation]
043    (frequencies (map :genetic-sequence population)))
044  
045  (defn print-solution-frequencies
046    "Finds how frequently each genetic sequence is repeated across the `population`, and prints it to std-out"
047    [population current-generation]
048    (mk-monitor print-solution-frequencies* population current-generation))
049  
050  (defn print-fitness-score-frequencies*
051    "Finds how frequently each fitness score is repeated across the `population`"
052    [population current-generation]
053    (frequencies (map :fitness-score population)))
054  
055  (defn print-fitness-score-frequencies
056    "Finds how frequently each fitness score is repeated across the `population`, and prints it to std-out"
057    [population current-generation]
058    (mk-monitor print-fitness-score-frequencies* population current-generation))