Collection<NodeCandidate> assignTo(Collection<NodeCandidate> candidates) {
        int[] countInGroup = countInEachGroup(candidates);
        candidates = byUnretiringPriority(candidates).stream().map(node -> unretireNodeInExpandedGroup(node, countInGroup)).toList();
        candidates = candidates.stream().map(node -> assignGroupToNewNode(node, countInGroup)).toList();
        candidates = byUnretiringPriority(candidates).stream().map(node -> moveNodeInSurplusGroup(node, countInGroup)).toList();
        candidates = byRetiringPriority(candidates).stream().map(node -> retireSurplusNodeInGroup(node, countInGroup)).toList();
        candidates = candidates.stream().filter(node -> ! shouldRemove(node)).toList();
        return candidates;
    }
Knows how to assign a group index to a number of nodes (some of which have an index already),
such that the nodes are placed in the desired groups with minimal group movement.

@author bratseth
node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupAssigner.java