/*++ Copyright (c) 2017 Microsoft Corporation Author: Lev Nachmanson (levnach) Nikolaj Bjorner (nbjorner) --*/ #include "util/vector.h" #include "math/lp/factorization.h" namespace nla { void const_iterator_mon::init_vars_by_the_mask(unsigned_vector & k_vars, unsigned_vector & j_vars) const { // the last element for m_factorization.m_rooted_vars goes to k_vars SASSERT(m_mask.size() + 1 == m_ff->m_vars.size()); k_vars.push_back(m_ff->m_vars.back()); for (unsigned j = 0; j < m_mask.size(); j++) { if (m_mask[j]) k_vars.push_back(m_ff->m_vars[j]); else j_vars.push_back(m_ff->m_vars[j]); } } // todo : do we need the sign? bool const_iterator_mon::get_factors(factor& k, factor& j, rational& sign) const { unsigned_vector k_vars; unsigned_vector j_vars; init_vars_by_the_mask(k_vars, j_vars); SASSERT(!k_vars.empty() && !j_vars.empty()); std::sort(k_vars.begin(), k_vars.end()); std::sort(j_vars.begin(), j_vars.end()); if (m_num_failures > 1000) { for (bool& m : m_mask) m = true; m_mask[0] = false; m_full_factorization_returned = true; return false; } if (k_vars.size() == 1) k.set(k_vars[0], factor_type::VAR); else { unsigned i; if (!m_ff->find_canonical_monic_of_vars(k_vars, i)) { ++m_num_failures; return false; } k.set(i, factor_type::MON); } m_num_failures = 0; if (j_vars.size() == 1) j.set(j_vars[0], factor_type::VAR); else { unsigned i; if (!m_ff->find_canonical_monic_of_vars(j_vars, i)) { ++m_num_failures; return false; } j.set(i, factor_type::MON); } return true; } factorization const_iterator_mon::operator*() const { if (!m_full_factorization_returned) { return create_full_factorization(m_ff->m_monic); } factor j, k; rational sign; if (!get_factors(j, k, sign)) return factorization(nullptr); return create_binary_factorization(j, k); } void const_iterator_mon::advance_mask() { if (!m_full_factorization_returned) { m_full_factorization_returned = true; return; } for (bool& m : m_mask) { if (m) { m = false; } else { m = true; break; } } } const_iterator_mon::self_type const_iterator_mon::operator++() { self_type i = *this; operator++(1); return i; } const_iterator_mon::self_type const_iterator_mon::operator++(int) { advance_mask(); return *this; } const_iterator_mon::const_iterator_mon(const bool_vector& mask, const factorization_factory *f) : m_mask(mask), m_ff(f) , m_full_factorization_returned(false) {} bool const_iterator_mon::operator!=(const const_iterator_mon::self_type &other) const { return m_full_factorization_returned != other.m_full_factorization_returned || m_mask != other.m_mask; } factorization const_iterator_mon::create_binary_factorization(factor j, factor k) const { factorization f(nullptr); f.push_back(j); f.push_back(k); // Let m by *m_ff->m_monic, the monic we factorize // We have canonize_sign(m)*m.vars() = m.rvars() // Let s = canonize_sign(f). Then we have f[0]*f[1] = s*m.rvars() // s*canonize_sign(m)*val(m). // Therefore val(m) = sign*val((f[0])*val(f[1]), where sign = canonize_sign(f)*canonize_sign(m). // We apply this sign to the first factor. f[0].sign() ^= (m_ff->canonize_sign(f)^m_ff->canonize_sign(*m_ff->m_monic)); return f; } factorization const_iterator_mon::create_full_factorization(const monic* m) const { if (m != nullptr) return factorization(m); factorization f(nullptr); for (lpvar j : m_ff->m_vars) { f.push_back(factor(j, factor_type::VAR)); } return f; } }