void mk_magic_sets::create_magic_rules(app * head, unsigned tail_cnt, app * const * tail, bool const* negated, rule_set& result) { //TODO: maybe include relevant interpreted predicates from the original rule ptr_vector<app> new_tail; svector<bool> negations; new_tail.push_back(create_magic_literal(head)); new_tail.append(tail_cnt, tail); negations.push_back(false); negations.append(tail_cnt, negated); for (unsigned i=0; i<tail_cnt; i++) { if (m_extentional.contains(tail[i]->get_decl())) { continue; } app * mag_head = create_magic_literal(tail[i]); rule * r = m_context.get_rule_manager().mk(mag_head, i+1, new_tail.c_ptr(), negations.c_ptr()); TRACE("dl", r->display(m_context,tout); ); result.add_rule(r); }
void mk_unfold::expand_tail(rule& r, unsigned tail_idx, rule_set const& src, rule_set& dst) { SASSERT(tail_idx <= r.get_uninterpreted_tail_size()); if (tail_idx == r.get_uninterpreted_tail_size()) { dst.add_rule(&r); } else { func_decl* p = r.get_decl(tail_idx); rule_vector const& p_rules = src.get_predicate_rules(p); rule_ref new_rule(rm); for (unsigned i = 0; i < p_rules.size(); ++i) { rule const& r2 = *p_rules[i]; if (m_unify.unify_rules(r, tail_idx, r2) && m_unify.apply(r, tail_idx, r2, new_rule)) { expr_ref_vector s1 = m_unify.get_rule_subst(r, true); expr_ref_vector s2 = m_unify.get_rule_subst(r2, false); resolve_rule(rm, r, r2, tail_idx, s1, s2, *new_rule.get()); expand_tail(*new_rule.get(), tail_idx+r2.get_uninterpreted_tail_size(), src, dst); } } } }
bool mk_subsumption_checker::transform_rules(const rule_set & orig, rule_set & tgt) { bool modified = false; func_decl_set total_relations_with_included_rules; rule_subsumption_index subs_index(m_context); rule_ref_vector orig_rules(m_context.get_rule_manager()); orig_rules.append(orig.get_num_rules(), orig.begin()); rule * * rbegin = orig_rules.c_ptr(); rule * * rend = rbegin + orig_rules.size(); //before traversing we sort rules so that the shortest are in the beginning. //this will help make subsumption checks more efficient std::sort(rbegin, rend, rule_size_comparator); for(rule_set::iterator rit = rbegin; rit!=rend; ++rit) { rule * r = *rit; func_decl * head_pred = r->get_decl(); if(m_total_relations.contains(head_pred)) { if(!orig.is_output_predicate(head_pred) || total_relations_with_included_rules.contains(head_pred)) { //We just skip definitions of total non-output relations as //we'll eliminate them from the problem. //We also skip rules of total output relations for which we have //already output the rule which implies their totality. modified = true; continue; } rule * defining_rule; VERIFY(m_total_relation_defining_rules.find(head_pred, defining_rule)); if (defining_rule) { rule_ref totality_rule(m_context.get_rule_manager()); VERIFY(transform_rule(defining_rule, subs_index, totality_rule)); if(defining_rule!=totality_rule) { modified = true; } tgt.add_rule(totality_rule); SASSERT(totality_rule->get_decl()==head_pred); } else { modified = true; } total_relations_with_included_rules.insert(head_pred); continue; } rule_ref new_rule(m_context.get_rule_manager()); if(!transform_rule(r, subs_index, new_rule)) { modified = true; continue; } if(m_new_total_relation_discovery_during_transformation && is_total_rule(new_rule)) { on_discovered_total_relation(head_pred, new_rule.get()); } if(subs_index.is_subsumed(new_rule)) { modified = true; continue; } if(new_rule.get()!=r) { modified = true; } tgt.add_rule(new_rule); subs_index.add(new_rule); } tgt.inherit_predicates(orig); TRACE("dl", tout << "original set size: "<<orig.get_num_rules()<<"\n" << "reduced set size: "<<tgt.get_num_rules()<<"\n"; );