void variable_intersection::populate_self(const app * a) { SASSERT(is_uninterp(a)); //TODO: optimize quadratic complexity //TODO: optimize number of checks when variable occurs multiple times unsigned arity = a->get_num_args(); for(unsigned i1=0; i1<arity; i1++) { expr * e1=a->get_arg(i1); if(is_var(e1)) { var* v1=to_var(e1); for(unsigned i2=i1+1; i2<arity; i2++) { expr * e2=a->get_arg(i2); if(!is_var(e2)) { continue; } var* v2=to_var(e2); if(v1->get_idx()==v2->get_idx()) { add_pair(i1, i2); } } } else { SASSERT(is_app(e1)); app * c1 = to_app(e1); SASSERT(c1->get_num_args()==0); //c1 must be a constant m_const_indexes.push_back(i1); m_consts.push_back(c1); SASSERT(m_const_indexes.size()==m_consts.size()); } } }
void mk_new_rule_tail(ast_manager & m, app * pred, var_idx_set const & non_local_vars, unsigned & next_idx, varidx2var_map & varidx2var, sort_ref_buffer & new_rule_domain, expr_ref_buffer & new_rule_args, app_ref & new_pred) { expr_ref_buffer new_args(m); unsigned n = pred->get_num_args(); for (unsigned i = 0; i < n; i++) { expr * arg = pred->get_arg(i); if (m.is_value(arg)) { new_args.push_back(arg); } else { SASSERT(is_var(arg)); int vidx = to_var(arg)->get_idx(); var * new_var = 0; if (!varidx2var.find(vidx, new_var)) { new_var = m.mk_var(next_idx, to_var(arg)->get_sort()); next_idx++; varidx2var.insert(vidx, new_var); if (non_local_vars.contains(vidx)) { // other predicates used this variable... so it should be in the domain of the filter new_rule_domain.push_back(to_var(arg)->get_sort()); new_rule_args.push_back(new_var); } } SASSERT(new_var != 0); new_args.push_back(new_var); } } new_pred = m.mk_app(pred->get_decl(), new_args.size(), new_args.c_ptr()); }
bool visit_children(expr * n, unsigned delta) { bool visited = true; unsigned dw; unsigned j; switch (n->get_kind()) { case AST_VAR: dw = m_window <= UINT_MAX - delta ? m_window + delta : UINT_MAX; if (to_var(n)->get_idx() >= delta && to_var(n)->get_idx() <= dw) m_contains = true; break; case AST_APP: j = to_app(n)->get_num_args(); while (j > 0) { --j; visit(to_app(n)->get_arg(j), delta, visited); } break; case AST_QUANTIFIER: if (delta <= UINT_MAX - to_quantifier(n)->get_num_decls()) { visit(to_quantifier(n)->get_expr(), delta + to_quantifier(n)->get_num_decls(), visited); } break; default: break; } return visited; }
/** \brief Find bounds of the form (<= x k) (<= (+ x (* -1 y)) k) (<= (+ x (* -1 t)) k) (<= (+ t (* -1 x)) k) x and y are a bound variables, t is a ground term and k is a numeral It also detects >=, and the atom can be negated. */ bool elim_bounds::is_bound(expr * n, var * & lower, var * & upper) { upper = 0; lower = 0; bool neg = false; if (m_manager.is_not(n)) { n = to_app(n)->get_arg(0); neg = true; } bool le = false; if (m_util.is_le(n)) { SASSERT(m_util.is_numeral(to_app(n)->get_arg(1))); n = to_app(n)->get_arg(0); le = true; } else if (m_util.is_ge(n)) { SASSERT(m_util.is_numeral(to_app(n)->get_arg(1))); n = to_app(n)->get_arg(0); le = false; } else { return false; } if (neg) le = !le; if (is_var(n)) { upper = to_var(n); } else if (m_util.is_add(n) && to_app(n)->get_num_args() == 2) { expr * arg1 = to_app(n)->get_arg(0); expr * arg2 = to_app(n)->get_arg(1); if (is_var(arg1)) upper = to_var(arg1); else if (!is_ground(arg1)) return false; rational k; bool is_int; if (m_util.is_mul(arg2) && m_util.is_numeral(to_app(arg2)->get_arg(0), k, is_int) && k.is_minus_one()) { arg2 = to_app(arg2)->get_arg(1); if (is_var(arg2)) lower = to_var(arg2); else if (!is_ground(arg2)) return false; // not supported } else { return false; // not supported } } else { return false; } if (!le) std::swap(upper, lower); return true; }
/** \brief Find bounds of the form (<= x k) (<= (+ x (* -1 y)) k) (<= (+ x (* -1 t)) k) (<= (+ t (* -1 x)) k) x and y are a bound variables, t is a ground term and k is a numeral It also detects >=, and the atom can be negated. */ bool elim_bounds_cfg::is_bound(expr * n, var * & lower, var * & upper) { upper = nullptr; lower = nullptr; bool neg = false; if (m.is_not(n)) { n = to_app(n)->get_arg(0); neg = true; } expr* l = nullptr, *r = nullptr; bool le = false; if (m_util.is_le(n, l, r) && m_util.is_numeral(r)) { n = l; le = true; } else if (m_util.is_ge(n, l, r) && m_util.is_numeral(r)) { n = l; le = false; } else { return false; } if (neg) le = !le; if (is_var(n)) { upper = to_var(n); } else if (m_util.is_add(n, l, r)) { expr * arg1 = l; expr * arg2 = r; if (is_var(arg1)) upper = to_var(arg1); else if (!is_ground(arg1)) return false; rational k; bool is_int; if (m_util.is_mul(arg2) && m_util.is_numeral(to_app(arg2)->get_arg(0), k, is_int) && k.is_minus_one()) { arg2 = to_app(arg2)->get_arg(1); if (is_var(arg2)) lower = to_var(arg2); else if (!is_ground(arg2)) return false; // not supported } else { return false; // not supported } } else { return false; } if (!le) std::swap(upper, lower); return true; }
bool matcher::operator()(expr * e1, expr * e2, substitution & s) { reset(); m_subst = &s; m_todo.push_back(expr_pair(e1, e2)); while (!m_todo.empty()) { expr_pair const & p = m_todo.back(); // if (m_cache.contains(p)) { // m_todo.pop_back(); // continue; // } if (is_var(p.first)) { expr_offset r; if (m_subst->find(to_var(p.first), 0, r)) { if (r.get_expr() != p.second) return false; } else { m_subst->insert(to_var(p.first), 0, expr_offset(p.second, 1)); } m_todo.pop_back(); continue; } if (is_var(p.second)) return false; if (!is_app(p.first)) return false; if (!is_app(p.second)) return false; app * n1 = to_app(p.first); app * n2 = to_app(p.second); if (n1->get_decl() != n2->get_decl()) return false; unsigned num_args1 = n1->get_num_args(); if (num_args1 != n2->get_num_args()) return false; m_todo.pop_back(); if (num_args1 == 0) continue; // m_cache.insert(p); unsigned j = num_args1; while (j > 0) { --j; m_todo.push_back(expr_pair(n1->get_arg(j), n2->get_arg(j))); } } return true; }
unsigned var_counter::get_max_var(bool& has_var) { has_var = false; unsigned max_var = 0; ptr_vector<quantifier> qs; while (!m_todo.empty()) { expr* e = m_todo.back(); m_todo.pop_back(); if (m_visited.is_marked(e)) { continue; } m_visited.mark(e, true); switch(e->get_kind()) { case AST_QUANTIFIER: { qs.push_back(to_quantifier(e)); break; } case AST_VAR: { if (to_var(e)->get_idx() >= max_var) { has_var = true; max_var = to_var(e)->get_idx(); } break; } case AST_APP: { app* a = to_app(e); for (unsigned i = 0; i < a->get_num_args(); ++i) { m_todo.push_back(a->get_arg(i)); } break; } default: UNREACHABLE(); break; } } m_visited.reset(); while (!qs.empty()) { var_counter aux_counter; quantifier* q = qs.back(); qs.pop_back(); aux_counter.m_todo.push_back(q->get_expr()); bool has_var1 = false; unsigned max_v = aux_counter.get_max_var(has_var1); if (max_v >= max_var + q->get_num_decls()) { max_var = max_v - q->get_num_decls(); has_var = has_var || has_var1; } } return max_var; }
bool fpa_util::contains_floats(ast * a) { switch (a->get_kind()) { case AST_APP: { app * aa = to_app(a); if (contains_floats(aa->get_decl())) return true; else for (unsigned i = 0; i < aa->get_num_args(); i++) if (contains_floats(aa->get_arg(i))) return true; break; } case AST_VAR: return contains_floats(to_var(a)->get_sort()); break; case AST_QUANTIFIER: { quantifier * q = to_quantifier(a); for (unsigned i = 0; i < q->get_num_children(); i++) if (contains_floats(q->get_child(i))) return true; for (unsigned i = 0; i < q->get_num_decls(); i++) if (contains_floats(q->get_decl_sort(i))) return true; if (contains_floats(q->get_expr())) return true; break; } case AST_SORT: { sort * s = to_sort(a); if (is_float(s) || is_rm(s)) return true; else { for (unsigned i = 0; i < s->get_num_parameters(); i++) { parameter const & pi = s->get_parameter(i); if (pi.is_ast() && contains_floats(pi.get_ast())) return true; } } break; } case AST_FUNC_DECL: { func_decl * f = to_func_decl(a); for (unsigned i = 0; i < f->get_arity(); i++) if (contains_floats(f->get_domain(i))) return true; if (contains_floats(f->get_range())) return true; for (unsigned i = 0; i < f->get_num_parameters(); i++) { parameter const & pi = f->get_parameter(i); if (pi.is_ast() && contains_floats(pi.get_ast())) return true; } break; } default: UNREACHABLE(); } return false; }
bool udoc_relation::is_var_range(expr* e, unsigned& hi, unsigned& lo, unsigned& v) const { udoc_plugin& p = get_plugin(); if (is_var(e)) { v = to_var(e)->get_idx(); hi = p.num_sort_bits(e)-1; lo = 0; return true; } expr* e2; if (p.bv.is_extract(e, lo, hi, e2) && is_var(e2)) { v = to_var(e2)->get_idx(); SASSERT(lo <= hi); return true; } return false; }
void mk_unbound_compressor::detect_tasks(unsigned rule_index) { rule * r = m_rules.get(rule_index); var_idx_set tail_vars; collect_tail_vars(m_manager, r, tail_vars); app * head = r->get_head(); func_decl * head_pred = head->get_decl(); if (m_context.is_output_predicate(head_pred)) { //we don't compress output predicates return; } unsigned n = head_pred->get_arity(); var_counter head_var_counter; head_var_counter.count_vars(m_manager, head, 1); for (unsigned i=0; i<n; i++) { expr * arg = head->get_arg(i); if (!is_var(arg)) { continue; } unsigned var_idx = to_var(arg)->get_idx(); if (!tail_vars.contains(var_idx)) { //unbound unsigned occurence_cnt = head_var_counter.get(var_idx); SASSERT(occurence_cnt>0); if (occurence_cnt == 1) { TRACE("dl", r->display(m_context, tout << "Compress: ");); add_task(head_pred, i); return; //we compress out the unbound arguments one by one }
void unifier::save_var(expr_offset const & p, expr_offset const & t) { expr * n = p.get_expr(); if (is_var(n)) { unsigned off = p.get_offset(); m_subst->insert(to_var(n)->get_idx(), off, t); } }
void mk_magic_sets::adornment::populate(app * lit, const var_idx_set & bound_vars) { SASSERT(empty()); unsigned arity = lit->get_num_args(); for (unsigned i = 0; i < arity; i++) { const expr * arg = lit->get_arg(i); bool bound = !is_var(arg) || bound_vars.contains(to_var(arg)->get_idx()); push_back(bound ? AD_BOUND : AD_FREE); } }
unsigned var_counter::get_max_var(bool& has_var) { has_var = false; unsigned max_var = 0; while (!m_todo.empty()) { expr* e = m_todo.back(); unsigned scope = m_scopes.back(); m_todo.pop_back(); m_scopes.pop_back(); if (m_visited.is_marked(e)) { continue; } m_visited.mark(e, true); switch(e->get_kind()) { case AST_QUANTIFIER: { quantifier* q = to_quantifier(e); m_todo.push_back(q->get_expr()); m_scopes.push_back(scope + q->get_num_decls()); break; } case AST_VAR: { if (to_var(e)->get_idx() >= scope + max_var) { has_var = true; max_var = to_var(e)->get_idx() - scope; } break; } case AST_APP: { app* a = to_app(e); for (unsigned i = 0; i < a->get_num_args(); ++i) { m_todo.push_back(a->get_arg(i)); m_scopes.push_back(scope); } break; } default: UNREACHABLE(); break; } } m_visited.reset(); return max_var; }
void operator()(var * v) { unsigned idx = to_var(v)->get_idx(); if (idx >= m_num_bindings) { warning_msg("free variables cannot be used in patterns."); m_result = false; return; } if (idx < m_num_new_bindings) { m_found_a_var = true; m_found_vars.insert(idx); } }
bool reduce_arg(expr* a, expr_ref& result) { sort* s = get_sort(a); if (!m_imp.is_fd(s)) { return false; } unsigned bv_size = get_bv_size(s); if (is_var(a)) { result = m.mk_var(to_var(a)->get_idx(), m_bv.mk_sort(bv_size)); return true; } SASSERT(is_app(a)); func_decl* f = to_app(a)->get_decl(); if (m_dt.is_constructor(f)) { unsigned idx = m_dt.get_constructor_idx(f); result = m_bv.mk_numeral(idx, bv_size); } else if (is_uninterp_const(a)) { func_decl* f_fresh; if (m_imp.m_enum2bv.find(f, f_fresh)) { result = m.mk_const(f_fresh); return true; } // create a fresh variable, add bounds constraints for it. unsigned nc = m_dt.get_datatype_num_constructors(s); result = m.mk_fresh_const(f->get_name().str().c_str(), m_bv.mk_sort(bv_size)); f_fresh = to_app(result)->get_decl(); if (!is_power_of_two(nc) || nc == 1) { m_imp.m_bounds.push_back(m_bv.mk_ule(result, m_bv.mk_numeral(nc-1, bv_size))); } expr_ref f_def(m); ptr_vector<func_decl> const& cs = *m_dt.get_datatype_constructors(s); f_def = m.mk_const(cs[nc-1]); for (unsigned i = nc - 1; i > 0; ) { --i; f_def = m.mk_ite(m.mk_eq(result, m_bv.mk_numeral(i,bv_size)), m.mk_const(cs[i]), f_def); } m_imp.m_enum2def.insert(f, f_def); m_imp.m_enum2bv.insert(f, f_fresh); m_imp.m_bv2enum.insert(f_fresh, f); m_imp.m_enum_consts.push_back(f); m_imp.m_enum_bvs.push_back(f_fresh); m_imp.m_enum_defs.push_back(f_def); } else { throw_non_fd(a); } ++m_imp.m_num_translated; return true; }
float mk_magic_sets::get_unbound_cost(app * lit, const var_idx_set & bound_vars) { func_decl * pred = lit->get_decl(); float res = 1; unsigned n = lit->get_num_args(); for (unsigned i = 0; i < n; i++) { const expr * arg = lit->get_arg(i); if (is_var(arg) && !bound_vars.contains(to_var(arg)->get_idx())) { res *= m_context.get_sort_size_estimate(pred->get_domain(i)); } //res-=1; } return res; }
unsigned get_bound_arg_count(app * lit, const var_idx_set & bound_vars) { unsigned res = 0; unsigned n = lit->get_num_args(); for (unsigned i = 0; i < n; i++) { const expr * arg = lit->get_arg(i); if (!is_var(arg) || bound_vars.contains(to_var(arg)->get_idx())) { SASSERT(is_var(arg) || is_app(arg)); SASSERT(!is_app(arg) || to_app(arg)->get_num_args()==0); res++; } } return res; }
bool mk_unbound_compressor::is_unbound_argument(rule * r, unsigned head_index) { app * head = r->get_head(); expr * head_arg = head->get_arg(head_index); if (!is_var(head_arg)) { return false; } unsigned var_idx = to_var(head_arg)->get_idx(); var_idx_set tail_vars; collect_tail_vars(m_manager, r, tail_vars); return tail_vars.contains(var_idx); }
void quick_checker::collector::collect_core(app * n, func_decl * p, unsigned i) { func_decl * f = n->get_decl(); unsigned num_args = n->get_num_args(); for (unsigned j = 0; j < num_args; j++) { expr * arg = n->get_arg(j); if (is_var(arg)) { unsigned idx = to_var(arg)->get_idx(); if (idx >= m_num_vars) return; if (m_already_found[idx] && m_conservative) { enode_set & s = m_candidates[idx]; enode_set & ns = m_tmp_candidates[idx]; if (s.empty()) continue; ns.reset(); enode_vector::const_iterator it = m_context.begin_enodes_of(f); enode_vector::const_iterator end = m_context.end_enodes_of(f); for (; it != end; ++it) { enode * curr = *it; if (m_context.is_relevant(curr) && curr->is_cgr() && check_arg(curr, p, i) && j < curr->get_num_args()) { enode * arg = curr->get_arg(j)->get_root(); // intersection if (s.contains(arg)) ns.insert(arg); } } SASSERT(m_conservative); s.swap(ns); } else { m_already_found[idx] = true; enode_set & s = m_candidates[idx]; enode_vector::const_iterator it = m_context.begin_enodes_of(f); enode_vector::const_iterator end = m_context.end_enodes_of(f); for (; it != end; ++it) { enode * curr = *it; if (m_context.is_relevant(curr) && curr->is_cgr() && check_arg(curr, p, i) && j < curr->get_num_args()) { enode * arg = curr->get_arg(j)->get_root(); s.insert(arg); } } } } else { if (n->get_family_id() != m_manager.get_basic_family_id()) collect(arg, n->get_decl(), j); else collect(arg, 0, 0); } } }
void get_expr_stat(expr * n, expr_stat & r) { typedef std::pair<expr *, unsigned> pair; buffer<pair> todo; todo.push_back(pair(n, 0)); while (!todo.empty()) { pair & p = todo.back(); n = p.first; unsigned depth = p.second; unsigned j; todo.pop_back(); r.m_sym_count++; if (depth > r.m_depth) r.m_depth = depth; switch (n->get_kind()) { case AST_APP: j = to_app(n)->get_num_args(); if (j == 0) r.m_const_count++; while (j > 0) { --j; todo.push_back(pair(to_app(n)->get_arg(j), depth + 1)); } break; case AST_VAR: if (to_var(n)->get_idx() > r.m_max_var_idx) r.m_max_var_idx = to_var(n)->get_idx(); r.m_ground = false; break; case AST_QUANTIFIER: todo.push_back(pair(to_quantifier(n)->get_expr(), depth+1)); break; default: UNREACHABLE(); } } }
/** \brief Decreate the balance of the given variable. */ inline void kbo::dec(expr_offset v) { int val; unsigned v_idx = to_var(v.get_expr())->get_idx(); unsigned offset = v.get_offset(); if (m_deltas.find(v_idx, offset, val)) { if (val == 0) m_num_neg++; else if (val == 1) m_num_pos--; m_deltas.insert(v_idx, offset, val - 1); } else { m_deltas.insert(v_idx, offset, -1); m_num_neg ++; } }
void mk_coalesce::extract_conjs(expr_ref_vector const& sub, rule const& rl, expr_ref& result) { obj_map<expr, unsigned> indices; bool_rewriter bwr(m); rule_ref r(const_cast<rule*>(&rl), rm); ptr_vector<sort> sorts; expr_ref_vector revsub(m), conjs(m); rl.get_vars(sorts); revsub.resize(sorts.size()); svector<bool> valid(sorts.size(), true); for (unsigned i = 0; i < sub.size(); ++i) { expr* e = sub[i]; sort* s = m.get_sort(e); expr_ref w(m.mk_var(i, s), m); if (is_var(e)) { unsigned v = to_var(e)->get_idx(); SASSERT(v < valid.size()); if (sorts[v]) { SASSERT(s == sorts[v]); if (valid[v]) { revsub[v] = w; valid[v] = false; } else { SASSERT(revsub[v].get()); SASSERT(m.get_sort(revsub[v].get()) == s); conjs.push_back(m.mk_eq(revsub[v].get(), w)); } } } else { SASSERT(m.is_value(e)); SASSERT(m.get_sort(e) == m.get_sort(w)); conjs.push_back(m.mk_eq(e, w)); } } for (unsigned i = 0; i < sorts.size(); ++i) { if (valid[i] && sorts[i] && !revsub[i].get()) { revsub[i] = m.mk_var(m_idx++, sorts[i]); } } var_subst vs(m, false); for (unsigned i = r->get_uninterpreted_tail_size(); i < r->get_tail_size(); ++i) { vs(r->get_tail(i), revsub.size(), revsub.c_ptr(), result); conjs.push_back(result); } bwr.mk_and(conjs.size(), conjs.c_ptr(), result); }
/** \brief Increase the balance of the given variable. */ inline void kbo::inc(expr_offset v) { SASSERT(is_var(v.get_expr())); int val; unsigned v_idx = to_var(v.get_expr())->get_idx(); unsigned offset = v.get_offset(); if (m_deltas.find(v_idx, offset, val)) { if (val == -1) m_num_neg--; else if (val == 0) m_num_pos++; m_deltas.insert(v_idx, offset, val + 1); } else { m_deltas.insert(v_idx, offset, 1); m_num_pos ++; } }
bool kbo::VWBc(expr_offset t, expr_offset target_var) { SASSERT(target_var.get_expr() == 0 || is_var(target_var.get_expr())); svector<expr_offset> & todo = m_vwbc_todo; expr_offset s; bool found = false; unsigned j; SASSERT(todo.empty()); todo.push_back(t); while (!todo.empty()) { t = todo.back(); if (t == target_var) found = true; expr * n = t.get_expr(); unsigned offset = t.get_offset(); todo.pop_back(); switch (n->get_kind()) { case AST_VAR: if (m_subst && m_subst->find(to_var(n), offset, s)) todo.push_back(s); else if (pos) { inc(t); m_weight_balance += var_weight(); } else { dec(t); m_weight_balance -= var_weight(); } break; case AST_APP: if (pos) m_weight_balance += f_weight(to_app(n)->get_decl()); else m_weight_balance -= f_weight(to_app(n)->get_decl()); j = to_app(n)->get_num_args(); while (j > 0) { --j; todo.push_back(expr_offset(to_app(n)->get_arg(j), offset)); } break; default: UNREACHABLE(); break; } } return found; }
bool is_well_formed_vars(ptr_vector<sort>& bound, expr* e) { ptr_vector<expr> todo; ast_mark mark; todo.push_back(e); while (!todo.empty()) { expr* e = todo.back(); todo.pop_back(); if (mark.is_marked(e)) { continue; } mark.mark(e, true); if (is_quantifier(e)) { quantifier* q = to_quantifier(e); unsigned depth = q->get_num_decls(); bound.append(depth, q->get_decl_sorts()); if (!is_well_formed_vars(bound, q->get_expr())) { return false; } bound.resize(bound.size()-depth); } else if (is_app(e)) { app* a = to_app(e); for (unsigned i = 0; i < a->get_num_args(); ++i) { todo.push_back(a->get_arg(i)); } } else if (is_var(e)) { var* v = to_var(e); unsigned index = v->get_idx(); sort* s = v->get_sort(); SASSERT(index < bound.size()); index = bound.size()-1-index; if (!bound[index]) { bound[index] = s; } if (bound[index] != s) { return false; } } else { UNREACHABLE(); } } return true; }
/** \brief Return true if \c e is of the form (not (= VAR t)) or (not (iff VAR t)) or (iff VAR t) or (iff (not VAR) t) or (VAR IDX) or (not (VAR IDX)). The last case can be viewed */ bool der::is_var_diseq(expr * e, unsigned num_decls, var * & v, expr_ref & t) { // (not (= VAR t)) and (not (iff VAR t)) cases if (m_manager.is_not(e) && (m_manager.is_eq(to_app(e)->get_arg(0)) || m_manager.is_iff(to_app(e)->get_arg(0)))) { app * eq = to_app(to_app(e)->get_arg(0)); SASSERT(m_manager.is_eq(eq) || m_manager.is_iff(eq)); expr * lhs = eq->get_arg(0); expr * rhs = eq->get_arg(1); if (!is_var(lhs, num_decls) && !is_var(rhs, num_decls)) return false; if (!is_var(lhs, num_decls)) std::swap(lhs, rhs); SASSERT(is_var(lhs, num_decls)); // Remark: Occurs check is not necessary here... the top-sort procedure will check for cycles... // if (occurs(lhs, rhs)) { // return false; // } v = to_var(lhs); t = rhs; TRACE("der", tout << mk_pp(e, m_manager) << "\n";);
void aig_exporter::collect_var_substs(substitution& subst, const app *h, const expr_ref_vector& vars, expr_ref_vector& eqs) { for (unsigned i = 0; i < h->get_num_args(); ++i) { expr *arg = h->get_arg(i); expr *latchvar = get_latch_var(i, vars); if (is_var(arg)) { var *v = to_var(arg); expr_offset othervar; if (subst.find(v, 0, othervar)) { eqs.push_back(m.mk_eq(latchvar, othervar.get_expr())); } else { subst.insert(v, 0, expr_offset(latchvar, 0)); } } else { eqs.push_back(m.mk_eq(latchvar, arg)); } } }
enode * checker::get_enode_eq_to(expr * n) { if (is_var(n)) { unsigned idx = to_var(n)->get_idx(); if (idx >= m_num_bindings) return 0; return m_bindings[m_num_bindings - idx - 1]; } if (m_context.e_internalized(n) && m_context.is_relevant(n)) return m_context.get_enode(n); if (!is_app(n) || to_app(n)->get_num_args() == 0) return 0; enode * r = 0; if (n->get_ref_count() > 1 && m_to_enode_cache.find(n, r)) return r; r = get_enode_eq_to_core(to_app(n)); if (n->get_ref_count() > 1) m_to_enode_cache.insert(n, r); return r; }
/** \brief Return true if \c n is an application of the form (f x_{k_1}, ..., x_{k_n}) where f is uninterpreted n == num_decls x_{k_i}'s are variables and {k_1, ..., k_n } is equals to the set {0, ..., num_decls-1} */ bool macro_util::is_macro_head(expr * n, unsigned num_decls) const { if (is_app(n) && !to_app(n)->get_decl()->is_associative() && to_app(n)->get_family_id() == null_family_id && to_app(n)->get_num_args() == num_decls) { sbuffer<int> var2pos; var2pos.resize(num_decls, -1); for (unsigned i = 0; i < num_decls; i++) { expr * c = to_app(n)->get_arg(i); if (!is_var(c)) return false; unsigned idx = to_var(c)->get_idx(); if (idx >= num_decls || var2pos[idx] != -1) return false; var2pos[idx] = i; } return true; } return false; }
void output_predicate(context & ctx, app * f, std::ostream & out) { func_decl * pred_decl = f->get_decl(); unsigned arity = f->get_num_args(); out << pred_decl->get_name() << '('; for (unsigned i = 0; i < arity; i++) { expr * arg = f->get_arg(i); if (i != 0) { out << ','; } if (is_var(arg)) { out << "#" << to_var(arg)->get_idx(); } else { out << mk_pp(arg, ctx.get_manager()); } } out << ")"; }