Example #1
0
/*
 * Flatten all terms in flat->queue to conjuncts
 * - all terms in the queue must also be in the cache
 * - f_ite: if true, flatten (ite c a b)
 * - f_iff: if true, flatten (iff a b)
 */
static void flattener_build_conjuncts(flattener_t *flat, bool f_ite, bool f_iff) {
  term_table_t *terms;
  int_queue_t *queue;
  composite_term_t *d;
  term_t t, u, v;
  uint32_t i, n;

  queue = &flat->queue;
  terms = flat->terms;

  while (! int_queue_is_empty(queue)) {
    t = int_queue_pop(queue);

    switch (term_kind(terms, t)) {
    case ITE_TERM:
    case ITE_SPECIAL:
      d = ite_term_desc(terms, t);
      assert(d->arity == 3);
      if (f_ite && is_boolean_term(terms, d->arg[1])) {
        assert(is_boolean_term(terms, d->arg[2]));
        /*
         * If t is (ite C A B)
         *    u := (C => A)
         *    v := (not C => B)
         * Otherwise, t is (not (ite C A B))
         *    u := (C => not A)
         *    v := (not C => not B)
         */
        u = d->arg[1];  // A
        v = d->arg[2];  // B
        if (is_neg_term(t)) {
          u = opposite_term(u);
          v = opposite_term(v);
        }
        u = mk_implies(flat->manager, d->arg[0], u); // (C => u)
        v = mk_implies(flat->manager, opposite_term(d->arg[0]), v); // (not C) => v
        flattener_push_term(flat, u);
        flattener_push_term(flat, v);
        continue;
      }
      break;

    case EQ_TERM:
      d = eq_term_desc(terms, t);
      assert(d->arity == 2);
      if (f_iff && is_boolean_term(terms, d->arg[0])) {
        assert(is_boolean_term(terms, d->arg[1]));
        /*
         * t is either (iff A B) or (not (iff A B)):
         */
        u = d->arg[0]; // A
        v = d->arg[1]; // B
        if (is_neg_term(t)) {
          u = opposite_term(u);
        }
        // flatten to (u => v) and (v => u)
        t = mk_implies(flat->manager, u, v); // (u => v)
        u = mk_implies(flat->manager, v, u); // (v => u);
        flattener_push_term(flat, t);
        flattener_push_term(flat, u);
        continue;
      }
      break;

    case OR_TERM:
      if (is_neg_term(t)) {
        /*
         * t is (not (or a[0] ... a[n-1]))
         * it flattens to (and (not a[0]) ... (not a[n-1]))
         */
        d = or_term_desc(terms, t);
        n = d->arity;
        for (i=0; i<n; i++) {
          flattener_push_term(flat, opposite_term(d->arg[i]));
        }
        continue;
      }
      break;

    default:
      break;
    }
    ivector_push(&flat->resu, t);
  }

  // clean up the cache
  assert(int_queue_is_empty(queue));
  int_hset_reset(&flat->cache);
}
Example #2
0
/*
 * Check whether t occurs in v
 * - t must be a free root
 * - v must be a valid term
 */
