Program: 42216
Project: 42216
Buggy source:
/** 
 * Checks whether laut and raut are equivalent using HopcroftKarp on the SFA accepting the reverse language
 */
public static <P,S,E extends BooleanExpression>Pair<Boolean,List<S>> areReverseEquivalent(SAFA<P,S,E> aut1,SAFA<P,S,E> aut2,BooleanAlgebra<P,S> ba){
  UnionFindHopKarp<S> ds=new UnionFindHopKarp<>();
  HashMap<HashSet<Integer>,Integer> reached1=new HashMap<HashSet<Integer>,Integer>();
  HashMap<HashSet<Integer>,Integer> reached2=new HashMap<HashSet<Integer>,Integer>();
  LinkedList<Pair<HashSet<Integer>,HashSet<Integer>>> toVisit=new LinkedList<>();
  HashSet<Integer> in1=new HashSet<Integer>(aut1.finalStates);
  HashSet<Integer> in2=new HashSet<Integer>(aut2.finalStates);
  reached1.put(in1,0);
  reached2.put(in2,1);
  toVisit.add(new Pair<HashSet<Integer>,HashSet<Integer>>(in1,in2));
  ds.add(0,in1.contains(aut1.initialState),new LinkedList<>());
  ds.add(1,in2.contains(aut2.initialState),new LinkedList<>());
  ds.mergeSets(0,1);
  while (!toVisit.isEmpty()) {
    Pair<HashSet<Integer>,HashSet<Integer>> curr=toVisit.removeFirst();
    HashSet<Integer> curr1=curr.first;
    HashSet<Integer> curr2=curr.second;
    ArrayList<SAFAInputMove<P,S,E>> movesToCurr1=new ArrayList<>();
    ArrayList<P> predicatesToCurr1=new ArrayList<>();
    ArrayList<SAFAInputMove<P,S,E>> movesToCurr2=new ArrayList<>();
    ArrayList<P> predicatesToCurr2=new ArrayList<>();
    for (    SAFAInputMove<P,S,E> t : aut1.getInputMoves())     if (t.to.hasModel(curr1)) {
      movesToCurr1.add(t);
      predicatesToCurr1.add(t.guard);
    }
    for (    SAFAInputMove<P,S,E> t : aut2.getInputMoves())     if (t.to.hasModel(curr2)) {
      movesToCurr2.add(t);
      predicatesToCurr2.add(t.guard);
    }
    Collection<Pair<P,ArrayList<Integer>>> minterms1=ba.GetMinterms(predicatesToCurr1);
    Collection<Pair<P,ArrayList<Integer>>> minterms2=ba.GetMinterms(predicatesToCurr2);
    for (    Pair<P,ArrayList<Integer>> minterm1 : minterms1) {
      for (      Pair<P,ArrayList<Integer>> minterm2 : minterms2) {
        P conj=ba.MkAnd(minterm1.first,minterm2.first);
        if (ba.IsSatisfiable(conj)) {
          HashSet<Integer> from1=new HashSet<>();
          HashSet<Integer> from2=new HashSet<>();
          for (int i=0; i < minterm1.second.size(); i++)           if (minterm1.second.get(i) == 1)           from1.add(movesToCurr1.get(i).from);
          for (int i=0; i < minterm2.second.size(); i++)           if (minterm2.second.get(i) == 1)           from2.add(movesToCurr2.get(i).from);
          List<S> pref=new LinkedList<S>(ds.getWitness(reached1.get(curr1)));
          pref.add(ba.generateWitness(conj));
          Integer r1=null, r2=null;
          if (!reached1.containsKey(from1)) {
            r1=ds.getNumberOfElements();
            reached1.put(from1,r1);
            ds.add(r1,from1.contains(aut1.initialState),pref);
          }
          if (r1 == null)           r1=reached1.get(from1);
          if (!reached2.containsKey(from2)) {
            r2=ds.getNumberOfElements();
            reached2.put(from2,r2);
            ds.add(r2,from2.contains(aut2.initialState),pref);
          }
          if (r2 == null)           r2=reached2.get(from2);
          if (!ds.areInSameSet(r1,r2)) {
            if (!ds.mergeSets(r1,r2))             return new Pair<Boolean,List<S>>(false,Lists.reverse(pref));
            toVisit.add(new Pair<HashSet<Integer>,HashSet<Integer>>(from1,from2));
          }
        }
      }
    }
  }
  return new Pair<Boolean,List<S>>(true,null);
}

