 (defn mk-graph
   "[[x y]] -> Graph
   assumes points are connected"
-  [points]
-  (Graph. 1.0 1.1 1.2 ;; "standard" t-range, i-range, s-range
+  [t-range i-range s-range points]
+  (Graph. t-range i-range s-range
           (vec (map (fn [[x y]] (Graph$P. x y)) points))))
 
 ;; for repeatable results, specify seed for test vector

         ;  x - 1 - 2 - 5 - 6
         ;
         ;  optimal: 0 1 2 3 5
         [[0 0] [0 1] [0 2] [1 2] [2 2] [0 3] [0 4]])]
      (for [n (range 20 200 20)]
        ;; shuffle,
        (mk-graph (shuffle-with test-rng (take n (rand-walk))))))))

(defn error-function
  "evalulate program inside greedy algorithm, compared to lower bound (bfs-depth).
  For most graphs, bfs-depth is too low, so programs can't be perfect (0 vector).
  But otherwise, it's a decent function with forgiving slope."
  [program]
  (let [selector (push-based-selector program)]
    (vec (for [graph test-graphs]
           (double (/ (HCABS/run graph selector)
                      (.depth graph)))))))

(comment (defn -main [& args]
           (println
             "test run:"
             (HCABS/run (test-graphs 0) Selector/NUM_UNINFORMED))))

(defn -main [& args]
  (if (not-empty args)
    (doseq [n (range 0 (count test-graphs))]
      (let [ps (.ps (test-graphs n))
            x (map #(.x %) ps)
            y (map #(.y %) ps)]
        (spit (str "test-data-" n ".svg")
              (chart/emit-svg
                (-> (chart/xy-plot :width 500 :height 500
                                   :xmin 0 :xmax 25
                                   :ymin 0 :ymax 25
                                   :r 1)
                    (chart/add-points [x y] :transpose-data?? true
                                      :fill "rgba(0,0,0,0.1)"
                                      :size (/ 500 25))
                    (chart/add-points [x y] :transpose-data?? true
                                      :fill "rgba(0,255,0,1)"
                                      :size 1))))))
    (do
      (pushgp
        {:error-function error-function
         :error-threshold (* (count test-graphs) 1.50)
         :atom-generators '(
                            exec_y
                            exec_pop
                            exec_eq
                            exec_stackdepth
                            exec_rot
                            exec_when
                            exec_do*times
                            exec_do*count
                            exec_s
                            exec_do*range
                            exec_if
                            exec_k
                            exec_yank
                            exec_yankdup
                            exec_swap
                            exec_dup
                            exec_shove

                            boolean_pop
                            boolean_dup
                            boolean_swap
                            boolean_rot
                            boolean_flush
                            boolean_eq
                            boolean_stackdepth
                            boolean_yank
                            boolean_yankdup
                            boolean_shove
                            boolean_and
                            boolean_or
                            boolean_not
                            boolean_xor
                            boolean_invert_first_then_and
                            boolean_invert_second_then_and
                            boolean_frominteger

                            integer_flush
                            integer_stackdepth
                            integer_yank
                            integer_yankdup
                            integer_shove
                            integer_add
                            integer_div
                            integer_dup
                            integer_eq
                            integer_gt
                            integer_lt
                            integer_mod
                            integer_mult
                            integer_pop
                            integer_rot
                            integer_sub
                            integer_swap
                            integer_fromboolean
                            integer_min
                            integer_max

                            node_pop
                            node_dup
                            node_swap
                            node_rot
                            node_flush
                            node_eq
                            node_stackdepth
                            node_yank
                            node_yankdup
                            node_shove
                            return_fromnode

                            bitset_pop
                            bitset_dup
                            bitset_swap
                            bitset_rot
                            bitset_flush
                            bitset_eq
                            bitset_stackdepth
                            bitset_yank
                            bitset_yankdup
                            bitset_shove

                            reduce-max
                            reduce-min

                            get-time
                            get-depth
                            nodes-of
                            neighbors-of
                            interferers-of
                            sensors-of
                            bfs-children

                            set-cardinality
                            is-empty
                            get-informed
                            get-active
                            get-able

                            set-and
                            set-or
                            set-xor
                            set-intersects
                            set-get
                            set-flip
                            set-set
                            set-clear
                            in-set

                            bfs-depth
                            bfs-decendents
                            bfs-child-count
                            bfs-parent
                            )
      ; :use-single-thread true
      :population-size 200
      :max-generations 1000
      :max-points 500
      :max-points-in-initial-program 200
      :evalpush-limit 500

    (java.util.Collections/shuffle al rng)
    (clojure.lang.RT/vector (.toArray al))))

(defn uniform-graph
  "different strategy of generating connected graphs,
  where points are put into boxes in order, making sure
  they always have a neighbor"
  [n]
  (let [peturb (repeatedly n (fn [] [(* 0.5 (.nextDouble test-rng))
                                     (* 0.5 (.nextDouble test-rng))]))
        grid (for [i (range 0 25 0.5)
                   j (range 0 25 0.5)]
               [i j])

        ;; peturb each grid point.
        nodes (map (fn [[x y] [dx dy]] [(+ x dx) (+ y dy)])
                   peturb
                   (cycle grid))]
    (mk-graph 1.0 1.1 1.2 nodes)))

(def test-graphs
  (vec
    (concat
