#include "nlsat/nlsat_variable_ordering_strategy.h" namespace nlsat { struct vos_var_info_collector::imp { pmanager & pm; atom_vector const & m_atoms; unsigned num_vars; Variable_Ordering_Strategy_Type m_vos_type; /** Maximum degree of this variable. */ unsigned_vector m_max_degree; /** Sum of degrees of this variable within all polynomials. */ unsigned_vector m_sum_poly_degree; /** Number of polynomials that contain this variable. */ unsigned_vector m_num_polynomials; /** Maximum degree of the leading coefficient of this variable. */ unsigned_vector m_max_lc_degree; /** Maximum of total degrees of terms that contain this variable. */ unsigned_vector m_max_terms_tdegree; /** Sum of degrees of this variable within all terms. */ unsigned_vector m_sum_term_degree; /** Number of terms that contain this variable. */ unsigned_vector m_num_terms; unsigned_vector m_num_uni; numeral_vector m_coeffs; imp(pmanager & _pm, atom_vector const & atoms, unsigned _num_vars, unsigned _vos_type): pm(_pm), m_atoms(atoms), num_vars(_num_vars), m_vos_type(Variable_Ordering_Strategy_Type(_vos_type)) { m_max_degree.resize(num_vars, 0); m_sum_poly_degree.resize(num_vars, 0); m_num_polynomials.resize(num_vars, 0); if (m_vos_type != ONLYPOLY) { m_max_lc_degree.resize(num_vars, 0); m_max_terms_tdegree.resize(num_vars, 0); m_sum_term_degree.resize(num_vars, 0); m_num_terms.resize(num_vars, 0); m_num_uni.resize(num_vars, 0); m_coeffs.resize(num_vars, 0); } } void collect(monomial * m) { unsigned mdeg = 0; for (unsigned i = 0, sz = pm.size(m); i < sz; ++i) { var x = pm.get_var(m, i); mdeg += pm.degree_of(m, x); ++m_num_terms[x]; } for (unsigned i = 0, sz = pm.size(m); i < sz; ++i) { var x = pm.get_var(m, i); m_sum_term_degree[x] += mdeg; if (mdeg > m_max_terms_tdegree[x]) m_max_terms_tdegree[x] = mdeg; unsigned lc_deg = mdeg - pm.degree_of(m, x); if (lc_deg > m_max_lc_degree[x]) m_max_lc_degree[x] = lc_deg; } } void collect(poly * p) { var_vector vec_vars; pm.vars(p, vec_vars); if (m_vos_type == UNIVARIATE) { if (vec_vars.size() == 1) ++m_num_uni[vec_vars[0]]; } for (unsigned i = 0, sz = vec_vars.size(); i < sz; ++i) { var x = vec_vars[i]; unsigned k = pm.degree(p, x); ++m_num_polynomials[x]; m_sum_poly_degree[x] += k; if (k > m_max_degree[x]) m_max_degree[x] = k; if (m_vos_type == FEATURE){ for (unsigned kl = 0; kl <= k; kl++) { scoped_numeral curr(pm.m()); if (pm.const_coeff(p, x, kl, curr)) { pm.m().abs(curr); if (pm.m().gt(curr, m_coeffs[x])) { pm.m().set(m_coeffs[x], curr); } } } } } if (m_vos_type != ONLYPOLY && m_vos_type != UNIVARIATE){ for (unsigned i = 0, sz = pm.size(p); i < sz; ++i) { collect(pm.get_monomial(p, i)); } } } void collect(literal l) { bool_var b = l.var(); atom * a = m_atoms[b]; if (a == nullptr) return; if (a->is_ineq_atom()) { unsigned sz = to_ineq_atom(a)->size(); for (unsigned i = 0; i < sz; i++) { collect(to_ineq_atom(a)->p(i)); } } else { collect(to_root_atom(a)->p()); } } void collect(clause const & c) { unsigned sz = c.size(); for (unsigned i = 0; i < sz; i++) collect(c[i]); } void collect(clause_vector const & cs) { unsigned sz = cs.size(); for (unsigned i = 0; i < sz; i++) collect(*(cs[i])); } struct univariate_reorder_lt { vos_var_info_collector::imp const *m_info; univariate_reorder_lt(vos_var_info_collector::imp const *info):m_info(info) {} bool operator()(var x, var y) const { if (m_info->m_num_uni[x] != m_info->m_num_uni[y]) return m_info->m_num_uni[x] > m_info->m_num_uni[y]; return x < y; } }; struct feature_reorder_lt { vos_var_info_collector::imp const *m_info; feature_reorder_lt(vos_var_info_collector::imp const * info): m_info(info){} bool operator()(var x, var y) const { if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) return m_info->m_max_degree[x] > m_info->m_max_degree[y]; if (m_info->m_max_terms_tdegree[x] != m_info->m_max_terms_tdegree[y]) return m_info->m_max_terms_tdegree[x] > m_info->m_max_terms_tdegree[y]; if (!m_info->pm.m().eq(m_info->m_coeffs[x], m_info->m_coeffs[y])) { return m_info->pm.m().lt(m_info->m_coeffs[x], m_info->m_coeffs[y]); } return x < y; } }; struct brown_reorder_lt { vos_var_info_collector::imp const *m_info; brown_reorder_lt(vos_var_info_collector::imp const *info):m_info(info) {} bool operator()(var x, var y) const { // if (a.max_degree != b.max_degree) // return a.max_degree > b.max_degree; // if (a.max_terms_tdegree != b.max_terms_tdegree) // return a.max_terms_tdegree > b.max_terms_tdegree; // return a.num_terms > b.num_terms; if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) return m_info->m_max_degree[x] > m_info->m_max_degree[y]; if (m_info->m_max_terms_tdegree[x] != m_info->m_max_terms_tdegree[y]) return m_info->m_max_terms_tdegree[x] > m_info->m_max_terms_tdegree[y]; if (m_info->m_num_terms[x] != m_info->m_num_terms[y]) return m_info->m_num_terms[x] > m_info->m_num_terms[y]; return x < y; } }; struct triangular_reorder_lt { const vos_var_info_collector::imp *m_info; triangular_reorder_lt(vos_var_info_collector::imp const *info):m_info(info) {} bool operator()(var x, var y) const { // if (a.max_degree != b.max_degree) // return a.max_degree > b.max_degree; // if (a.max_lc_degree != b.max_lc_degree) // return a.max_lc_degree > b.max_lc_degree; // return a.sum_poly_degree > b.sum_poly_degree; if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) return m_info->m_max_degree[x] > m_info->m_max_degree[y]; if (m_info->m_max_lc_degree[x] != m_info->m_max_lc_degree[y]) return m_info->m_max_lc_degree[x] > m_info->m_max_lc_degree[y]; if (m_info->m_sum_poly_degree[x] != m_info->m_sum_poly_degree[y]) return m_info->m_sum_poly_degree[x] > m_info->m_sum_poly_degree[y]; return x < y; } }; struct onlypoly_reorder_lt { const vos_var_info_collector::imp *m_info; onlypoly_reorder_lt(vos_var_info_collector::imp const *info):m_info(info) {} bool operator()(var x, var y) const { // high degree first if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) return m_info->m_max_degree[x] > m_info->m_max_degree[y]; // if (m_info->m_sum_poly_degree[x] != m_info->m_sum_poly_degree[y]) return m_info->m_sum_poly_degree[x] > m_info->m_sum_poly_degree[y]; // more constrained first if (m_info->m_num_polynomials[x] != m_info->m_num_polynomials[y]) return m_info->m_num_polynomials[x] > m_info->m_num_polynomials[y]; return x < y; } }; bool check_invariant() const {return true;} // what is the invariant void operator()(var_vector &perm) { var_vector new_order; for (var x = 0; x < num_vars; x++) { new_order.push_back(x); } if (m_vos_type == BROWN) { std::sort(new_order.begin(), new_order.end(), brown_reorder_lt(this)); } else if (m_vos_type == TRIANGULAR) { std::sort(new_order.begin(), new_order.end(), triangular_reorder_lt(this)); } else if (m_vos_type == ONLYPOLY) { std::sort(new_order.begin(), new_order.end(), onlypoly_reorder_lt(this)); } else if(m_vos_type == UNIVARIATE){ std::sort(new_order.begin(), new_order.end(), univariate_reorder_lt(this)); } else if(m_vos_type == FEATURE){ std::sort(new_order.begin(), new_order.end(), feature_reorder_lt(this)); } else { UNREACHABLE(); } TRACE(reorder, tout << "new order: "; for (unsigned i = 0; i < num_vars; i++) tout << new_order[i] << " "; tout << "\n"; ); perm.resize(num_vars, 0); for (var x = 0; x < num_vars; x++) { perm[new_order[x]] = x; } SASSERT(check_invariant()); } // std::ostream& display(std::ostream & out, display_var_proc const & proc) { // unsigned sz = m_num_occs.size(); // for (unsigned i = 0; i < sz; i++) { // proc(out, i); out << " -> " << m_max_degree[i] << " : " << m_num_occs[i] << "\n"; // } // return out; // } // std::ostream& display(std::ostream & out, display_var_proc const & proc) { // for (unsigned i = 0; i < num_vars; ++i) { // proc(out, i); out << " -> " << m_max_degree[i] << " : " << m_sum_poly_degree[i] << "\n"; // } // return out; // } }; vos_var_info_collector::vos_var_info_collector(pmanager & _pm, atom_vector const & _atoms, unsigned _num_vars, unsigned _vos_type) { m_imp = alloc(imp, _pm, _atoms, _num_vars, _vos_type); } vos_var_info_collector::~vos_var_info_collector() { dealloc(m_imp); } void vos_var_info_collector::collect(clause_vector const & cs) { m_imp->collect(cs); } void vos_var_info_collector::operator()(var_vector &perm) { m_imp->operator()(perm); } }