/**
  * Logically ands the provided terms with the terms in the formula, replacing this formula with
  * the result
  *
  * @param other the terms to and with this formula
  * @return this object.
  */
 public BooleanFormula andWith(BooleanFormula other) {
   if (other.isTrue()) {
     return this;
   }
   if (other.isFalse() || isFalse()) {
     if (booleanTerms == null) {
       booleanTerms = new HashSet<BooleanTerm>();
     } else {
       booleanTerms.clear();
     }
     isSimplified = true;
     return this;
   }
   if (isTrue()) {
     booleanTerms = new HashSet<BooleanTerm>(other.booleanTerms);
     return this;
   }
   BooleanFormula newTerms = new BooleanFormula();
   for (BooleanTerm otherTerm : other) {
     for (BooleanTerm term : booleanTerms) {
       BooleanTerm newTerm = term.andWith(otherTerm);
       if (newTerm != null) {
         newTerms.add(newTerm);
       }
     }
   }
   booleanTerms = newTerms.booleanTerms;
   isSimplified = newTerms.isSimplified;
   return this;
 }
 /**
  * Resolves the formula using the boolean values specified in <code>features</code>. If there are
  * no more un-resolved variables in the forumula, the resulting formula will be either TRUE or
  * FALSE.
  *
  * @param features the values to assign to variables in the formula
  * @return this object
  */
 public BooleanFormula resolveWith(Features features) {
   if (isTrue() || isFalse()) {
     return this;
   }
   BooleanFormula formula = new BooleanFormula();
   for (BooleanTerm term : this) {
     BooleanTerm evaluated = term.resolveWith(features);
     if (evaluated.isFalse()) {
       // term is false.  Don't add to result
     } else if (evaluated.isTrue()) {
       // term is true so formula is true
       booleanTerms = null;
       isSimplified = true;
       return this;
     } else {
       formula.add(evaluated);
     }
   }
   booleanTerms = formula.booleanTerms;
   isSimplified = formula.isSimplified;
   return this;
 }