 
 
 
-(comment ; TODO: refine-input must go somewhere
-  (refine-input      [s maybe-refined-input-set])  
-  (refine-input-   [s refined-input-set] "must be a strict subset of input-set."))
+
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Subproblem Impl  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defn make-simple-subproblem [name inp-set out-set summary-fn inner-children copy-children child-transform]
+(defn make-simple-subproblem [name inp-set out-set summary-fn refine-input-fn]
   (let [ts-atom (atom nil)
         ret (traits/reify-traits [cache-trait summaries/simple-node]
              summaries/Summarizable (summarize [s] (summary-fn s))
              Subproblem             (subproblem-name [s] name)
                                     (input-set       [s] inp-set)
                                     (output-set       [s] out-set)
-                                    (tree-summarizer [s] @ts-atom))
+                                    (tree-summarizer [s] @ts-atom)
+                                    (refine-input    [s new-inp-set]
+                                     (if (= inp-set new-inp-set) s (refine-input-fn s new-inp-set))))        
         ts  (make-tree-summarizer ret)]
     (summaries/add-parent! ret ts false)
     (reset! ts-atom ts)
-
-    (doseq [child inner-children]
-      (summaries/connect! ret child false))
-
-    (doseq [child copy-children]
-      (add-watcher! child (fn [_ out-sp] (connect-child-sp! ts (child-transform out-sp)))))
-
     ret))
 
-
-
-(comment
-     (refine-input    [s maybe-refined-input-set]
-      (if (= input-set maybe-refined-input-set)
-        s
-        (let [refined (refine-input- s maybe-refined-input-set)]
-          (assert refined)
-          (summaries/connect! (tree-summarizer s) (tree-summarizer refined) true)
-          refined))))
+(defn setup-ordinary-subproblem! [sp inner-children copy-children child-transform]
+  (doseq [child inner-children]
+    (summaries/connect! sp child false))
+  (doseq [child copy-children]
+    (add-watcher! child (fn [_ out-sp] (connect-child-sp! (tree-summarizer sp) (child-transform out-sp))))))
+
+(defn setup-subsumed-subproblem! [sp subsuming-sp]
+  (summaries/connect! (tree-summarizer sp) (tree-summarizer subsuming-sp) true)
+  (add-watcher! subsuming-sp
+     (fn [_ sub-out]
+       (let [sub-stub (refine-input sub-out (input-set sp))]
+         (summaries/connect! sp sub-stub)
+         (add-watcher! sub-stub
+           (fn [_ out-sp] (connect-child-sp! (tree-summarizer sp) out-sp)))))))
+
+
 
 
 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;      Atomic       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(declare make-fs-seq-stub)

(comment
 (defn- refined-children [sub-sp inp-set]
   (when-let [sub-children (and sub-sp
                                (not (= :blocked (summary/status (summaries/summary sub-sp))))
                                (concat (summaries/node-ordinary-children sub-sp)
                                        (summaries/node-ordinary-children (tree-summarizer sub-sp))))]
     (map #(refine-input- % inp-set) sub-children))))


(defn- make-atomic-subproblem [stub inp-set function-set out-set reward status]
  (let [children (when (= status :live)
                   (or #_ (refined-children subsuming-as inp-set) ;; TODO!!
                       (map #(make-fs-seq-stub inp-set %)
                            (fs/child-seqs function-set inp-set))))]
    (make-simple-subproblem
     [::Atomic (fs/fs-name function-set) inp-set]
     inp-set out-set
     (if (= status :live)
       (fn [s]
         (assert (empty? (summaries/node-subsuming-children s)))
         (assert (= (count children) (count (summaries/node-ordinary-children s))))
         (summary/or-combine (map summaries/summary children) s reward))
       (fn [s] (summary/make-simple-summary reward status s)))     
     children children identity #_ #(util/prog1 % (println "AS")))))


(comment  (refine-input- [s refined-input-set]
                   (make-simple-atomic-subproblem s refined-input-set function-set)))

;; Note: this is double-stage to lazily generate children.  Could be simpler single-stage.
(defn- make-atomic-stub [subsuming-as inp-set function-set]
;  (println "Making atomic stub" inp-set (fs/fs-name function-set))
  (let [state (atom :ready)] ;; set to [out-set reward] after first eval, then :go after second.
    (traits/reify-traits [simple-watched cache-trait (summaries/fixed-node nil)]



(defn- make-fs-seq-stub [inp-set [first-fs & rest-fs]]
  (let [first-stub (make-atomic-stub nil false inp-set first-fs)]
    (if (empty? rest-fs)
      first-stub
      (make-left-stub first-stub #(make-fs-seq-stub % rest-fs)))))
