/*++ Copyright (c) 2017 Microsoft Corporation Module Name: Abstract: Author: Lev Nachmanson (levnach) Revision History: --*/ #pragma once #include #include "math/lp/numeric_pair.h" #include "util/debug.h" #include #include template std::ostream& print_vector(const C & t, std::ostream & out) { for (const auto & p : t) out << p << " "; return out; } template bool contains(const C & collection, const D & key) { return collection.find(key) != collection.end(); } template std::ostream& print_vector(const C * t, unsigned size, std::ostream & out) { for (unsigned i = 0; i < size; i++ ) out << t[i] << " "; out << std::endl; return out; } template bool try_get_value(const std::unordered_map & map, const A& key, B & val) { const auto it = map.find(key); if (it == map.end()) return false; val = it->second; return true; } template bool contains(const std::unordered_map & map, const A& key) { return map.find(key) != map.end(); } #ifdef Z3DEBUG #define Z3DEBUG 1 #endif namespace lp { template bool is_non_decreasing(const K& v) { auto a = v.begin(); if (a == v.end()) return true; // v is empty auto b = v.begin(); b++; for (; b != v.end(); a++, b++) { if (*a > *b) return false; } return true; } template std::ostream& print_linear_combination_customized(const vector> & coeffs, std::function var_str, std::ostream & out) { bool first = true; for (const auto & it : coeffs) { T val = it.first; if (first) { first = false; if (val.is_neg()) { out << "- "; val = -val; } } else { if (val.is_pos()) { out << " + "; } else { out << " - "; val = -val; } } if (val == 1) out << " "; else { out << T_to_string(val); } out << var_str(it.second); } return out; } template std::ostream& print_linear_combination_of_column_indices_only(const vector> & coeffs, std::ostream & out) { return print_linear_combination_customized( coeffs, [](unsigned j) {std::stringstream ss; ss << "v" << j; return ss.str();}, out); } template std::ostream& print_linear_combination_indices_only(const T & coeffs, std::ostream & out) { vector> cfs; for (const auto & it : coeffs) { cfs.push_back(std::make_pair(it.coeff(), it.var())); } return print_linear_combination_of_column_indices_only(cfs, out); } inline void throw_exception(std::string && str) { throw default_exception(std::move(str)); } typedef z3_exception exception; #define lp_assert(_x_) { SASSERT(_x_); } inline void lp_unreachable() { lp_assert(false); } template inline X zero_of_type() { return numeric_traits::zero(); } template inline X one_of_type() { return numeric_traits::one(); } template inline bool is_zero(const X & v) { return numeric_traits::is_zero(v); } template inline bool is_pos(const X & v) { return numeric_traits::is_pos(v); } template inline bool is_neg(const X & v) { return numeric_traits::is_neg(v); } template inline bool is_integer(const X & v) { return numeric_traits::is_int(v); } template inline X ceil_ratio(const X & a, const X & b) { return numeric_traits::ceil_ratio(a, b); } template inline X floor_ratio(const X & a, const X & b) { return numeric_traits::floor_ratio(a, b); } template inline bool precise() { return numeric_traits::precise(); } // returns true if a factor of b template bool is_proper_factor(const T & a, const T & b) { if (a.size() >= b.size()) return false; SASSERT(lp::is_non_decreasing(a) && lp::is_non_decreasing(b)); auto i = a.begin(); auto j = b.begin(); while (true) { if (i == a.end()) { return true; } if (j == b.end()) { return false; } if (*i == *j) { i++;j++; continue; } j++; } } // b / a, where a is a factor of b and both vectors are sorted template svector vector_div(const T & b, const T & a) { SASSERT(lp::is_non_decreasing(a)); SASSERT(lp::is_non_decreasing(b)); SASSERT(is_proper_factor(a, b)); svector r; auto i = a.begin(); auto j = b.begin(); while (true) { if (j == b.end()) { break; } if (i == a.end()) { r.push_back(*j); j++; continue; } if (*i == *j) { i++;j++; continue; } r.push_back(*j); j++; } return r; } } // namespace lp namespace std { template<> struct hash { inline size_t operator()(const rational & v) const { return v.hash(); } }; } template inline void hash_combine(std::size_t & seed, const T & v) { seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } namespace std { template struct hash> { inline size_t operator()(const pair & v) const { size_t seed = 0; hash_combine(seed, v.first); hash_combine(seed, v.second); return seed; } }; template<> struct hash> { inline size_t operator()(const lp::numeric_pair & v) const { size_t seed = 0; hash_combine(seed, v.x); hash_combine(seed, v.y); return seed; } }; inline void intersect_set(std::unordered_set& p, const std::unordered_set& w) { for (auto it = p.begin(); it != p.end(); ) { auto iit = it; iit ++; if (w.find(*it) == w.end()) p.erase(it); it = iit; } } }