示例#1
0
/**Function********************************************************************

   Synopsis           [Aux fun of w2w_wff_expand_case]

   Description        [Aux fun of w2w_wff_expand_case]

   SideEffects        []

   SeeAlso            []

******************************************************************************/
static node_ptr w2w_wff_expand_case_aux(node_ptr wff)
{
  if (CASE == node_get_type(wff) || IFTHENELSE == node_get_type(wff)) {
    node_ptr cur_cond  = car(car(wff));
    node_ptr cur_rslt  = cdr(car(wff));
    node_ptr case_rest = cdr(wff);
    node_ptr res;

    nusmv_assert(node_get_type(car(wff)) == COLON);

    /* here lazy evaluation is required to get rid of FAILURE node
       in case-expressions (see this function below)
    */
    if (cur_cond == Wff_make_truth()) return cur_rslt;
    if (cur_cond == Wff_make_falsity()) return case_rest;

    res = Wff_make_or( Wff_make_and(cur_cond, cur_rslt),
                       Wff_make_and(Wff_make_not(cur_cond),
                                    w2w_wff_expand_case_aux(case_rest))
                       );
    return res;

  }
  else {
    if (FAILURE == node_get_type(wff)) {
      if (failure_get_kind(wff) == FAILURE_CASE_NOT_EXHAUSTIVE) {
        warning_case_not_exhaustive(wff);
        /* forces a default */
        return Wff_make_truth();
      }
      else if (failure_get_kind(wff) == FAILURE_DIV_BY_ZERO) {
        warning_possible_div_by_zero(wff);
        /* forces a default */
        return Wff_make_truth();
      }
      else if (failure_get_kind(wff) == FAILURE_ARRAY_OUT_OF_BOUNDS) {
        warning_possible_array_out_of_bounds(wff);
        /* forces a default */
        return Wff_make_truth();
      }
      else {
        report_failure_node(wff); /* some error in the input expr */
        error_unreachable_code();
      }
    }

    return wff;
  }
}
示例#2
0
node_ptr Wff_make_or(NodeMgr_ptr nodemgr, node_ptr arg1, node_ptr arg2)
{
  node_ptr falsity;
  node_ptr truth;

  truth = Wff_make_truth(nodemgr);
  if ((arg1 == truth) || (arg2 == truth)) return truth;

  falsity = Wff_make_falsity(nodemgr);
  if (arg1 == falsity) return arg2;
  if (arg2 == falsity) return arg1;

  return expr_wff_make_binary(nodemgr, OR, arg1, arg2);
}
示例#3
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;
}