|
| 1 | +/*++ |
| 2 | + Copyright (c) 2017 Microsoft Corporation |
| 3 | +
|
| 4 | + Author: |
| 5 | + Lev Nachmanson (levnach) |
| 6 | +
|
| 7 | + --*/ |
| 8 | +#pragma once |
| 9 | +#include "math/lp/nla_defs.h" |
| 10 | +#include "util/hashtable.h" |
| 11 | +#include "util/trail.h" |
| 12 | +#include <cstring> |
| 13 | + |
| 14 | +namespace nla { |
| 15 | + |
| 16 | +class nla_throttle { |
| 17 | +public: |
| 18 | + enum throttle_kind { |
| 19 | + ORDER_LEMMA, // order lemma (9 params) |
| 20 | + BINOMIAL_SIGN_LEMMA, // binomial sign (5 params) |
| 21 | + MONOTONE_LEMMA // monotonicity (2 params) |
| 22 | + }; |
| 23 | + |
| 24 | +private: |
| 25 | + struct signature { |
| 26 | + unsigned m_values[8]; |
| 27 | + |
| 28 | + signature() { |
| 29 | + std::memset(m_values, 0, sizeof(m_values)); |
| 30 | + } |
| 31 | + |
| 32 | + bool operator==(const signature& other) const { |
| 33 | + return std::memcmp(m_values, other.m_values, sizeof(m_values)) == 0; |
| 34 | + } |
| 35 | + }; |
| 36 | + |
| 37 | + struct signature_hash { |
| 38 | + unsigned operator()(const signature& s) const { |
| 39 | + unsigned hash = 0; |
| 40 | + for (int i = 0; i < 8; i++) { |
| 41 | + hash = combine_hash(hash, s.m_values[i]); |
| 42 | + } |
| 43 | + return hash; |
| 44 | + } |
| 45 | + }; |
| 46 | + |
| 47 | + hashtable<signature, signature_hash, default_eq<signature>> m_seen; |
| 48 | + trail_stack& m_trail; |
| 49 | + bool m_enabled = true; |
| 50 | + |
| 51 | +public: |
| 52 | + nla_throttle(trail_stack& trail) : m_trail(trail) {} |
| 53 | + |
| 54 | + void set_enabled(bool enabled) { m_enabled = enabled; } |
| 55 | + bool enabled() const { return m_enabled; } |
| 56 | + |
| 57 | + // Monotone lemma: mvar + is_lt |
| 58 | + bool insert_new(throttle_kind k, lpvar mvar, bool is_lt) { |
| 59 | + if (!m_enabled) return false; |
| 60 | + signature sig; |
| 61 | + sig.m_values[0] = static_cast<unsigned>(k); |
| 62 | + sig.m_values[1] = static_cast<unsigned>(mvar); |
| 63 | + sig.m_values[2] = static_cast<unsigned>(is_lt); |
| 64 | + return insert_new_impl(sig); |
| 65 | + } |
| 66 | + |
| 67 | + // Binomial sign: xy_var + x + y + sign + sy |
| 68 | + bool insert_new(throttle_kind k, lpvar xy_var, lpvar x, lpvar y, int sign, int sy) { |
| 69 | + if (!m_enabled) return false; |
| 70 | + signature sig; |
| 71 | + sig.m_values[0] = static_cast<unsigned>(k); |
| 72 | + sig.m_values[1] = static_cast<unsigned>(xy_var); |
| 73 | + sig.m_values[2] = static_cast<unsigned>(x); |
| 74 | + sig.m_values[3] = static_cast<unsigned>(y); |
| 75 | + sig.m_values[4] = normalize_sign(sign); |
| 76 | + sig.m_values[5] = normalize_sign(sy); |
| 77 | + return insert_new_impl(sig); |
| 78 | + } |
| 79 | + |
| 80 | + // Order lemma: ac_var + a + c_sign + c + bd_var + b_var + d_sign + d + ab_cmp |
| 81 | + bool insert_new(throttle_kind k, lpvar ac_var, lpvar a, const rational& c_sign, lpvar c, |
| 82 | + lpvar bd_var, lpvar b_var, const rational& d_sign, lpvar d, llc ab_cmp) { |
| 83 | + if (!m_enabled) return false; |
| 84 | + signature sig; |
| 85 | + sig.m_values[0] = static_cast<unsigned>(k); |
| 86 | + sig.m_values[1] = static_cast<unsigned>(ac_var); |
| 87 | + sig.m_values[2] = static_cast<unsigned>(a); |
| 88 | + sig.m_values[3] = pack_rational_sign(c_sign); |
| 89 | + sig.m_values[4] = static_cast<unsigned>(c); |
| 90 | + sig.m_values[5] = static_cast<unsigned>(bd_var); |
| 91 | + sig.m_values[6] = static_cast<unsigned>(b_var); |
| 92 | + // Pack d_sign, d, and ab_cmp into the last slot |
| 93 | + sig.m_values[7] = (pack_rational_sign(d_sign) << 24) | |
| 94 | + ((static_cast<unsigned>(d) & 0xFFFF) << 8) | |
| 95 | + (static_cast<unsigned>(ab_cmp) & 0xFF); |
| 96 | + return insert_new_impl(sig); |
| 97 | + } |
| 98 | + |
| 99 | +private: |
| 100 | + bool insert_new_impl(const signature& sig); |
| 101 | + |
| 102 | + // Helper functions for packing values |
| 103 | + static unsigned pack_rational_sign(const rational& r) { |
| 104 | + return r.is_pos() ? 1 : (r.is_neg() ? 255 : 0); |
| 105 | + } |
| 106 | + |
| 107 | + static unsigned normalize_sign(int sign) { |
| 108 | + return static_cast<unsigned>(sign + 127); |
| 109 | + } |
| 110 | +}; |
| 111 | + |
| 112 | +} |
0 commit comments