Program: 42213
Project: 42213
Buggy source:
/** 
 * Checks whether laut and raut are equivalent using bisimulation up to congruence.
 */
public static <P,S,E extends BooleanExpression,F extends BooleanExpression>boolean isEquivalent(SAFA<P,S,F> laut,SAFA<P,S,F> raut,BooleanAlgebra<P,S> ba,BooleanExpressionFactory<E> boolexpr) throws TimeoutException {
  SAFARelation similar=new SATRelation();
  LinkedList<Pair<E,E>> worklist=new LinkedList<>();
  E leftInitial=(E)laut.initialState;
  E rightInitial=(E)raut.initialState;
  similar.add(leftInitial,rightInitial);
  worklist.add(new Pair<>(leftInitial,rightInitial));
  while (!worklist.isEmpty()) {
    Pair<E,E> next=worklist.removeFirst();
    E left=next.getFirst();
    E right=next.getSecond();
    LinkedList<Pair<P,Map<Integer,E>>> leftMoves=laut.getTransitionTablesFrom(left.getStates(),ba,ba.True(),boolexpr);
    for (    Pair<P,Map<Integer,E>> leftMove : leftMoves) {
      E leftSucc=boolexpr.substitute((lit) -> leftMove.getSecond().get(lit)).apply(left);
      boolean leftSuccAccept=leftSucc.hasModel(laut.finalStates);
      LinkedList<Pair<P,Map<Integer,E>>> rightMoves=raut.getTransitionTablesFrom(right.getStates(),ba,leftMove.getFirst(),boolexpr);
      for (      Pair<P,Map<Integer,E>> rightMove : rightMoves) {
        E rightSucc=boolexpr.substitute((lit) -> rightMove.getSecond().get(lit)).apply(right);
        if (leftSuccAccept != rightSucc.hasModel(raut.finalStates)) {
          return false;
        }
 else         if (!similar.isMember(leftSucc,rightSucc)) {
          similar.add(leftSucc,rightSucc);
          worklist.addFirst(new Pair<>(leftSucc,rightSucc));
        }
      }
    }
  }
  return true;
}

Fixed version (ground truth):
/** 
 * Checks whether laut and raut are equivalent using bisimulation up to congruence.
 */
public static <P,S,E extends BooleanExpression,F extends BooleanExpression>boolean isEquivalent(SAFA<P,S,F> laut,SAFA<P,S,F> raut,BooleanAlgebra<P,S> ba,BooleanExpressionFactory<E> boolexpr) throws TimeoutException {
  SAFARelation similar=new SATRelation();
  LinkedList<Pair<E,E>> worklist=new LinkedList<>();
  BooleanExpressionMorphism<E> coerce=new BooleanExpressionMorphism<>((x) -> boolexpr.MkState(x),boolexpr);
  E leftInitial=coerce.apply(laut.initialState);
  E rightInitial=coerce.apply(raut.initialState);
  similar.add(leftInitial,rightInitial);
  worklist.add(new Pair<>(leftInitial,rightInitial));
  while (!worklist.isEmpty()) {
    Pair<E,E> next=worklist.removeFirst();
    E left=next.getFirst();
    E right=next.getSecond();
    LinkedList<Pair<P,Map<Integer,E>>> leftMoves=laut.getTransitionTablesFrom(left.getStates(),ba,ba.True(),boolexpr);
    for (    Pair<P,Map<Integer,E>> leftMove : leftMoves) {
      E leftSucc=boolexpr.substitute((lit) -> leftMove.getSecond().get(lit)).apply(left);
      boolean leftSuccAccept=leftSucc.hasModel(laut.finalStates);
      LinkedList<Pair<P,Map<Integer,E>>> rightMoves=raut.getTransitionTablesFrom(right.getStates(),ba,leftMove.getFirst(),boolexpr);
      for (      Pair<P,Map<Integer,E>> rightMove : rightMoves) {
        E rightSucc=boolexpr.substitute((lit) -> rightMove.getSecond().get(lit)).apply(right);
        if (leftSuccAccept != rightSucc.hasModel(raut.finalStates)) {
          return false;
        }
 else         if (!similar.isMember(leftSucc,rightSucc)) {
          similar.add(leftSucc,rightSucc);
          worklist.addFirst(new Pair<>(leftSucc,rightSucc));
        }
      }
    }
  }
  return true;
}