/**
   * After a path was strengthened, we need to take care of the coverage relation. We also remove
   * the infeasible part from the ARG, and re-establish the coverage invariant (i.e., that states on
   * the path are either covered or cannot be covered).
   */
  @Override
  protected void finishRefinementOfPath(
      ARGState infeasiblePartOfART,
      List<ARGState> changedElements,
      ARGReachedSet pReached,
      boolean pRepeatedCounterexample)
      throws CPAException, InterruptedException {
    // only thing to do here is adding the false predicate for unreacheable states
    newPredicates.put(extractLocation(infeasiblePartOfART), predAbsMgr.makeFalsePredicate());
    changedElements.add(infeasiblePartOfART);

    if (restartAfterRefinement) {
      refinementRoot = (ARGState) reached.asReachedSet().getFirstState();

    } else if (refinementRoot == null) {
      refinementRoot = changedElements.get(0);

      // search parent of both refinement roots and use this as the new
      // refinement root
    } else {
      PathIterator firstPath = ARGUtils.getOnePathTo(refinementRoot).pathIterator();
      PathIterator secondPath = ARGUtils.getOnePathTo(changedElements.get(0)).pathIterator();

      // TODO should they be equal or identical?
      while (firstPath.getAbstractState().equals(secondPath.getAbstractState())) {
        refinementRoot = firstPath.getAbstractState();

        if (firstPath.hasNext() && secondPath.hasNext()) {
          firstPath.advance();
          secondPath.advance();
        } else {
          break;
        }
      }
    }
  }
  /**
   * This method chooses a new refinement root, in a bottom-up fashion along the error path. It
   * either picks the next state on the path sharing the same CFA location, or the (only) child of
   * the ARG root, what ever comes first.
   *
   * @param currentRoot the current refinement root
   * @return the relocated refinement root
   */
  private ARGState relocateRepeatedRefinementRoot(final ARGState currentRoot) {
    repeatedRefinements.inc();
    int currentRootNumber = AbstractStates.extractLocation(currentRoot).getNodeNumber();

    ARGPath path = ARGUtils.getOnePathTo(currentRoot);
    for (ARGState currentState : path.asStatesList().reverse()) {
      // skip identity, because a new root has to be found
      if (currentState == currentRoot) {
        continue;
      }

      if (currentRootNumber == AbstractStates.extractLocation(currentState).getNodeNumber()) {
        return currentState;
      }
    }

    return Iterables.getOnlyElement(path.getFirstState().getChildren());
  }