br_status bool_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { SASSERT(f->get_family_id() == m().get_basic_family_id()); switch (f->get_decl_kind()) { case OP_EQ: case OP_IFF: SASSERT(num_args == 2); return mk_eq_core(args[0], args[1], result); case OP_DISTINCT: return mk_distinct_core(num_args, args, result); case OP_AND: return mk_and_core(num_args, args, result); case OP_OR: return mk_or_core(num_args, args, result); case OP_NOT: SASSERT(num_args == 1); return mk_not_core(args[0], result); case OP_ITE: SASSERT(num_args == 3); return mk_ite_core(args[0], args[1], args[2], result); case OP_IMPLIES: SASSERT(num_args == 2); mk_implies(args[0], args[1], result); return BR_DONE; case OP_XOR: SASSERT(num_args == 2); mk_xor(args[0], args[1], result); return BR_DONE; default: return BR_FAILED; } }
bool basic_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { set_reduce_invoked(); SASSERT(f->get_family_id() == m_manager.get_basic_family_id()); basic_op_kind k = static_cast<basic_op_kind>(f->get_decl_kind()); switch (k) { case OP_FALSE: case OP_TRUE: return false; case OP_EQ: SASSERT(num_args == 2); mk_eq(args[0], args[1], result); return true; case OP_DISTINCT: mk_distinct(num_args, args, result); return true; case OP_ITE: SASSERT(num_args == 3); mk_ite(args[0], args[1], args[2], result); return true; case OP_AND: mk_and(num_args, args, result); return true; case OP_OR: mk_or(num_args, args, result); return true; case OP_IMPLIES: mk_implies(args[0], args[1], result); return true; case OP_IFF: mk_iff(args[0], args[1], result); return true; case OP_XOR: mk_xor(args[0], args[1], result); return true; case OP_NOT: SASSERT(num_args == 1); mk_not(args[0], result); return true; default: UNREACHABLE(); return false; } }
/* * 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); }