示例#1
0
node_ptr Wff_make_opnext_times(NodeMgr_ptr nodemgr, node_ptr arg, int x)
{
  nusmv_assert(x >= 0);

  if (x == 0)
    return arg;
  else
    return Wff_make_opnext(nodemgr, Wff_make_opnext_times(nodemgr, arg, x - 1));
}
示例#2
0
/**Function********************************************************************

   Synopsis           [The private function that does the actual
                       wff2nnf conversion]

   Description        [The private function that does the actual
                       wff2nnf conversion]

   SideEffects        []

   SeeAlso            []

******************************************************************************/
static node_ptr w2w_wff_mk_nnf(node_ptr wff, boolean pol)
{
  node_ptr res;

  /* if reached a Nil branch then end recursion with a Nil node */
  if (wff == Nil) return Nil;

  /* Only temporal operator X (node type OP_NEXT) is legal in LTL wffs.
     The operator NEXT used in model definition is trapped. */
  nusmv_assert(node_get_type(wff) != NEXT);

  res = w2w_wff2nnf_hash_lookup_entry(wff, pol);
  if (res != (node_ptr) NULL) return res;

  switch (node_get_type(wff)) {
  case TRUEEXP:
    if (pol) res = Wff_make_truth();
    else res = Wff_make_falsity();  /* !1 <-> 0 */
    break;

  case FALSEEXP:
    if (pol) res = Wff_make_falsity();
    else res = Wff_make_truth();    /* !0 <-> 1 */
    break;

  case NOT:
    /* !(a) <-> (!a) */
    /* !(!a) <-> a */
    res = w2w_wff_mk_nnf(car(wff), !pol);
    break;

  case AND:
    if (pol) res = Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                                w2w_wff_mk_nnf(cdr(wff), true));
    else {
      /* !(a & b) <-> (!a | !b) */
      res = Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                        w2w_wff_mk_nnf(cdr(wff), false));
    }
    break;

  case OR:
    if (pol) res = Wff_make_or(w2w_wff_mk_nnf(car(wff), true),
                               w2w_wff_mk_nnf(cdr(wff), true));
    else {
      /* !(a | b) <-> (!a & !b) */
      res = Wff_make_and(w2w_wff_mk_nnf(car(wff), false),
                         w2w_wff_mk_nnf(cdr(wff), false));
    }
    break;

  case IMPLIES:
    if (pol) {
      /* (a -> b) <-> !(a & !b) <-> (!a | b) */
      res = Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                        w2w_wff_mk_nnf(cdr(wff), true));
    }
    else {
      /* !(a -> b) <-> (a & !b) */
      res = Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                         w2w_wff_mk_nnf(cdr(wff), false));
    }
    break;

  case IFF:
    if (pol) {
      /* (a <-> b) <->
         !(a & !b) & !(b & !a) <->
         (!a | b) & (!b | a) */
      res = Wff_make_and( Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)),
                          Wff_make_or(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)) );
    }
    else {
      /* !(a <-> b) <->
         !(!(a & !b) & !(b & !a)) <->
         (a & !b) | (b & !a) */
      res = Wff_make_or( Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)),
                         Wff_make_and(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)) );
    }
    break;

  case XOR:
    if (pol) {
      /* (a xor b) <-> (a & !b) | (!a & b) */
      res = Wff_make_or( Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)),
                         Wff_make_and(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)) );
    }
    else {
      /* !(a xnor b) <-> (a | !b) & (!a | b) */
      res = Wff_make_and( Wff_make_or(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)),
                          Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)) );
    }
    break;

  case XNOR:
    if (pol) {
      /* (a xnor b) <-> (!a | b) & (!b | a) */
      res = Wff_make_and( Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)),
                          Wff_make_or(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)) );
    }
    else {
      /* !(a xnor b) <-> (a & !b) | (!a & b) */
      res = Wff_make_or( Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)),
                         Wff_make_and(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)) );
    }
    break;

  case OP_NEXT:
    /* !X(a) <-> X(!a) */
    res = Wff_make_opnext(w2w_wff_mk_nnf(car(wff), pol));
    break;

  case OP_PREC:
    /* !Y(a) <-> Z(!a) */
    if (pol) res = Wff_make_opprec(w2w_wff_mk_nnf(car(wff), pol));
    else res = Wff_make_opnotprecnot(w2w_wff_mk_nnf(car(wff), pol));
    break;

  case OP_NOTPRECNOT:
    /* !Z(a) <-> Y(!a) */
    if (pol) res = Wff_make_opnotprecnot(w2w_wff_mk_nnf(car(wff), pol));
    else res = Wff_make_opprec(w2w_wff_mk_nnf(car(wff), pol));
    break;

  case OP_GLOBAL:
    if (pol) res = Wff_make_globally(w2w_wff_mk_nnf(car(wff), pol));
    else {
      /* !G(a) <-> F(!a) */
      res = Wff_make_eventually(w2w_wff_mk_nnf(car(wff), pol));
    }
    break;

  case OP_HISTORICAL:
    if (pol) res = Wff_make_historically(w2w_wff_mk_nnf(car(wff), pol));
    else {
      /* !H(a) <-> O(!a) */
      res = Wff_make_once(w2w_wff_mk_nnf(car(wff), pol));
    }
    break;

  case OP_FUTURE:
    if (pol) res = Wff_make_eventually(w2w_wff_mk_nnf(car(wff), pol));
    else {
      /* !F(a) <-> G(!a) */
      res = Wff_make_globally(w2w_wff_mk_nnf(car(wff), pol));
    }
    break;

  case OP_ONCE:
    if (pol) res = Wff_make_once(w2w_wff_mk_nnf(car(wff), pol));
    else {
      /* !O(a) <-> H(!a) */
      res = Wff_make_historically(w2w_wff_mk_nnf(car(wff), pol));
    }
    break;

  case UNTIL:
    if (pol) res = Wff_make_until(w2w_wff_mk_nnf(car(wff), pol),
                                  w2w_wff_mk_nnf(cdr(wff), pol));
    else {
      /* !(a U b) <-> (!a V !b) */
      res = Wff_make_releases(w2w_wff_mk_nnf(car(wff), pol),
                              w2w_wff_mk_nnf(cdr(wff), pol));
    }
    break;

  case SINCE:
    if (pol) res = Wff_make_since(w2w_wff_mk_nnf(car(wff), pol),
                                  w2w_wff_mk_nnf(cdr(wff), pol));
    else {
      /* !(a S b) <-> (!a T !b) */
      res = Wff_make_triggered(w2w_wff_mk_nnf(car(wff), pol),
                               w2w_wff_mk_nnf(cdr(wff), pol));
    }
    break;

  case RELEASES:
    if (pol) res = Wff_make_releases(w2w_wff_mk_nnf(car(wff), pol),
                                     w2w_wff_mk_nnf(cdr(wff), pol));
    else {
      /* !(a V b) <-> (!a U !b) */
      res = Wff_make_until(w2w_wff_mk_nnf(car(wff), pol),
                           w2w_wff_mk_nnf(cdr(wff), pol));
    }
    break;

  case TRIGGERED:
    if (pol) res = Wff_make_triggered(w2w_wff_mk_nnf(car(wff), pol),
                                      w2w_wff_mk_nnf(cdr(wff), pol));
    else {
      /* !(a T b) <-> (!a S !b) */
      res = Wff_make_since(w2w_wff_mk_nnf(car(wff), pol),
                           w2w_wff_mk_nnf(cdr(wff), pol));
    }
    break;

  case IFTHENELSE:
  case CASE:
    {
      node_ptr nocase_wff = w2w_wff_expand_case(wff);
      res = w2w_wff_mk_nnf(nocase_wff, pol);
      break;
    }

  case BIT:
  case DOT:
  case ARRAY:
    /* it is a bexp var */
    if (pol) res = wff;
    else res = Wff_make_not(wff);
    break;

  case ATOM:
  case NUMBER:
  case NUMBER_UNSIGNED_WORD:
  case NUMBER_SIGNED_WORD:
  case NUMBER_FRAC:
  case NUMBER_REAL:
  case NUMBER_EXP:
    /* internal format for atoms that should have been previously
       hidden within DOT and ARRAY */
    internal_error("w2w_wff_mk_nnf: unexpected leaf %d\n",
                   node_get_type(wff));
    res = (node_ptr) NULL;
    break;

  case MOD:
    internal_error("w2w_wff_mk_nnf: unexpected mod operator\n");

    /* stop recursion when a predicate is found */
  case LE: case LT:
  case GE: case GT:
  case EQUAL: case NOTEQUAL:
  case SETIN:
    res = (pol) ? wff : Wff_make_not(wff);
      break;

  default:
    internal_error("w2w_wff_mk_nnf: unexpected TOKEN %d\n",
                   node_get_type(wff));

  }

  if (res != (node_ptr) NULL) {
    w2w_wff2nnf_hash_insert_entry(wff, pol, res);
  }

  return res;
}