/**
   * Get the predicates out of an interpolant.
   *
   * @param pInterpolant The interpolant formula.
   * @return A set of predicates.
   */
  private final Collection<AbstractionPredicate> convertInterpolant(
      final BooleanFormula pInterpolant) {

    BooleanFormula interpolant = pInterpolant;

    if (bfmgr.isTrue(interpolant)) {
      return Collections.<AbstractionPredicate>emptySet();
    }

    Collection<AbstractionPredicate> preds;

    if (atomicPredicates) {
      preds = predAbsMgr.getPredicatesForAtomsOf(interpolant);

    } else {
      preds = ImmutableList.of(predAbsMgr.getPredicateFor(interpolant));
    }

    assert !preds.isEmpty()
        : "Interpolant without relevant predicates: "
            + pInterpolant
            + "; simplified to "
            + interpolant;

    logger.log(Level.FINEST, "Got predicates", preds);

    return preds;
  }
  @Override
  protected boolean performRefinementForState(BooleanFormula pInterpolant, ARGState pState)
      throws InterruptedException, SolverException {
    checkState(newPredicates != null);
    checkArgument(!bfmgr.isTrue(pInterpolant));

    predicateCreation.start();
    newPredicates.putAll(extractLocation(pState), convertInterpolant(pInterpolant));
    predicateCreation.stop();

    return false;
  }
  /**
   * For each interpolant, we strengthen the corresponding state by conjunctively adding the
   * interpolant to its state formula. This is all implemented in {@link
   * ImpactUtility#strengthenStateWithInterpolant(BooleanFormula, ARGState, AbstractionFormula)}.
   */
  @Override
  protected boolean performRefinementForState(BooleanFormula itp, ARGState s)
      throws SolverException, InterruptedException {
    checkArgument(!bfmgr.isTrue(itp));
    checkArgument(!bfmgr.isFalse(itp));

    boolean stateChanged = impact.strengthenStateWithInterpolant(itp, s, lastAbstraction);

    // Get the abstraction formula of the current state
    // (whether changed or not) to have it ready for the next call to this method).
    lastAbstraction = getPredicateState(s).getAbstractionFormula();

    return !stateChanged; // Careful: this method requires negated return value.
  }
  @Override
  public Region fromFormula(
      BooleanFormula pF, FormulaManagerView fmgr, Function<BooleanFormula, Region> atomToRegion) {
    cleanupReferences();

    BooleanFormulaManagerView bfmgr = fmgr.getBooleanFormulaManager();
    if (bfmgr.isFalse(pF)) {
      return makeFalse();
    }

    if (bfmgr.isTrue(pF)) {
      return makeTrue();
    }

    try (FormulaToRegionConverter converter = new FormulaToRegionConverter(fmgr, atomToRegion)) {
      return wrap(bfmgr.visit(pF, converter));
    }
  }