(use '[clojure.contrib.test-is])

(require 'src.utils) (alias 'ut 'src.utils)
(require 'src.graph) (alias 'gr 'src.graph)
(require 'src.optim) (alias 'ot 'src.optim)

(def fa-table '[[[0 0 0] [0 0]]
                [[1 0 0] [1 0]]
                [[0 1 0] [1 0]]
                [[1 1 0] [0 1]]
                [[0 0 1] [1 0]]
                [[1 0 1] [0 1]]
                [[0 1 1] [0 1]]
                [[1 1 1] [1 1]]])

(def gr-fa
  (let [gr            (gr/new-graph)
        [gr i0 i1 i2] (gr/inputs gr 0 1 2)
        [gr o0 o1]    (gr/truth-table gr fa-table [i0 i1 i2])
        gr            (gr/outputs gr [o0 0] [o1 1])]
    (gr/remove-unrefered-conns gr)))

(def graphs
  (interleave
    (map #(gr/remove-unrefered-conns
            (gr/random-graph (ut/lfsr32 %) 2 1 4))
         (map first
              (partition 99 (ut/lfsr32 1))
              ))
    (map #(gr/remove-unrefered-conns
            (gr/random-graph (ut/lfsr32 %) 3 2 6))
         (map first
              (partition 99 (ut/lfsr32 100))
              ))
    (map #(gr/remove-unrefered-conns
            (gr/random-graph (ut/lfsr32 %) 4 2 8))
         (map first
              (partition 99 (ut/lfsr32 100))
              ))))

(deftest test-eq-gr-pairs
  (let [pairs (take 10 (ot/eq-gr-pairs graphs {}))]
    (map #(is (= (count %) 2))
         pairs)
    (map #(is (= (gr/calc-all %1) (gr/calc-all %2)))
         pairs)))

(run-tests)

(def ptns
     (map (fn [[bfr aft]]
            (gr/gr-to-replace-ptn bfr aft))
          (ot/eq-gr-pairs graphs {})))

(println (first (ot/eq-gr-pairs graphs {})))
(println (first ptns))

(println
  (gr/match1 (ut/lfsr32 1) gr-fa
             (:nodes (:bfr (first ptns)))
             (:edges (:bfr (first ptns)))))

(def replaceds
  (take 1000
    (map (fn [ptns rss]
           (reduce (fn [gr [ptn rs]]
                     (gr/replace rs gr ptn))
                   gr-fa
                   (map vector ptns rss)
                   ))
         (partition 4 ptns)
         (partition 4
           (map #(ut/lfsr32 %) (ut/lfsr32 1))
           ))))

;(println replaceds)

(def size (map #(count (:nodes %)) replaceds))
(println (remove #(= % (count (:nodes gr-fa)))
                 size))
(println (apply min size))
