     (map->ClassGraph {:classes topo-classes
                       :succs succs :preds preds
                       :sources sources :sinks sinks
-                      :block-succs (:succs block-graph)
-                      :block-preds (:preds block-graph)})))
-
-
-(def FlatGraph->ClassGraph
-  (comp BlockGraph->ClassGraph
-        FlatGraph->BlockGraph))
+                      :block-succs (:succs block-info)
+                      :block-preds (:preds block-info)})))
 
 
 (defn FlatGraph->FlatGraphs

        (recur sources' succs' (conj sorted node))))))


(defn FlatGraph->BlockGraph
  "Organizes all of the Nodes and Segments in a FlatGraph into horizontally-
  aligned blocks. These blocks are then organized into a graph of their own,
  where the nodes are blocks and the edges are determined by adjacency between
  their constituent Nodes and Segments in each FlatLayer."
  [flat-graph]
  (let [[roots blocks] (blockify flat-graph)
        edge->set #(update-in %1 [(:src %2)] (fnil conj #{}) %2)
        [succs preds]
        (reduce (fn [[succs preds] block-item]
                  (let [block (second block-item) ; we want the value
                        b-succs (->> (map #(get-in flat-graph [:aboves %])
                                          block)
                                     (remove nil?)
                                     (group-by #(get roots %))
                                     (map (fn [[above-root above-nodes]]
                                            (BlockEdge.
                                             (get blocks above-root)
                                             block
                                             (apply max (map :weight
                                                             above-nodes))))))
                        b-preds (map rev b-succs)]
                    [(reduce edge->set succs b-succs)
                     (reduce edge->set preds b-preds)]))
                [{} {}]
                blocks)
        simple-succs (->> (map (fn [[src edges]]
                                 [src (set (map :dest edges))])
                               succs)
                          (into {}))
        block-set (set (vals blocks))
        long-block (first (filter #(> (count %) 1) block-set))
        layer-id-compare (if (< (-> long-block first :layer-id)
                                (-> long-block second :layer-id))
                           < >)
        sources (->> (set/difference block-set (keys preds))
                     (sort-by #(:layer-id (get % 0))
                              layer-id-compare))
        topo-blocks (topo-sort sources simple-succs)]
    (map->BlockGraph {:blocks topo-blocks :succs succs :preds preds
                      :simple-succs simple-succs :sources sources})))


(defn classify-source



(defn classify
  "Given block-info, organizes the blocks into classes that are defined as
  all blocks that are reachable from a block that is a source in its
  graph, with preference given to the left-most sources"
  [block-info]
  (reduce (fn [classes root-block]
            (let [proto-class (classify-source root-block
                                               (:simple-succs block-info))
                  class-set (apply set/difference proto-class (vals classes))
                  class (filterv #(contains? class-set %)
                                 (:blocks block-info))]
              (reduce #(assoc %1 %2 class) classes class)))
          {}
          (:sources block-info)))


(defn FlatGraph->ClassGraph
  "Given block-info, organizes the blocks into classes and then constructs a
  ClassGraph, where the nodes are classes and the edges are BlockEdges that
  span classes. This means there can be multiple edges per class pair."
  [flat-graph]
  (let [block-info (FlatGraph->block-info flat-graph)
        block-classes (classify block-info)
        classes (set (vals block-classes))
        edge->set #(update-in %1 [(get block-classes (:src %2))]
                              (fnil conj #{}) %2)
