 
 (declare refinement-names)
 
-;; TODO: subsuming sp can become blocked before its children come to fruition...
-;; TODO: fix in dash_astar too.
-;; Easiest solution: pair not blocked until it has output.
 (defn- make-atomic-subproblem [fs inp-set]
-  (let [nm         (atomic-name fs)
-        summary-fn (atom #(make-summary nil :live %))
-        set-sf!    (fn [s f] (reset! summary-fn f) (schedule-decrease! s))] 
-    (make-subproblem
-     nm inp-set nil
-     (fn evaluate! [s]
-       (util/print-debug 1 "eval" nm (if (get-output-set s) :out :no-out))
-       (if-not (get-output-set s) ; Not evaluated yet -- evalute description and publish output
-         (let [[out-set reward status] (fs/apply-opt fs inp-set)]
-	   (when-not out-set (util/assert-is (= reward Double/NEGATIVE_INFINITY)
-					     "Bad outcome: %s" [(fs/fs-name fs) reward status]))
-           (set-sf! s #(make-summary reward status %))
-           (when out-set (set-output-set! s out-set)))
-         (do (set-sf! s sg/or-summary) ; Evaluated to live -- generate children now.
-             (if-let [subsuming-sps (seq (filter #(not (terminal? %)) (subsuming-sps s)))]
-               (connect-and-watch! s (apply min-key (comp sg/get-bound sp-ts) subsuming-sps) nil
-                 (fn [sub-out] (add-sp-child! s (refine-input sub-out inp-set) true))) 
-               (doseq [ref-name (refinement-names fs inp-set)] ;		 (println fs ref-name)
-                 (add-sp-child! s (get-subproblem ref-name inp-set) false))))))     
-     (fn [s ri]  (assert (not *collect-equal-outputs*))  
-       (if (= ri inp-set) s (get-subproblem nm  ri)))
-     (fn summarize [s] (@summary-fn s)))))
+  (let [[out-set reward status] (fs/apply-opt fs inp-set)]
+    (when out-set
+     (let [nm         (atomic-name fs)
+	   summary-fn (atom #(make-summary reward status %))
+	   set-sf!    (fn [s f] (reset! summary-fn f) (schedule-decrease! s))] 
+       (make-subproblem
+	nm inp-set out-set nil
+	(fn expand! [s]
+	  (util/print-debug 1 "expand" nm)
+	  (set-sf! s sg/or-summary) 
+	  (if-let [subsuming-sps (seq (remove terminal? (subsuming-sps s)))]
+	    (connect-and-watch! s (apply min-key (comp sg/get-bound sp-ts) subsuming-sps)
+	      (fn [sub-child] (publish-child! s (refine-input sub-child inp-set)))) 
+	    (doseq [ref-name (refinement-names fs inp-set)] 
+	      (publish-child! s (get-subproblem ref-name inp-set)))))     
+	(fn [s ri]  (assert (not *collect-equal-outputs*))  
+	  (if (= ri inp-set) s (get-subproblem nm  ri)))
+	(fn summarize [s] (@summary-fn s)))))))
 
 (defmethod get-subproblem :Atomic [[_ fs :as n] inp-set] 
   (make-atomic-subproblem fs inp-set))          
 
 
-
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;      Pair      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Pair subproblems represent sequntial composition of two subproblems.
 

;; Note: subsumed subproblems can have different irrelevant vars
;; Also note: new input can have subset of variables of old. (=-state-sets does ntthis now).
(defn- make-state-abstracted-subproblem [fs inner-sp inp-set]
  (make-wrapped-subproblem
   (sa-name (sp-name inner-sp)) inp-set #{:OC} inner-sp
   (fn [o] (fs/transfer-effects inp-set o))
   (fn [sp child-sp] (add-sp-child! sp (make-state-abstracted-subproblem fs child-sp inp-set) :irrelevant)) 
   (fn [sp ni] #_ (def *bad* sp) (if (fs/=-state-sets ni inp-set) sp (make-state-abstracted-subproblem fs (refine-input inner-sp ni) ni)))))

(defmethod get-subproblem :SA [[_ inner-n :as n] inp-set]
  (let [fs (atomic-name-fs (second inner-n))] 

(defprotocol Subproblem
  (sp-name             [s] "A name to identify this subproblem type (indep. of input)")
  (input-set           [s] "Input set for this subproblem.")
  (output-set          [s] "Output set for this subproblem.")  
  (sp-ts               [s] "Summarizer that includes outputs/children.")
  (expand!             [s] "Start expanding or throw exception if not expandable.")

  (publish-child!      [s o] "Add a new subproblem child")
  (list-children       [s] "List current children, primarily for debugging.")
  (subscribe-children! [s w] "Register a callback to be called on all published children")

  (subsuming-sps       [s]      "Known subproblems with same name, >= inp-set") 
  (add-subsuming-sp!   [s subsuming-sp] "Add subsuming sp") 

  (refine-input        [s refined-input-set] "Sp with same name, subset of input-set."))

(defmethod print-method angelic.search.implicit.dash_astar_opt_simple.Subproblem [sp o]
  (print-method (format "#<SP$%8h %s>" (System/identityHashCode sp) (sp-name sp)) o))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Auxillary fns  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  
(defn- terminal? [sp]
  (and (empty? (list-children sp))
       (not (summary/live? (sg/summary sp)))))

(defn- solved-terminal? [sp]
  (and (empty? (list-children sp))
       (summary/solved? (sg/summary sp))))

;; Canonical SPs are Atomic and Pair; wrappers use TS of inner SP.
