private boolean noConcreteSuccessorExist(
     final ARGState pPredecessor,
     final CFAEdge pSuccEdge,
     HistoryForwardingReachedSet pForwaredReachedSet) {
   // check if analysis stopped exploration due e.g. time limit
   for (ReachedSet reached : pForwaredReachedSet.getAllReachedSetsUsedAsDelegates()) {
     if (reached.getWaitlist().contains(pPredecessor)) {
       return false;
     }
   }
   // check if analysis stopped exploration due to true state in automaton --> concrete successors
   // may exist
   for (AbstractState state : AbstractStates.asIterable(pPredecessor)) {
     if (state instanceof AutomatonState
         && ((AutomatonState) state).getOwningAutomatonName().equals("AssumptionAutomaton")) {
       if (AutomatonStateARGCombiningHelper.endsInAssumptionTrueState(
           (AutomatonState) state, pSuccEdge)) {
         return false;
       }
     }
   }
   return true;
 }
  @Override
  public AlgorithmStatus run(ReachedSet pReachedSet)
      throws CPAException, InterruptedException, CPAEnabledAnalysisPropertyViolationException {
    checkArgument(
        pReachedSet instanceof ForwardingReachedSet,
        "PartialARGsCombiner needs ForwardingReachedSet");

    HistoryForwardingReachedSet reached = new HistoryForwardingReachedSet(pReachedSet);

    logger.log(Level.INFO, "Start inner algorithm to analyze program(s)");
    AlgorithmStatus status = AlgorithmStatus.UNSOUND_AND_PRECISE;

    stats.analysisTime.start();
    try {
      status = restartAlgorithm.run(reached);
    } finally {
      stats.analysisTime.stop();
    }

    if (status.isSound()) {
      shutdown.shutdownIfNecessary();

      logger.log(Level.INFO, "Program(s) soundly analyzed, start combining ARGs.");

      stats.argCombineTime.start();
      try {
        Collection<ReachedSet> usedReachedSets = reached.getAllReachedSetsUsedAsDelegates();

        if (usedReachedSets.size() <= 1) {
          logger.log(Level.INFO, "Only a single ARG is considered. Do not need to combine ARGs");
          if (usedReachedSets.size() == 1) {
            ((ForwardingReachedSet) pReachedSet).setDelegate(reached.getDelegate());
          }
          return status;
        }

        if (from(reached.getDelegate()).anyMatch((IS_TARGET_STATE))) {
          logger.log(Level.INFO, "Error found, do not combine ARGs.");
          ((ForwardingReachedSet) pReachedSet).setDelegate(reached.getDelegate());
          return status;
        }

        logger.log(Level.FINE, "Extract root nodes of ARGs");
        List<ARGState> rootNodes = new ArrayList<>(usedReachedSets.size());
        for (ReachedSet usedReached : usedReachedSets) {
          checkArgument(
              usedReached.getFirstState() instanceof ARGState,
              "Require that all restart configurations use ARGCPA as top level CPA.");
          checkArgument(
              AbstractStates.extractLocation(usedReached.getFirstState()) != null,
              "Require that all restart configurations consider a location aware state");

          for (AbstractState errorState : from(usedReached).filter((IS_TARGET_STATE))) {
            logger.log(
                Level.INFO,
                "Error state found in reached set ",
                usedReached,
                "but not by last configuration. Error state must be infeasible.");
            logger.log(Level.FINE, "Remove infeasible error state", errorState);
            ((ARGState) errorState).removeFromARG();
          }

          rootNodes.add((ARGState) usedReached.getFirstState());
        }

        shutdown.shutdownIfNecessary();

        if (!combineARGs(rootNodes, (ForwardingReachedSet) pReachedSet, reached)) {
          logger.log(Level.SEVERE, "Combination of ARGs failed.");
          return status.withSound(false);
        }
      } finally {
        stats.argCombineTime.stop();
      }

      logger.log(Level.INFO, "Finished combination of ARGS");

    } else {
      logger.log(
          Level.INFO,
          "Program analysis is already unsound.",
          "Do not continue with combination of unsound results");
      // set reached set to last used by restart algorithm
      if (reached.getDelegate() != pReachedSet) {
        ((ForwardingReachedSet) pReachedSet).setDelegate(reached.getDelegate());
      }
      return status.withSound(false);
    }

    return status.withSound(true);
  }