/* * Main abstraction function */ static epartition_t *eq_abstract(eq_learner_t *learner, term_t f, bool polarity) { term_table_t *terms; epartition_t *a; assert(is_boolean_term(learner->terms, f)); a = find_cached_abstraction(learner, signed_term(f, polarity)); if (a == NULL) { // not in the cache // remove top-level negation if (is_neg_term(f)) { f = opposite_term(f); polarity = !polarity; } // explore f terms = learner->terms; switch (term_kind(terms, f)) { case EQ_TERM: a = eq_abstract_eq(learner, eq_term_desc(terms, f), polarity); break; case ITE_TERM: case ITE_SPECIAL: a = eq_abstract_ite(learner, ite_term_desc(terms, f), polarity); break; case OR_TERM: a = eq_abstract_or(learner, or_term_desc(terms, f), polarity); break; default: a = empty_epartition(&learner->manager); break; } cache_abstraction(learner, signed_term(f, polarity), a); } return a; }
/* * 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); }
/* * 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); }
static match_code_t match_term(context_t *ctx, term_t t, term_t *a, term_t *x) { composite_term_t *eq; term_table_t *terms; match_code_t code; term_t t1, t2; if (term_is_false(ctx, t)) { code = MATCH_FALSE; } else { code = MATCH_OTHER; terms = ctx->terms; switch (term_kind(terms, t)) { case OR_TERM: if (is_pos_term(t)) { code = MATCH_OR; } break; case EQ_TERM: eq = eq_term_desc(terms, t); t1 = intern_tbl_get_root(&ctx->intern, eq->arg[0]); t2 = intern_tbl_get_root(&ctx->intern, eq->arg[1]); if (is_boolean_term(terms, t1)) { assert(is_boolean_term(terms, t2)); /* * t is either (iff t1 t2) or (not (iff t1 t2)) * we rewrite (not (iff t1 t2)) to (iff t1 (not t2)) */ if (is_neg_term(t)) { t2 = opposite_term(t2); } /* * Check whether t1 or t2 is true or false */ if (term_is_true(ctx, t1)) { code = MATCH_IFF; *x = t2; } else if (term_is_false(ctx, t1)) { code = MATCH_IFF; *x = opposite_term(t2); } else if (term_is_true(ctx, t2)) { code = MATCH_IFF; *x = t1; } else if (term_is_false(ctx, t2)) { code = MATCH_IFF; *x = opposite_term(t1); } } else if (t1 != t2) { /* * t1 and t2 are not Boolean * if t1 and t2 are equal, we return MATCH_OTHER, since (eq t1 t2) is true */ assert(is_pos_term(t1) && is_pos_term(t2)); if (false_eq(terms, t1, t2)) { code = MATCH_FALSE; } else if (term_is_constant(terms, t1)) { *a = t1; *x = t2; code = MATCH_EQ; } else if (term_is_constant(terms, t2)) { *a = t2; *x = t1; code = MATCH_EQ; } } break; default: break; } } return code; }