/* * Convert term t to a conditional; store the result in d * - d is reset first * - t must be a valid term defined in d->terms * - if t is not an if-then-else term, the result is * d->nconds = 0 * d->defval = t * - if t is (ite c a b) then the conversion depends on whether * a or b is an if-then-else term. */ void convert_term_to_conditional(conditional_t *d, term_t t) { composite_term_t *ite; term_t a, b; if (is_ite_term(d->terms, t)) { ite = ite_term_desc(d->terms, t); assert(ite->arity == 3); a = ite->arg[1]; b = ite->arg[2]; if (is_neg_term(t)) { a = opposite_term(a); b = opposite_term(b); } convert_ite_to_conditional(d, ite->arg[0], ite->arg[1], ite->arg[2]); } else { reset_conditional(d); d->defval = t; } }
/* * 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); }
/* * Convert (if c a b) to a conditional */ void convert_ite_to_conditional(conditional_t *d, term_t c, term_t a, term_t b) { composite_term_t *ite; term_t t, c1, t1, t2; reset_conditional(d); if (is_ite_term(d->terms, b)) { /* * b is either (ite c1 ...) or (not (ite c1 ...). * * we normalize to (ite c1 t1 t2): * - if b is (ite c1 t1 t2) we're done * - if b is (not (ite c1 u1 u2)) we push the negation inside: * so t1 := (not u1) and t2 := (not u2) */ ite = ite_term_desc(d->terms, b); assert(ite->arity == 3); c1 = ite->arg[0]; t1 = ite->arg[1]; t2 = ite->arg[2]; if (is_neg_term(b)) { t1 = opposite_term(t1); t2 = opposite_term(t2); } /* * we try to build the conditional * [c --> a, c1 --> t1, else --> t2] if c and c1 are disjoint * or [c --> a, not c1 --> t2, else --> t1] if c and not c1 are disjoint */ if (incompatible_boolean_terms(d->terms, c, c1)) { conditional_add_pair(d, c, a); conditional_add_pair(d, c1, t1); t = t2; goto loop; } if (incompatible_boolean_terms(d->terms, c, opposite_term(c1))) { conditional_add_pair(d, c, a); conditional_add_pair(d, opposite_term(c1), t2); t = t1; goto loop; } } if (is_ite_term(d->terms, a)) { /* * a is either (ite c1 ...) or (not (ite c1 ...)) * we normalize as above to (ite c1 t1 t2) */ ite = ite_term_desc(d->terms, a); assert(ite->arity == 3); c1 = ite->arg[0]; t1 = ite->arg[1]; t2 = ite->arg[2]; if (is_neg_term(a)) { t1 = opposite_term(t1); t2 = opposite_term(t2); } /* * we try * [not c --> b, c1 --> t1, else --> t2] * or [not c --> b, not c1 --> t2, else --> t1] */ if (incompatible_boolean_terms(d->terms, opposite_term(c), c1)) { conditional_add_pair(d, opposite_term(c), b); conditional_add_pair(d, c1, t1); t = t2; goto loop; } if (incompatible_boolean_terms(d->terms, opposite_term(c), opposite_term(c1))) { conditional_add_pair(d, opposite_term(c), b); conditional_add_pair(d, opposite_term(c1), t2); t = t1; goto loop; } } // Default: found no disjoint conditions conditional_add_pair(d, c, a); d->defval = b; return; // t is the 'else part' loop: while (is_ite_term(d->terms, t)) { // t is (ite c1 t1 t2) ite = ite_term_desc(d->terms, t); assert(ite->arity == 3); c1 = ite->arg[0]; t1 = ite->arg[1]; t2 = ite->arg[2]; if (is_neg_term(t)) { t1 = opposite_term(t1); t2 = opposite_term(t2); } if (disjoint_condition(d, c1)) { conditional_add_pair(d, c1, t1); t = t2; } else if (disjoint_condition(d, opposite_term(c1))) { conditional_add_pair(d, opposite_term(c1), t2); t = t1; } else { break; } } d->defval = t; }
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; }