static bool bfs_occurs_check(intern_tbl_t *tbl, term_t t, term_t v) {
  term_table_t *terms;
  int_queue_t *queue;
  int_hset_t *cache;
  int32_t x;
  bool found;

  assert(intern_tbl_root_is_free(tbl, t));
  assert(is_pos_term(t) && term_kind(tbl->terms, t) == UNINTERPRETED_TERM);

  terms = tbl->terms;
  queue = intern_tbl_get_queue(tbl);
  cache = intern_tbl_get_cache(tbl);

  assert(int_queue_is_empty(queue) && int_hset_is_empty(cache));

  bfs_visit_term(tbl, v);
  found = false;

  do {
    x = int_queue_pop(queue);

    switch (kind_for_idx(terms, x)) {
    case CONSTANT_TERM:
    case ARITH_CONSTANT:
    case BV64_CONSTANT:
    case BV_CONSTANT:
    case VARIABLE:
      break;

    case UNINTERPRETED_TERM:
      if (x == index_of(t)) {
        // found a cycle
        found = true;
        goto done;
      }
      break;

    case ARITH_EQ_ATOM:
    case ARITH_GE_ATOM:
      bfs_visit_term(tbl, integer_value_for_idx(terms, x));
      break;

    case ITE_TERM:
    case ITE_SPECIAL:
    case APP_TERM:
    case UPDATE_TERM:
    case TUPLE_TERM:
    case EQ_TERM:
    case DISTINCT_TERM:
    case FORALL_TERM:
    case LAMBDA_TERM:
    case OR_TERM:
    case XOR_TERM:
    case ARITH_BINEQ_ATOM:
    case BV_ARRAY:
    case BV_DIV:
    case BV_REM:
    case BV_SDIV:
    case BV_SREM:
    case BV_SMOD:
    case BV_SHL:
    case BV_LSHR:
    case BV_ASHR:
    case BV_EQ_ATOM:
    case BV_GE_ATOM:
    case BV_SGE_ATOM:
      bfs_visit_composite(tbl, composite_for_idx(terms, x));
      break;

    case BIT_TERM:
    case SELECT_TERM:
      bfs_visit_term(tbl, select_for_idx(terms, x)->arg);
      break;

    case POWER_PRODUCT:
      bfs_visit_pprod(tbl, pprod_for_idx(terms, x));
      break;

    case ARITH_POLY:
      bfs_visit_poly(tbl, polynomial_for_idx(terms, x));
      break;

    case BV64_POLY:
      bfs_visit_bvpoly64(tbl, bvpoly64_for_idx(terms, x));
      break;

    case BV_POLY:
      bfs_visit_bvpoly(tbl, bvpoly_for_idx(terms, x));
      break;

    default:
      assert(false);
      abort();
      break;
    }

  } while (! int_queue_is_empty(queue));

 done:
  int_hset_reset(cache);
  int_queue_reset(queue);

  return found;
}
Example #3
0
/*
 * Process disjuncts and universal quantifiers
 * - input = all terms in the queue
 * - f_ite: if true, flatten (ite c a b)
 * - f_iff: if true, flatten (iff a b)
 */
static void flattener_forall_disjuncts(flattener_t *flat, bool f_ite, bool f_iff) {
  term_table_t *terms;
  int_queue_t *queue;
  composite_term_t *d;
  term_t t, u, v;
  uint32_t i, n;

  queue = &flat->queue;
  terms = flat->terms;

  while (! int_queue_is_empty(queue)) {
    t = int_queue_pop(queue);

    switch (term_kind(terms, t)) {
    case ITE_TERM:
    case ITE_SPECIAL:
      d = ite_term_desc(terms, t);
      assert(d->arity == 3);
      if (f_ite && is_boolean_term(terms, d->arg[1])) {
        assert(is_boolean_term(terms, d->arg[2]));
        /*
         * If t is (ite C A B)
         *    u := (C AND A)
         *    v := (not C AND B)
         * Otherwise, t is (not (ite C A B))
         *    u := (C AND not A)
         *    v := (not C AND not B)
         */
        u = d->arg[1];  // A
        v = d->arg[2];  // B
        if (is_neg_term(t)) {
          u = opposite_term(u); // NOT A
          v = opposite_term(v); // NOT B
        }
        u = mk_binary_and(flat->manager, d->arg[0], u); // (C AND u)
        v = mk_binary_and(flat->manager, opposite_term(d->arg[0]), v); // (not C) AND v
        flattener_push_term(flat, u);
        flattener_push_term(flat, v);
        continue;
      }
      break;

    case EQ_TERM:
      d = eq_term_desc(terms, t);
      assert(d->arity == 2);
      if (f_iff && is_boolean_term(terms, d->arg[0])) {
        assert(is_boolean_term(terms, d->arg[1]));
        /*
         * t is either (iff A B) or (not (iff A B)):
         */
        u = d->arg[0]; // A
        v = d->arg[1]; // B
        if (is_neg_term(t)) {
          u = opposite_term(u);
        }
        // flatten to (u AND v) or ((not u) AND (not v))
        t = mk_binary_and(flat->manager, u, v); // (u AND v)
        u = mk_binary_and(flat->manager, opposite_term(u), opposite_term(v)); // (not u AND not v);
        flattener_push_term(flat, t);
        flattener_push_term(flat, u);
        continue;
      }
      break;

    case OR_TERM:
      if (is_pos_term(t)) {
        /*
         * t is (or a[0] ... a[n-1])
         */
        d = or_term_desc(terms, t);
        n = d->arity;
        for (i=0; i<n; i++) {
          flattener_push_term(flat, d->arg[i]);
        }
        continue;
      }
      break;

    case FORALL_TERM:
      if (is_pos_term(t)) {
        d = forall_term_desc(terms, t);
        n = d->arity;
        assert(n >= 2);
        /*
         * t is (FORALL x_0 ... x_k : body)
         * body is the last argument in the term descriptor
         */
        flattener_push_term(flat, d->arg[n-1]);
        continue;
      }
      break;

    default:
      break;
    }

    ivector_push(&flat->resu, t);
  }

  // clean up the cache
  assert(int_queue_is_empty(queue));
  int_hset_reset(&flat->cache);
}
Example #4
0
/*
 * Check whether f is a range constraint
 * - if so return a term t and fill in vector v with the formula's constants
 * - otherwise, return NULL_TERM
 *
 * Side effect: use queue and cache.
 * v may be modified even if the function returns NULL_TERM.
 */
