inline void kbo::VWB(expr_offset t, unsigned idx) { expr_offset null(0, 0); app * n = to_app(t.get_expr()); unsigned num = n->get_num_args(); for (; idx < num; idx++) VWBc<pos>(expr_offset(n->get_arg(idx), t.get_offset()), null); }
/** \brief Check whether the variable in t1 occurs in t2. */ bool lpo::occurs(expr_offset const & t1, expr_offset const & t2) { SASSERT(is_var(t1.get_expr())); if (is_ground(t2.get_expr())) return false; m_todo.reset(); m_todo.push_back(t2); while (!m_todo.empty()) { expr_offset t = m_todo.back(); m_todo.pop_back(); t = find(t); expr * n = t.get_expr(); if (is_ground(n)) continue; unsigned offset = t.get_offset(); unsigned j; switch (n->get_kind()) { case AST_VAR: if (t == t1) return true; break; case AST_APP: j = to_app(n)->get_num_args(); while (j > 0) { --j; expr * arg = to_app(n)->get_arg(j); if (!is_ground(arg)) m_todo.push_back(expr_offset(arg, offset)); } break; default: UNREACHABLE(); } } return false; }
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; }
/** \brief Return true if s >_{lpo} t_i forall children t_i of t. */ bool lpo::dominates_args(expr_offset s, expr_offset t, unsigned depth) { SASSERT(is_app(t.get_expr())); unsigned num_args = to_app(t.get_expr())->get_num_args(); unsigned off = t.get_offset(); for (unsigned i = 0; i < num_args; i++) { expr * t_i = to_app(t.get_expr())->get_arg(i); if (!greater(s, expr_offset(t_i, off), depth+1)) return false; } return true; }
/** \brief Return true if s_i >=_{lpo} t for some arg s_i of s. */ bool lpo::arg_dominates_expr(expr_offset s, expr_offset t, unsigned depth) { SASSERT(is_app(s.get_expr())); unsigned num_args = to_app(s.get_expr())->get_num_args(); unsigned off = s.get_offset(); for (unsigned i = 0; i < num_args; i++) { expr * s_i = to_app(s.get_expr())->get_arg(i); result r = compare(expr_offset(s_i, off), t, depth+1); if (r == EQUAL || r == GREATER) return true; } return false; }
void tst_match(ast_manager & m, app * t, app * i) { substitution s(m); s.reserve(2, 10); // reserving a big number of variables to be safe. matcher match; std::cout << "Is " << mk_pp(i, m) << " an instance of " << mk_pp(t, m) << "\n"; if (match(t, i, s)) { std::cout << "yes\n"; s.display(std::cout); } else { std::cout << "no\n"; } s.reset(); if (t->get_decl() == i->get_decl()) { // trying to match the arguments of t and i std::cout << "Are the arguments of " << mk_pp(i, m) << " an instance of the arguments of " << mk_pp(t, m) << "\n"; unsigned num_args = t->get_num_args(); unsigned j; for (j = 0; j < num_args; j++) { if (!match(t->get_arg(j), i->get_arg(j), s)) break; } if (j == num_args) { std::cout << "yes\n"; s.display(std::cout); // create some dummy term to test for applying the substitution. sort_ref S( m.mk_uninterpreted_sort(symbol("S")), m); sort * domain[3] = {S, S, S}; func_decl_ref r( m.mk_func_decl(symbol("r"), 3, domain, S), m); expr_ref x1( m.mk_var(0, S), m); expr_ref x2( m.mk_var(1, S), m); expr_ref x3( m.mk_var(2, S), m); app_ref rxyzw( m.mk_app(r, x1.get(), x2.get(), x3.get()), m); expr_ref result(m); unsigned deltas[2] = {0,0}; s.apply(2, deltas, expr_offset(rxyzw, 0), result); std::cout << "applying substitution to\n" << mk_pp(rxyzw,m) << "\nresult:\n" << mk_pp(result,m) << "\n"; } else { std::cout << "no\n"; } } std::cout << "\n"; }
order::result lpo::lex_compare(expr_offset s, expr_offset t, unsigned depth) { SASSERT(is_app(s.get_expr())); SASSERT(is_app(t.get_expr())); app * _s = to_app(s.get_expr()); app * _t = to_app(t.get_expr()); unsigned num_args1 = _s->get_num_args(); unsigned num_args2 = _t->get_num_args(); unsigned num_args = std::min(num_args1, num_args2); unsigned off1 = s.get_offset(); unsigned off2 = t.get_offset(); result r = EQUAL; for (unsigned i = 0; i < num_args; i++) { r = compare(expr_offset(_s->get_arg(i), off1), expr_offset(_t->get_arg(i), off2), depth+1); if (r != EQUAL) break; } if (r == EQUAL) { if (num_args1 > num_args2) return GREATER; if (num_args1 < num_args2) return NOT_GTEQ; } return r; }
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; }
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)); } } }
order::result kbo::compare(expr_offset const & t1, expr_offset const & t2, substitution * s) { reset(); m_subst = s; if (t1 == t2) return EQUAL; expr * n1 = t1.get_expr(); expr * n2 = t2.get_expr(); // f(s) >_{kbo} f(t) iff s >_{kbo} t while (is_unary_app(n1) && is_unary_app(n2) && to_app(n1)->get_decl() == to_app(n2)->get_decl()) { n1 = to_app(n1)->get_arg(0); n2 = to_app(n2)->get_arg(0); } svector<entry> & todo = m_compare_todo; SASSERT(todo.empty()); todo.push_back(entry(find(expr_offset(n1, t1.get_offset())), find(expr_offset(n2, t2.get_offset())), 0)); result res = UNKNOWN; while (!todo.empty()) { entry & e = todo.back(); expr_offset t1 = e.m_t1; expr_offset t2 = e.m_t2; expr * n1 = t1.get_expr(); expr * n2 = t2.get_expr(); TRACE("kbo", tout << "processing with idx: " << e.m_idx << "\n" << mk_pp(n1, m_manager) << "\n" << mk_pp(n2, m_manager) << "\n"; tout << "wb : " << m_weight_balance << "\n";); SASSERT(!is_quantifier(n1) && !is_quantifier(n2)); bool v1 = is_var(n1); bool v2 = is_var(n2); if (v1 && v2) { todo.pop_back(); inc(t1); dec(t2); res = t1 == t2 ? EQUAL : UNCOMPARABLE; } else if (v1) { todo.pop_back(); res = VWBc<false>(t2, t1) ? LESSER : UNCOMPARABLE; inc(t1); m_weight_balance += var_weight(); } else if (v2) { todo.pop_back(); res = VWBc<true>(t1, t2) ? GREATER : UNCOMPARABLE; dec(t2); m_weight_balance -= var_weight(); } else { func_decl * f = to_app(n1)->get_decl(); func_decl * g = to_app(n2)->get_decl(); result lex; if (f != g || to_app(n1)->get_num_args() != to_app(n2)->get_num_args()) { VWB<true>(t1, 0); VWB<false>(t2, 0); lex = UNCOMPARABLE; } else { unsigned & idx = e.m_idx; // when idx > 0, res contains the result for child (idx - 1) if (idx > 0 && res != EQUAL) { VWB<true>(t1, idx); VWB<false>(t2, idx); lex = res; } else if (idx == to_app(n1)->get_num_args()) { // all children were visited lex = EQUAL; } else if (idx < to_app(n1)->get_num_args()) { expr_offset c1 = find(expr_offset(to_app(n1)->get_arg(idx), t1.get_offset())); expr_offset c2 = find(expr_offset(to_app(n2)->get_arg(idx), t2.get_offset())); idx++; // move curr entry child idx entry new_entry(c1, c2, 0); todo.push_back(new_entry); continue; // process child before continuing } } todo.pop_back(); m_weight_balance += f_weight(f); m_weight_balance -= f_weight(g); if (m_weight_balance > 0) res = no_neg(); else if (m_weight_balance < 0) res = no_pos(); else if (f_greater(f, g)) res = no_neg(); else if (f_greater(g, f)) res = no_pos(); else if (f != g) res = UNCOMPARABLE; else if (lex == EQUAL) res = EQUAL; else if (lex == GREATER) res = no_neg(); else if (lex == LESSER) res = no_pos(); else res = UNCOMPARABLE; } TRACE("kbo", tout << "result: " << res << "\n";);