private Set<Key<?>> getKeysToRemove(DependencyGraph graph, Collection<Key<?>> discovered) {
    Set<Key<?>> toRemove = new LinkedHashSet<Key<?>>();
    while (!discovered.isEmpty()) {
      toRemove.addAll(discovered);
      discovered = getRequiredSourcesTargeting(graph, discovered);
      discovered.removeAll(toRemove);
    }
    return toRemove;
  }
private Set < Key < ? > > getKeysToRemove ( DependencyGraph graph , Collection < Key < ? > > discovered ) { Set < Key < ? > > toRemove = new LinkedHashSet < Key < ? > > ( ) ; while ( ! discovered . isEmpty ( ) ) { toRemove . addAll ( discovered ) ; discovered = getRequiredSourcesTargeting ( graph , discovered ) ; discovered . removeAll ( toRemove ) ; } return toRemove ; }
Given the set of optional keys that had problems, compute the set of all optional keys that
should be removed.  This may include additional keys, for instance if an optional key requires
an invalid key, than the optional key should also be removed.

<p>This will only add optional keys to {@code toRemove}.  Recall that a key is required iff
there exists a path to it that passes through only required edges.  If key Y is optional, and
there is a required edge from X -> Y, then X must also be optional.  If X were required, by
our definition Y would also be required.