Program: 4808
Project: 4808
Buggy source:
/** 
 * Split this dag into multiple dags. Each subdag will contain at most a single reduce node.
 * @return list of subdags.
 */
public List<Dag> split(){
  List<Dag> dags=new ArrayList<>();
  Set<String> remainingNodes=new HashSet<>();
  remainingNodes.addAll(nodes);
  Set<String> possibleNewSources=Sets.union(sources,connectors.keySet());
  Set<String> possibleNewSinks=Sets.union(sinks,connectors.keySet());
  for (  String reduceNode : reduceNodes) {
    Dag subdag=subsetAround(reduceNode,possibleNewSources,possibleNewSinks);
    remainingNodes.removeAll(subdag.getNodes());
    dags.add(subdag);
  }
  Set<String> remainingSources=Sets.intersection(remainingNodes,possibleNewSources);
  Set<String> processedNodes=new HashSet<>();
  if (!remainingSources.isEmpty()) {
    Map<String,Set<String>> nodesAccessibleBySources=new HashMap<>();
    for (    String remainingSource : remainingSources) {
      Dag remainingNodesDag=subsetFrom(remainingSource,possibleNewSinks);
      nodesAccessibleBySources.put(remainingSource,remainingNodesDag.getNodes());
    }
    for (    String remainingSource : remainingSources) {
      if (processedNodes.contains(remainingSource)) {
        continue;
      }
      Set<String> remainingAccessibleNodes=nodesAccessibleBySources.get(remainingSource);
      Set<String> islandNodes=new HashSet<>();
      islandNodes.addAll(remainingAccessibleNodes);
      for (      String otherSource : remainingSources) {
        if (remainingSource.equals(otherSource)) {
          continue;
        }
        Set<String> otherAccessibleNodes=nodesAccessibleBySources.get(otherSource);
        if (!Sets.intersection(remainingAccessibleNodes,otherAccessibleNodes).isEmpty()) {
          islandNodes.addAll(otherAccessibleNodes);
        }
      }
      dags.add(createSubDag(islandNodes));
      processedNodes.addAll(islandNodes);
    }
  }
  return dags;
}

Fixed version (ground truth):
/** 
 * Split this dag into multiple dags. Each subdag will contain at most a single reduce node.
 * @return list of subdags.
 */
public List<Dag> split(){
  List<Dag> dags=new ArrayList<>();
  Set<String> remainingNodes=new HashSet<>(nodes);
  Set<String> possibleNewSources=Sets.union(sources,connectors.keySet());
  Set<String> possibleNewSinks=Sets.union(sinks,connectors.keySet());
  for (  String reduceNode : reduceNodes) {
    Dag subdag=subsetAround(reduceNode,possibleNewSources,possibleNewSinks);
    remainingNodes.removeAll(subdag.getNodes());
    dags.add(subdag);
  }
  Set<String> remainingSources=new TreeSet<>(Sets.intersection(remainingNodes,possibleNewSources));
  Set<String> processedNodes=new HashSet<>();
  Map<String,Set<String>> nodesAccessibleBySources=new HashMap<>();
  for (  String remainingSource : remainingSources) {
    Dag remainingNodesDag=subsetFrom(remainingSource,possibleNewSinks);
    nodesAccessibleBySources.put(remainingSource,remainingNodesDag.getNodes());
  }
  for (  String remainingSource : remainingSources) {
    if (!processedNodes.add(remainingSource)) {
      continue;
    }
    Set<String> subdag=new HashSet<>(nodesAccessibleBySources.get(remainingSource));
    Set<String> otherSources=Sets.difference(remainingSources,processedNodes);
    boolean nodesAdded;
    do {
      nodesAdded=false;
      for (      String otherSource : otherSources) {
        Set<String> otherAccessibleNodes=nodesAccessibleBySources.get(otherSource);
        if (!Sets.intersection(subdag,otherAccessibleNodes).isEmpty()) {
          if (subdag.addAll(otherAccessibleNodes)) {
            nodesAdded=true;
          }
        }
      }
    }
 while (nodesAdded);
    dags.add(createSubDag(subdag));
    processedNodes.addAll(subdag);
  }
  return dags;
}