static term_t formula_is_range_constraint(sym_breaker_t *breaker, term_t f, ivector_t *v) {
  int_queue_t *queue;
  int_hset_t *cache;
  term_table_t *terms;
  intern_tbl_t *intern;
  term_t r, t;
  term_t x, a, y, b;
  uint32_t neqs;

  queue = &breaker->queue;
  cache = &breaker->cache;
  terms = breaker->terms;
  intern = &breaker->ctx->intern;

  assert(int_queue_is_empty(queue) && int_hset_is_empty(cache));
  push_term(queue, cache, f);

  neqs = 0;
  t = NULL_TERM;

  y = NULL_TERM; // prevent GCC warning
  b = NULL_TERM; // prevent GCC warning

  /*
   * Invariants:
   * - neqs = number of equality atoms seen so far
   * - if neq == 1, then the first equality is stored as (y == b) where b is a constant
   * - if neq >= 2, then all equalities seen so far were of the form (x == constant)
   */
  do {
    // r := root of the first term in the queue
    r = intern_tbl_get_root(intern, int_queue_pop(queue));

    switch (match_term(breaker->ctx, r, &a, &x)) {
    case MATCH_FALSE: // skip false terms
      break;

    case MATCH_OR:
      push_children(queue, cache, or_term_desc(terms, r));
      break;

    case MATCH_EQ:
      assert(term_is_constant(terms, a));
      if (neqs == 0) {
	y = x; b = a;
      } else if (neqs == 1) {
	/*
	 * First equality: (y == b). Second equality: (x == a)
	 */
	if (y == x) {
	  // y is the common term, a and b are constant
	  ivector_push(v, b);
	  ivector_push(v, a);
	} else if (y == a && term_is_uconst(terms, x)) {
	  // y is the common term, b and x are constant
	  ivector_push(v, b);
	  ivector_push(v, a);
	} else if (x == b && term_is_uconst(terms, y)) {
	  // b is the common term, y and a are constant
	  ivector_push(v, y);
	  ivector_push(v, a);
	  y = b;
	} else if (a == b && term_is_uconst(terms, y) && term_is_uconst(terms, x)) {
	  // b is the common term, y and x are constant
	  ivector_push(v, y);
	  ivector_push(v, x);
	  y = b;
	} else {
	  // abort
	  goto done;
	}

      } else {
	/*
	 * All equalities so far have the form (y == constant)
	 * - the current equality is (x == a)
	 */
	if (y == x) {
	  ivector_push(v, a); // match
	} else if (y == a && term_is_constant(terms, x)) {
	  ivector_push(v, x); // swap a and x
	} else {
	  // no match
	  goto done;
	}
      }
      neqs ++;
      break;

    case MATCH_IFF:
      /*
       * the returned term x is equivalent to t
       */
      push_term(queue, cache, x);
      break;

    default:
      // abort
      goto done;
    }
  } while (! int_queue_is_empty(queue));

  assert(y != NULL_TERM && t == NULL_TERM);

  if (neqs >= 2) {
    assert(v->size == neqs);
    t = y;
  }

 done:
  int_queue_reset(queue);
  int_hset_reset(cache);

  return t;
}