Program: 42146
Project: 42146
Buggy source:
/** 
 * return an equivalent copy without epsilon moves
 */
protected static <P,F,S>SFT<P,F,S> removeEpsilonMovesFrom(SFT<P,F,S> sft,BooleanAlgebraSubst<P,F,S> ba){
  if (sft.isEpsilonFree)   return sft;
  Collection<SFTMove<P,F,S>> transitions=new ArrayList<SFTMove<P,F,S>>();
  Map<Integer,Set<List<S>>> finalStatesAndTails=new HashMap<Integer,Set<List<S>>>();
  for (  Integer state : sft.getStates())   transitions.addAll(sft.getInputMovesFrom(state));
  for (  Integer state : sft.getStates()) {
    Map<Integer,List<SFTEpsilon<P,F,S>>> epsilonClosureAndPath=sft.getSFTEpsClosureAndPath(state);
    if (!sft.isFinalState(state))     for (    Integer nextState : epsilonClosureAndPath.keySet()) {
      if (sft.isFinalState(nextState)) {
        List<S> outputAlongPath=new ArrayList<S>();
        for (        SFTEpsilon<P,F,S> transition : epsilonClosureAndPath.get(nextState)) {
          for (          S output : transition.outputs)           outputAlongPath.add(output);
        }
        Set<List<S>> newTails=new HashSet<List<S>>();
        if (sft.getFinalStatesAndTails().get(nextState).size() == 0) {
          newTails.add(outputAlongPath);
        }
 else {
          for (          List<S> tail : sft.getFinalStatesAndTails().get(nextState)) {
            List<S> newTail=new ArrayList<S>(outputAlongPath);
            newTail.addAll(tail);
          }
        }
        if (finalStatesAndTails.containsKey(state))         newTails.addAll(finalStatesAndTails.get(state));
        finalStatesAndTails.put(state,newTails);
      }
    }
    for (    Integer nextState : epsilonClosureAndPath.keySet())     if (!nextState.equals(state)) {
      List<F> outputFuncAlongPath=new ArrayList<F>();
      for (      SFTEpsilon<P,F,S> transition : epsilonClosureAndPath.get(nextState)) {
        for (        S output : transition.outputs)         outputFuncAlongPath.add(ba.MkFuncConst(output));
      }
      for (      SFTInputMove<P,F,S> nextInputMove : sft.getInputMovesFrom(nextState)) {
        List<F> combinedOutputFunctions=new ArrayList<F>(outputFuncAlongPath);
        combinedOutputFunctions.addAll(nextInputMove.outputFunctions);
        transitions.add(new SFTInputMove<P,F,S>(state,nextInputMove.to,nextInputMove.guard,combinedOutputFunctions));
      }
    }
  }
  return MkSFT(transitions,sft.initialState,finalStatesAndTails,ba);
}

Fixed version (ground truth):
/** 
 * return an equivalent copy without epsilon moves
 */
protected static <P,F,S>SFT<P,F,S> removeEpsilonMovesFrom(SFT<P,F,S> sft,BooleanAlgebraSubst<P,F,S> ba) throws TimeoutException {
  if (sft.isEpsilonFree)   return sft;
  Collection<SFTMove<P,F,S>> transitions=new ArrayList<SFTMove<P,F,S>>();
  Map<Integer,Set<List<S>>> finalStatesAndTails=new HashMap<Integer,Set<List<S>>>();
  for (  Integer state : sft.getStates())   transitions.addAll(sft.getInputMovesFrom(state));
  for (  Integer state : sft.getStates()) {
    Map<Integer,List<SFTEpsilon<P,F,S>>> epsilonClosureAndPath=sft.getSFTEpsClosureAndPath(state);
    if (!sft.isFinalState(state))     for (    Integer nextState : epsilonClosureAndPath.keySet()) {
      if (sft.isFinalState(nextState)) {
        List<S> outputAlongPath=new ArrayList<S>();
        for (        SFTEpsilon<P,F,S> transition : epsilonClosureAndPath.get(nextState)) {
          for (          S output : transition.outputs)           outputAlongPath.add(output);
        }
        Set<List<S>> newTails=new HashSet<List<S>>();
        if (sft.getFinalStatesAndTails().get(nextState).size() == 0) {
          newTails.add(outputAlongPath);
        }
 else {
          for (          List<S> tail : sft.getFinalStatesAndTails().get(nextState)) {
            List<S> newTail=new ArrayList<S>(outputAlongPath);
            newTail.addAll(tail);
          }
        }
        if (finalStatesAndTails.containsKey(state))         newTails.addAll(finalStatesAndTails.get(state));
        finalStatesAndTails.put(state,newTails);
      }
    }
    for (    Integer nextState : epsilonClosureAndPath.keySet())     if (!nextState.equals(state)) {
      List<F> outputFuncAlongPath=new ArrayList<F>();
      for (      SFTEpsilon<P,F,S> transition : epsilonClosureAndPath.get(nextState)) {
        for (        S output : transition.outputs)         outputFuncAlongPath.add(ba.MkFuncConst(output));
      }
      for (      SFTInputMove<P,F,S> nextInputMove : sft.getInputMovesFrom(nextState)) {
        List<F> combinedOutputFunctions=new ArrayList<F>(outputFuncAlongPath);
        combinedOutputFunctions.addAll(nextInputMove.outputFunctions);
        transitions.add(new SFTInputMove<P,F,S>(state,nextInputMove.to,nextInputMove.guard,combinedOutputFunctions));
      }
    }
  }
  return MkSFT(transitions,sft.initialState,finalStatesAndTails,ba);
}