Fixed version (ground truth):
/** 
 * Checks whether laut and raut are equivalent using HopcroftKarp on the SFA accepting the reverse language
 */
public static <P,S,E extends BooleanExpression>Pair<Boolean,List<S>> areReverseEquivalent(SAFA<P,S,E> aut1,SAFA<P,S,E> aut2,BooleanAlgebra<P,S> ba){
  UnionFindHopKarp<S> ds=new UnionFindHopKarp<>();
  HashMap<HashSet<Integer>,Integer> reached1=new HashMap<HashSet<Integer>,Integer>();
  HashMap<HashSet<Integer>,Integer> reached2=new HashMap<HashSet<Integer>,Integer>();
  LinkedList<Pair<HashSet<Integer>,HashSet<Integer>>> toVisit=new LinkedList<>();
  HashSet<Integer> in1=new HashSet<Integer>(aut1.finalStates);
  HashSet<Integer> in2=new HashSet<Integer>(aut2.finalStates);
  reached1.put(in1,0);
  reached2.put(in2,1);
  toVisit.add(new Pair<HashSet<Integer>,HashSet<Integer>>(in1,in2));
  ds.add(0,in1.contains(aut1.initialState),new LinkedList<>());
  ds.add(1,in2.contains(aut2.initialState),new LinkedList<>());
  ds.mergeSets(0,1);
  while (!toVisit.isEmpty()) {
    Pair<HashSet<Integer>,HashSet<Integer>> curr=toVisit.removeFirst();
    HashSet<Integer> curr1=curr.first;
    HashSet<Integer> curr2=curr.second;
    ArrayList<SAFAInputMove<P,S,E>> movesToCurr1=new ArrayList<>();
    ArrayList<P> predicatesToCurr1=new ArrayList<>();
    ArrayList<SAFAInputMove<P,S,E>> movesToCurr2=new ArrayList<>();
    ArrayList<P> predicatesToCurr2=new ArrayList<>();
    for (    SAFAInputMove<P,S,E> t : aut1.getInputMoves())     if (t.to.hasModel(curr1)) {
      movesToCurr1.add(t);
      predicatesToCurr1.add(t.guard);
    }
    for (    SAFAInputMove<P,S,E> t : aut2.getInputMoves())     if (t.to.hasModel(curr2)) {
      movesToCurr2.add(t);
      predicatesToCurr2.add(t.guard);
    }
    Collection<Pair<P,ArrayList<Integer>>> minterms1=ba.GetMinterms(predicatesToCurr1);
    Collection<Pair<P,ArrayList<Integer>>> minterms2=ba.GetMinterms(predicatesToCurr2);
    for (    Pair<P,ArrayList<Integer>> minterm1 : minterms1) {
      for (      Pair<P,ArrayList<Integer>> minterm2 : minterms2) {
        P conj=ba.MkAnd(minterm1.first,minterm2.first);
        if (ba.IsSatisfiable(conj)) {
          HashSet<Integer> from1=new HashSet<>();
          HashSet<Integer> from2=new HashSet<>();
          for (int i=0; i < minterm1.second.size(); i++)           if (minterm1.second.get(i) == 1)           from1.add(movesToCurr1.get(i).from);
          for (int i=0; i < minterm2.second.size(); i++)           if (minterm2.second.get(i) == 1)           from2.add(movesToCurr2.get(i).from);
          List<S> pref=new LinkedList<S>(ds.getWitness(reached1.get(curr1)));
          pref.add(ba.generateWitness(conj));
          Integer r1=null, r2=null;
          if (!reached1.containsKey(from1)) {
            r1=ds.getNumberOfElements();
            reached1.put(from1,r1);
            ds.add(r1,aut1.initialState.hasModel(from1),pref);
          }
          if (r1 == null)           r1=reached1.get(from1);
          if (!reached2.containsKey(from2)) {
            r2=ds.getNumberOfElements();
            reached2.put(from2,r2);
            ds.add(r2,aut2.initialState.hasModel(from2),pref);
          }
          if (r2 == null)           r2=reached2.get(from2);
          if (!ds.areInSameSet(r1,r2)) {
            if (!ds.mergeSets(r1,r2))             return new Pair<Boolean,List<S>>(false,Lists.reverse(pref));
            toVisit.add(new Pair<HashSet<Integer>,HashSet<Integer>>(from1,from2));
          }
        }
      }
    }
  }
  return new Pair<Boolean,List<S>>(true,null);
}