Program: 42200
Project: 42200
Buggy source:
/** 
 * Checks whether laut and raut are equivalent using bisimulation up to congruence.
 */
public static <P,S,E extends BooleanExpression>boolean isEquivalent(SAFA<P,S> laut,SAFA<P,S> 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();
    P guard=ba.True();
    do {
      S model=ba.generateWitness(guard);
      P implicant=ba.True();
      Map<Integer,E> leftMove=new HashMap<>();
      Map<Integer,E> rightMove=new HashMap<>();
      for (      Integer s : left.getStates()) {
        E succ=boolexpr.False();
        for (        SAFAInputMove<P,S> tr : laut.getInputMovesFrom(s)) {
          if (ba.HasModel(tr.guard,model)) {
            succ=boolexpr.MkOr(succ,coerce.apply(tr.to));
            implicant=ba.MkAnd(implicant,tr.guard);
          }
        }
        leftMove.put(s,succ);
      }
      for (      Integer s : right.getStates()) {
        E succ=boolexpr.False();
        for (        SAFAInputMove<P,S> tr : raut.getInputMovesFrom(s)) {
          if (ba.HasModel(tr.guard,model)) {
            succ=boolexpr.MkOr(succ,coerce.apply(tr.to));
            implicant=ba.MkAnd(implicant,tr.guard);
          }
        }
        rightMove.put(s,succ);
      }
      E leftSucc=boolexpr.substitute((lit) -> leftMove.get(lit)).apply(left);
      E rightSucc=boolexpr.substitute((lit) -> rightMove.get(lit)).apply(right);
      if (leftSucc.hasModel(laut.finalStates) != rightSucc.hasModel(raut.finalStates)) {
        return false;
      }
 else       if (!similar.isMember(leftSucc,rightSucc)) {
        similar.add(leftSucc,rightSucc);
        worklist.addFirst(new Pair<>(leftSucc,rightSucc));
      }
      guard=ba.MkAnd(guard,ba.MkNot(implicant));
    }
 while (ba.IsSatisfiable(guard));
  }
  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>Pair<Boolean,List<S>> isEquivalent(SAFA<P,S> laut,SAFA<P,S> raut,BooleanAlgebra<P,S> ba,BooleanExpressionFactory<E> boolexpr) throws TimeoutException {
  SAFARelation similar=new SATRelation();
  LinkedList<Pair<Pair<E,E>,List<S>>> 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<>(new Pair<>(leftInitial,rightInitial),new LinkedList<>()));
  while (!worklist.isEmpty()) {
    Pair<Pair<E,E>,List<S>> next=worklist.removeFirst();
    E left=next.getFirst().getFirst();
    E right=next.getFirst().getSecond();
    List<S> witness=next.getSecond();
    P guard=ba.True();
    do {
      S model=ba.generateWitness(guard);
      P implicant=ba.True();
      Map<Integer,E> leftMove=new HashMap<>();
      Map<Integer,E> rightMove=new HashMap<>();
      for (      Integer s : left.getStates()) {
        E succ=boolexpr.False();
        for (        SAFAInputMove<P,S> tr : laut.getInputMovesFrom(s)) {
          if (ba.HasModel(tr.guard,model)) {
            succ=boolexpr.MkOr(succ,coerce.apply(tr.to));
            implicant=ba.MkAnd(implicant,tr.guard);
          }
 else {
            implicant=ba.MkAnd(implicant,ba.MkNot(tr.guard));
          }
        }
        leftMove.put(s,succ);
      }
      for (      Integer s : right.getStates()) {
        E succ=boolexpr.False();
        for (        SAFAInputMove<P,S> tr : raut.getInputMovesFrom(s)) {
          if (ba.HasModel(tr.guard,model)) {
            succ=boolexpr.MkOr(succ,coerce.apply(tr.to));
            implicant=ba.MkAnd(implicant,tr.guard);
          }
 else {
            implicant=ba.MkAnd(implicant,ba.MkNot(tr.guard));
          }
        }
        rightMove.put(s,succ);
      }
      E leftSucc=boolexpr.substitute((lit) -> leftMove.get(lit)).apply(left);
      E rightSucc=boolexpr.substitute((lit) -> rightMove.get(lit)).apply(right);
      List<S> succWitness=new LinkedList<>();
      succWitness.addAll(witness);
      succWitness.add(model);
      if (leftSucc.hasModel(laut.finalStates) != rightSucc.hasModel(raut.finalStates)) {
        return new Pair<>(false,succWitness);
      }
 else       if (!similar.isMember(leftSucc,rightSucc)) {
        if (!similar.add(leftSucc,rightSucc)) {
          return new Pair<>(false,succWitness);
        }
        worklist.addFirst(new Pair<>(new Pair<>(leftSucc,rightSucc),succWitness));
      }
      guard=ba.MkAnd(guard,ba.MkNot(implicant));
    }
 while (ba.IsSatisfiable(guard));
  }
  return new Pair<>(true,null);
}