/** Returns an APMonom representing the formula rooted at this node. Formula has to be in DNF. */
  public APMonom toMonom(APSet apset) throws PrismException {
    APMonom result = new APMonom(true);

    switch (kind) {
      case AND:
        {
          APMonom l = left.toMonom(apset);
          APMonom r = right.toMonom(apset);

          result = l.and(r);
          return result;
        }
      case NOT:
        switch (left.kind) {
          case AP:
            result.setValue(apset.indexOf(left.ap), false);
            return result;
          case FALSE:
            return new APMonom(true);
          case TRUE:
            return new APMonom(false);
          default:
            throw new PrismException("Formula not in DNF!");
        }
      case AP:
        result.setValue(apset.indexOf(ap), true);
        return result;
      case FALSE:
        return new APMonom(false);
      case TRUE:
        return new APMonom(true);
      default:
        throw new PrismException("Formula not in DNF!");
    }
  }
  public APSet getAPs() {
    APSet rv;

    switch (kind) {
      case NOT:
      case NEXT:
      case GLOBALLY:
      case FINALLY:
        rv = left.getAPs();
        break;
      case OR:
      case AND:
      case EQUIV:
      case IMPLIES:
      case UNTIL:
      case RELEASE:
        rv = left.getAPs();
        for (String s : right.getAPs()) rv.addAP(s);
        break;
        // terminals
      case FALSE:
      case TRUE:
        rv = new APSet();
        break;
      case AP:
        rv = new APSet();
        rv.addAP(ap);
        break;
      default:
        rv = new APSet();
        break;
    }
    return rv;
  }