@Override
    public BDD visitIfThenElse(
        BooleanFormula pCondition, BooleanFormula pThenFormula, BooleanFormula pElseFormula) {
      BDD condition = convert(pCondition);
      BDD thenBDD = convert(pThenFormula);
      BDD elseBDD = convert(pElseFormula);

      BDD result = condition.ite(thenBDD, elseBDD);

      condition.free();
      thenBDD.free();
      elseBDD.free();
      return result;
    }
 @Override
 public BDD visitNot(BooleanFormula pOperand) {
   BDD operand = convert(pOperand);
   BDD result = operand.not();
   operand.free();
   return result;
 }
 @Override
 public void close() {
   for (BDD bdd : cache.values()) {
     bdd.free();
   }
   cache.clear();
 }
 @Override
 public void close() {
   checkState(currentCube == null);
   for (BDD bdd : cubes) {
     bdd.free();
   }
   cubes.clear();
 }
  @Override
  public boolean entails(Region pF1, Region pF2) {
    cleanupReferences();

    // check entailment using BDDs: create the BDD representing
    // the implication, and check that it is the TRUE formula
    BDD imp = unwrap(pF1).imp(unwrap(pF2));

    boolean result = imp.isOne();
    imp.free();
    return result;
  }
  /**
   * Cleanup all references to BDDs that are no longer needed. We call this method from all public
   * methods, so that this gets done as soon as possible. Usually we would do this in a daemon
   * thread in the background, but the BDD library is not multi-threaded.
   */
  private void cleanupReferences() {
    cleanupTimer.start();
    try {
      int count = 0;
      Reference<? extends JavaBDDRegion> ref;
      while ((ref = referenceQueue.poll()) != null) {
        count++;

        BDD bdd = referenceMap.remove(ref);
        assert bdd != null;
        bdd.free();
      }
      cleanupQueueSize.setNextValue(count);
    } finally {
      cleanupTimer.stop();
    }
  }
  @Override
  public Region makeExists(Region pF1, Region... pF2) {
    cleanupReferences();

    if (pF2.length == 0) {
      return pF1;
    }

    // we use id() to get copies of the BDDs, otherwise we would delete them
    BDD f = unwrap(pF2[0]).id();
    for (int i = 1; i < pF2.length; i++) {
      f.andWith(unwrap(pF2[i]).id());
    }
    Region result = wrap(unwrap(pF1).exist(f));
    f.free();

    return result;
  }