/*++ Copyright (c) 2017 Microsoft Corporation Module Name: Abstract: Author: Nikolaj Bjorner (nbjorner) Lev Nachmanson (levnach) Revision History: --*/ #pragma once #include "util/rational.h" #include "util/lp/monomial.h" namespace nla { struct factorization_factory; typedef unsigned lpvar; enum class factor_type { VAR, RM }; // RM stands for rooted monomial class factor { unsigned m_index; factor_type m_type; public: factor() {} explicit factor(unsigned j) : factor(j, factor_type::VAR) {} factor(unsigned i, factor_type t) : m_index(i), m_type(t) {} unsigned index() const { return m_index; } unsigned& index() { return m_index; } factor_type type() const { return m_type; } factor_type& type() { return m_type; } bool is_var() const { return m_type == factor_type::VAR; } bool operator==(factor const& other) const { return m_index == other.index() && m_type == other.type(); } bool operator!=(factor const& other) const { return m_index != other.index() || m_type != other.type(); } }; class factorization { vector m_vars; const monomial* m_mon; public: factorization(const monomial* m): m_mon(m) { if (m != nullptr) { for(lpvar j : *m) m_vars.push_back(factor(j, factor_type::VAR)); } } bool is_mon() const { return m_mon != nullptr;} bool is_empty() const { return m_vars.empty(); } factor operator[](unsigned k) const { return m_vars[k]; } size_t size() const { return m_vars.size(); } const factor* begin() const { return m_vars.begin(); } const factor* end() const { return m_vars.end(); } void push_back(factor v) { SASSERT(!is_mon()); m_vars.push_back(v); } const monomial* mon() const { return m_mon; } }; struct const_iterator_mon { // fields svector m_mask; const factorization_factory * m_ff; bool m_full_factorization_returned; // typedefs typedef const_iterator_mon self_type; typedef factorization value_type; typedef int difference_type; typedef std::forward_iterator_tag iterator_category; void init_vars_by_the_mask(unsigned_vector & k_vars, unsigned_vector & j_vars) const; bool get_factors(factor& k, factor& j, rational& sign) const; factorization operator*() const; void advance_mask(); self_type operator++(); self_type operator++(int); const_iterator_mon(const svector& mask, const factorization_factory *f); bool operator==(const self_type &other) const; bool operator!=(const self_type &other) const; factorization create_binary_factorization(factor j, factor k) const; factorization create_full_factorization(const monomial*) const; }; struct factorization_factory { const svector& m_vars; const monomial* m_monomial; // returns true if found virtual bool find_rm_monomial_of_vars(const svector& vars, unsigned& i) const = 0; virtual const monomial* find_monomial_of_vars(const svector& vars) const = 0; factorization_factory(const svector& vars, const monomial* m) : m_vars(vars), m_monomial(m) { } svector get_mask() const { // we keep the last element always in the first factor to avoid // repeating a pair twice, that is why m_mask is shorter by one then m_vars return m_vars.size() != 2? svector(m_vars.size() - 1, false) : svector(1, true); // init mask as in the end() since the full iteration will do the job } const_iterator_mon begin() const { return const_iterator_mon(get_mask(), this); } const_iterator_mon end() const { svector mask(m_vars.size() - 1, true); auto it = const_iterator_mon(mask, this); it.m_full_factorization_returned = true; return it; } }; }