docs: static List<Fragment> greedyTraversal(Arborescence<Node> arborescence,
                                                    Map<NodeId, Node> nodes,
                                                    Map<Node, Map<Node, Fragment>> edgeFragmentChildToParent) {
  
          List<Fragment> plan = new LinkedList<>();
  
          Map<Node, Set<Node>> edgesParentToChild = new HashMap<>();
          arborescence.getParents().forEach((child, parent) -> {
              if (!edgesParentToChild.containsKey(parent)) {
                  edgesParentToChild.put(parent, new HashSet<>());
              }
              edgesParentToChild.get(parent).add(child);
          });
  
          Node root = arborescence.getRoot();
  
          Set<Node> reachableNodes = Sets.newHashSet(root);
          // expanding from the root until all nodes have been visited
          while (!reachableNodes.isEmpty()) {
  
              Node nodeWithMinCost = reachableNodes.stream().min(Comparator.comparingDouble(node ->
                      branchWeight(node, arborescence, edgesParentToChild, edgeFragmentChildToParent))).orElse(null);
  
              assert nodeWithMinCost != null : "reachableNodes is never empty, so there is always a minimum";
  
              // add edge fragment first, then node fragment
              Fragment fragment = getEdgeFragment(nodeWithMinCost, arborescence, edgeFragmentChildToParent);
              if (fragment != null) plan.add(fragment);
  
              plan.addAll(nodeToPlanFragments(nodeWithMinCost, nodes, true));
  
              reachableNodes.remove(nodeWithMinCost);
              if (edgesParentToChild.containsKey(nodeWithMinCost)) {
                  reachableNodes.addAll(edgesParentToChild.get(nodeWithMinCost));
              }
          }
  
          return plan;
      }