private Map<Triple<DendrogramNode, RowKey, RowKey>, Number> visit(
     final DendrogramNode root,
     final Map<Triple<DendrogramNode, RowKey, RowKey>, Number> m,
     final Map<RowKey, DistanceVectorDataValue> d,
     final int allLeaves,
     final ExecutionContext exec)
     throws CanceledExecutionException {
   if (root.isLeaf()) {
     final RowKey key = RowKeyHelper.getKey(root);
     return Collections.singletonMap(Triple.apply(root, key, key), (Number) Double.valueOf(0));
   }
   final DendrogramNode w = root.getFirstSubnode();
   final Map<Triple<DendrogramNode, RowKey, RowKey>, Number> leftM =
       visit(w, m, d, allLeaves, exec);
   final DendrogramNode x = root.getSecondSubnode();
   final Map<Triple<DendrogramNode, RowKey, RowKey>, Number> rightM =
       visit(x, m, d, allLeaves, exec);
   final Map<Triple<DendrogramNode, RowKey, RowKey>, Number> ret =
       new HashMap<Triple<DendrogramNode, RowKey, RowKey>, Number>(leftM);
   ret.putAll(rightM);
   final Set<RowKey> leftKeys = computeLeaves(w);
   final Set<RowKey> rightKeys = computeLeaves(x);
   computeM(root, d, w, x, rightM, ret, leftKeys, rightKeys);
   exec.checkCanceled();
   computeM(root, d, x, w, leftM, ret, rightKeys, leftKeys);
   exec.setProgress(((double) leftKeys.size() + rightKeys.size()) / allLeaves);
   return ret;
 }
 private void computeLeaves(final DendrogramNode root, final Set<RowKey> ret) {
   if (root.isLeaf()) {
     ret.add(RowKeyHelper.getKey(root));
   } else {
     computeLeaves(root.getFirstSubnode(), ret);
     computeLeaves(root.getSecondSubnode(), ret);
   }
 }
 /**
  * Make a tree (with root: {@code root}) to {@link DistanceVectorDataValue} s.
  *
  * @param root A {@link DendrogramNode} tree's root element.
  * @param ret The result list.
  * @param d The distance matrix.
  */
 public static void flatten(
     final DendrogramNode root,
     final List<DistanceVectorDataValue> ret,
     final Map<RowKey, DistanceVectorDataValue> d) {
   if (root.isLeaf()) {
     ret.add(d.get(RowKeyHelper.getKey(root)));
     return;
   }
   flatten(root.getFirstSubnode(), ret, d);
   flatten(root.getSecondSubnode(), ret, d);
 }
 private static Triple<ClusterViewNode, RowKey, RowKey> buildNewTree(
     final Map<DendrogramNode, Map<Pair<RowKey, RowKey>, Number>> m,
     final DendrogramNode root,
     final Map<RowKey, Pair<DataRow, Integer>> rows,
     ExecutionContext exec)
     throws CanceledExecutionException {
   if (root.isLeaf()) {
     final Pair<DataRow, Integer> leafRow = rows.get(RowKeyHelper.getKey(root));
     return Triple.apply(
         new ClusterViewNode(leafRow.getFirst().getKey()),
         leafRow.getFirst().getKey(),
         leafRow.getFirst().getKey());
   }
   final Triple<ClusterViewNode, RowKey, RowKey> firstTree =
       buildNewTree(m, root.getFirstSubnode(), rows, exec);
   exec.checkCanceled();
   final Triple<ClusterViewNode, RowKey, RowKey> secondTree =
       buildNewTree(m, root.getSecondSubnode(), rows, exec);
   final Map<Pair<RowKey, RowKey>, Number> map = m.get(root);
   Pair<RowKey, RowKey> pairNoChange = Pair.create(firstTree.getO3(), secondTree.getO2());
   if (!map.containsKey(pairNoChange)) {
     pairNoChange = flip(pairNoChange);
   }
   Pair<RowKey, RowKey> pairChange = Pair.create(secondTree.getO3(), firstTree.getO2());
   if (!map.containsKey(pairChange)) {
     pairChange = flip(pairChange);
   }
   assert map.containsKey(pairNoChange);
   assert map.containsKey(pairChange);
   final double noChangeValue = map.get(pairNoChange).doubleValue();
   final double changeValue = map.get(pairChange).doubleValue();
   if (noChangeValue > changeValue) {
     return Triple.apply(
         new ClusterViewNode(firstTree.getO1(), secondTree.getO1(), root.getDist()),
         firstTree.getO2(),
         secondTree.getO3());
   }
   return Triple.apply(
       new ClusterViewNode(secondTree.getO1(), firstTree.getO1(), root.getDist()),
       secondTree.getO2(),
       firstTree.getO3());
 }