Program: 42220
Project: 42220
Buggy source:
/** 
 * checks whether aut1 is equivalent to aut2 using Hopcroft Karp's algorithm
 */
public static <A,B>boolean areHopcroftKarpEquivalent(SFA<A,B> aut1,SFA<A,B> aut2,BooleanAlgebra<A,B> ba){
  DisjointSet ds=new DisjointSet(aut1.stateCount() + aut2.stateCount());
  int offset=aut1.stateCount();
  ds.mergeSets(aut1.initialState,aut2.initialState + offset);
  LinkedList<Pair<Integer,Integer>> toVisit=new LinkedList<>();
  toVisit.add(new Pair<Integer,Integer>(aut1.initialState,aut2.initialState));
  while (!toVisit.isEmpty()) {
    Pair<Integer,Integer> curr=toVisit.removeFirst();
    for (    SFAInputMove<A,B> move1 : aut1.getInputMovesFrom(curr.first))     for (    SFAInputMove<A,B> move2 : aut2.getInputMovesFrom(curr.second))     if (ba.IsSatisfiable(ba.MkAnd(move1.guard,move2.guard))) {
      int r1=move1.to, r2=move2.to + offset;
      boolean isFinal1=aut1.isFinalState(move1.to);
      boolean isFinal2=aut2.isFinalState(move2.to);
      if (isFinal1 && !isFinal2)       return false;
      if (isFinal2 && !isFinal1)       return false;
      if (!ds.areInSameSet(r1,r2)) {
        ds.mergeSets(r1,r2);
        toVisit.add(new Pair<Integer,Integer>(r1,r2));
      }
    }
  }
  HashSet<Integer> finals=new HashSet<>();
  HashSet<Integer> nonFinals=new HashSet<>();
  for (  int st1 : aut1.states) {
    int rep=ds.getRepr(st1);
    if (aut1.finalStates.contains(st1)) {
      if (nonFinals.contains(rep))       return false;
      finals.add(rep);
    }
 else {
      if (finals.contains(rep))       return false;
      nonFinals.add(rep);
    }
  }
  for (  int st2 : aut2.states) {
    int rep=ds.getRepr(st2 + offset);
    if (aut2.finalStates.contains(st2)) {
      if (nonFinals.contains(rep))       return false;
      finals.add(rep);
    }
 else {
      if (finals.contains(rep))       return false;
      nonFinals.add(rep);
    }
  }
  return true;
}

Fixed version (ground truth):
/** 
 * checks whether aut1 is equivalent to aut2 using Hopcroft Karp's algorithm
 */
public static <A,B>boolean areHopcroftKarpEquivalent(SFA<A,B> aut1,SFA<A,B> aut2,BooleanAlgebra<A,B> ba){
  DisjointSet ds=new DisjointSet();
  int offset=aut1.stateCount();
  ds.add(aut1.initialState);
  ds.add(aut1.initialState + offset);
  ds.mergeSets(aut1.initialState,aut2.initialState + offset);
  LinkedList<Pair<Integer,Integer>> toVisit=new LinkedList<>();
  toVisit.add(new Pair<Integer,Integer>(aut1.initialState,aut2.initialState));
  while (!toVisit.isEmpty()) {
    Pair<Integer,Integer> curr=toVisit.removeFirst();
    for (    SFAInputMove<A,B> move1 : aut1.getInputMovesFrom(curr.first))     for (    SFAInputMove<A,B> move2 : aut2.getInputMovesFrom(curr.second))     if (ba.IsSatisfiable(ba.MkAnd(move1.guard,move2.guard))) {
      int r1=move1.to;
      int r2=move2.to + offset;
      boolean isFinal1=aut1.isFinalState(move1.to);
      boolean isFinal2=aut2.isFinalState(move2.to);
      if (isFinal1 && !isFinal2)       return false;
      if (isFinal2 && !isFinal1)       return false;
      if (!ds.contains(r1))       ds.add(r1);
      if (!ds.contains(r2))       ds.add(r2);
      if (!ds.areInSameSet(r1,r2)) {
        ds.mergeSets(r1,r2);
        toVisit.add(new Pair<Integer,Integer>(move1.to,move2.to));
      }
    }
  }
  HashSet<Integer> finals=new HashSet<>();
  HashSet<Integer> nonFinals=new HashSet<>();
  for (  int st1 : aut1.states) {
    int rep=ds.getRepr(st1);
    if (aut1.finalStates.contains(st1)) {
      if (nonFinals.contains(rep))       return false;
      finals.add(rep);
    }
 else {
      if (finals.contains(rep))       return false;
      nonFinals.add(rep);
    }
  }
  for (  int st2 : aut2.states) {
    int rep=ds.getRepr(st2 + offset);
    if (aut2.finalStates.contains(st2)) {
      if (nonFinals.contains(rep))       return false;
      finals.add(rep);
    }
 else {
      if (finals.contains(rep))       return false;
      nonFinals.add(rep);
    }
  }
  return true;
}