bool mk_subsumption_checker::transform_rule(rule * r, 
        rule_subsumption_index& subs_index, rule_ref & res)
    {
        unsigned u_len = r->get_uninterpreted_tail_size();
        unsigned len = r->get_tail_size();
        if(u_len==0) {
            res = r;
            return true;
        }
        app_ref head(r->get_head(), m);

        app_ref_vector tail(m);
        svector<bool> tail_neg;

        for(unsigned i=0; i<u_len; i++) {
            app * tail_atom = r->get_tail(i);
            bool neg = r->is_neg_tail(i);
            if(m_total_relations.contains(tail_atom->get_decl())
                || subs_index.is_subsumed(tail_atom)) {
                if(neg) {
                    //rule contains negated total relation, this means that it is unsatisfiable 
                    //and can be removed
                    return false;
                }
                else {
                    //we remove total relations from the tail
                    continue;
                }
            }
            if(!neg && head.get()==tail_atom) {
                //rule contains its head positively in the tail, therefore 
                //it will never add any new facts to the relation, so it 
                //can be removed
                return false;
            }
            tail.push_back(tail_atom);
            tail_neg.push_back(neg);
        }

        if(tail.size()==u_len) {
            res = r;
            return true;
        }

        //we just copy the interpreted part of the tail
        for(unsigned i=u_len; i<len; i++) {
            tail.push_back(r->get_tail(i));
            tail_neg.push_back(r->is_neg_tail(i));
        }

        SASSERT(tail.size()==tail_neg.size());
        res = m_context.get_rule_manager().mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr());
        res->set_accounting_parent_object(m_context, r);
        m_context.get_rule_manager().fix_unbound_vars(res, true);
        m_context.get_rule_manager().mk_rule_rewrite_proof(*r, *res.get());

        return true;
    }
    void mk_interp_tail_simplifier::rule_substitution::get_result(rule_ref & res) {
        SASSERT(m_rule);

        apply(m_rule->get_head(), m_head);

        m_tail.reset();
        m_neg.reset();

        unsigned tail_len = m_rule->get_tail_size();
        for (unsigned i=0; i<tail_len; i++) {
            app_ref new_tail_el(m);
            apply(m_rule->get_tail(i), new_tail_el);
            m_tail.push_back(new_tail_el);
            m_neg.push_back(m_rule->is_neg_tail(i));
        }

        mk_rule_inliner::remove_duplicate_tails(m_tail, m_neg);

        SASSERT(m_tail.size() == m_neg.size());
        res = m_context.get_rule_manager().mk(m_head, m_tail.size(), m_tail.c_ptr(), m_neg.c_ptr(),m_rule->name());
        res->set_accounting_parent_object(m_context, m_rule);
        res->norm_vars(res.get_manager());
    }