private ConfigurableProgramAnalysis getCPA(
     ReachedSetFactory reachedSetFactory, Configuration singleConfig1)
     throws InvalidConfigurationException, CPAException {
   CPABuilder builder1 =
       new CPABuilder(singleConfig1, logger, shutdownNotifier, reachedSetFactory);
   ConfigurableProgramAnalysis cpa1 =
       builder1.buildCPAs(cfa, specification, new AggregatedReachedSets());
   if (cpa1 instanceof StatisticsProvider) {
     ((StatisticsProvider) cpa1).collectStatistics(stats.getSubStatistics());
   }
   return cpa1;
 }
  private Algorithm getAlgorithm(
      ShutdownNotifier singleShutdownNotifier,
      Configuration singleConfig,
      LogManager singleLogger,
      ConfigurableProgramAnalysis cpa)
      throws InvalidConfigurationException, CPAException {
    singleLogger.log(Level.FINE, "Creating algorithms");
    Algorithm algorithm =
        CPAAlgorithm.create(cpa, singleLogger, singleConfig, singleShutdownNotifier);

    CEGARAlgorithm cegarAlgorithm = new CEGARAlgorithm(algorithm, cpa, singleConfig, singleLogger);
    cegarAlgorithm.collectStatistics(stats.getSubStatistics());

    return cegarAlgorithm;
  }
  @Override
  public AlgorithmStatus run(ReachedSet pReached) throws CPAException, InterruptedException {
    checkArgument(
        pReached instanceof ForwardingReachedSet, "RestartAlgorithm needs ForwardingReachedSet");
    ForwardingReachedSet reached = (ForwardingReachedSet) pReached;

    CFANode mainFunction = AbstractStates.extractLocation(pReached.getFirstState());
    assert mainFunction != null : "Location information needed";

    AlgorithmStatus status = AlgorithmStatus.UNSOUND_AND_PRECISE;

    try {
      ReachedSetFactory reachedSetFactory = new ReachedSetFactory(globalConfig);

      // predicate analysis
      logger.log(Level.FINE, "Creating CPA for PredicateAnalysis");
      Configuration singleConfig1 = getConfigFromFile(configFiles.get(0));
      ConfigurableProgramAnalysis cpa1 = getCPA(reachedSetFactory, singleConfig1);
      Algorithm algorithm1 = getAlgorithm(shutdownNotifier, singleConfig1, logger, cpa1);
      ReachedSet reached1 =
          createInitialReachedSetForRestart(cpa1, mainFunction, singleConfig1, logger);

      reached.setDelegate(reached1);

      stats.noOfAlgorithmsUsed++;
      stats.totalTime.start();

      status = run0(reached1, algorithm1);

      // stats.printIntermediateStatistics(System.out, Result.UNKNOWN, reached); // disabled,
      // because table-generator can not distinguish 1st and 2nd statistics.
      stats.resetSubStatistics();

      // predicate bit-precise analysis
      logger.log(Level.FINE, "Creating CPA for PredicateAnalysis-Bitprecise");
      Configuration singleConfig2 = getConfigFromFile(configFiles.get(1));
      ConfigurableProgramAnalysis cpa2 = getCPA(reachedSetFactory, singleConfig2);

      {
        // this is the important step: re-use the reached-set
        ARGReplayCPA argReplay = CPAs.retrieveCPA(cpa2, ARGReplayCPA.class);
        checkNotNull(argReplay, "ARGReplay-CPA is needed for second analysis");
        argReplay.setARGAndCPA(reached1, cpa1);
      }

      Algorithm algorithm2 = getAlgorithm(shutdownNotifier, singleConfig2, logger, cpa2);
      ReachedSet reached2 =
          createInitialReachedSetForRestart(cpa2, mainFunction, singleConfig2, logger);

      reached.setDelegate(reached2);

      stats.noOfAlgorithmsUsed++;
      stats.totalTime.start();

      status = run0(reached2, algorithm2);

      stats.printIntermediateStatistics(System.out, Result.UNKNOWN, reached);
      stats.resetSubStatistics();

    } catch (InvalidConfigurationException e) {
      logger.logUserException(
          Level.WARNING, e, "Exiting analysis because the configuration file is invalid");
    } catch (IOException e) {
      logger.logUserException(
          Level.WARNING, e, "Exiting analysis because the configuration file could not be read");
    } finally {
      // TODO close CPAs and algorithms
    }

    return status;
  }