/*++ Copyright (c) 2006 Microsoft Corporation Module Name: dl_rule_transformer.cpp Abstract: Author: Krystof Hoder (t-khoder) 2010-09-20. Revision History: --*/ #include #include #include "muz/base/dl_context.h" #include "muz/base/dl_rule_transformer.h" #include "util/stopwatch.h" namespace datalog { rule_transformer::rule_transformer(context & ctx) : m_context(ctx), m_rule_manager(m_context.get_rule_manager()), m_dirty(false) { } rule_transformer::~rule_transformer() { reset(); } void rule_transformer::reset() { for (auto* p : m_plugins) dealloc(p); m_plugins.reset(); m_dirty = false; } void rule_transformer::cancel() { for (auto* p : m_plugins) p->cancel(); } struct rule_transformer::plugin_comparator { bool operator()(rule_transformer::plugin * p1, rule_transformer::plugin * p2) { return p1->get_priority() > p2->get_priority(); } }; void rule_transformer::ensure_ordered() { if (m_dirty) { std::sort(m_plugins.begin(), m_plugins.end(), plugin_comparator()); m_dirty = false; } } void rule_transformer::register_plugin(plugin * p) { m_plugins.push_back(p); p->attach(*this); m_dirty = true; } bool rule_transformer::operator()(rule_set & rules) { ensure_ordered(); bool modified = false; TRACE("dl_rule_transf", tout<<"init:\n"; rules.display(tout); ); scoped_ptr new_rules = alloc(rule_set, rules); plugin_vector::iterator it = m_plugins.begin(); plugin_vector::iterator end = m_plugins.end(); for(; it!=end && !m_context.canceled(); ++it) { plugin & p = **it; IF_VERBOSE(1, verbose_stream() << "(transform " << typeid(p).name() << "...";); stopwatch sw; sw.start(); scoped_ptr new_rules1 = p(*new_rules); sw.stop(); double sec = sw.get_seconds(); if (sec < 0.001) sec = 0.0; if (!new_rules1) { IF_VERBOSE(1, verbose_stream() << "no-op " << sec << "s)\n";); continue; } if (p.can_destratify_negation() && !new_rules1->is_closed() && !new_rules1->close()) { warning_msg("a rule transformation skipped " "because it destratified negation"); new_rules1 = nullptr; IF_VERBOSE(1, verbose_stream() << "no-op " << sec << "s)\n";); continue; } modified = true; new_rules = new_rules1.detach(); new_rules->ensure_closed(); IF_VERBOSE(1, verbose_stream() << new_rules->get_num_rules() << " rules " << sec << "s)\n";); TRACE("dl_rule_transf", tout << typeid(p).name()<<":\n"; new_rules->display(tout); ); } if (modified) { rules.replace_rules(*new_rules); } return modified; } //------------------------------ // //rule_transformer::plugin // //------------------------------ void rule_transformer::plugin::remove_duplicate_tails(app_ref_vector& tail, bool_vector& tail_neg) { //one set for positive and one for negative obj_hashtable tail_apps[2]; unsigned i=0; while(i