diff --git a/src/math/lp/nla_order_lemmas.cpp b/src/math/lp/nla_order_lemmas.cpp index 159a02a5d..b07e8a331 100644 --- a/src/math/lp/nla_order_lemmas.cpp +++ b/src/math/lp/nla_order_lemmas.cpp @@ -111,6 +111,28 @@ bool order::throttle_monic(const monic& ac, std::string const & debug_location ) return false; } +bool order::throttle_mon_ol(const monic& ac, lpvar a, const rational& c_sign, lpvar c_var, + const monic& bd, const factor& b, const rational& d_sign, + lpvar d, llc ab_cmp, const std::string& debug_location) { + // Check if throttling is enabled + if (!c().params().arith_nl_thrl()) + return false; + + // Create the key for this specific generate_mon_ol invocation + mon_ol_key key(ac.var(), a, c_sign, c_var, bd.var(), b.var(), d_sign, d, ab_cmp); + + // Check if this combination has already been processed + if (m_processed_mon_ol.contains(key)) { + TRACE(nla_solver, tout << "throttled generate_mon_ol at " << debug_location << "\n";); + return true; + } + + // Mark this combination as processed and add to trail for backtracking + m_processed_mon_ol.insert(key); + c().trail().push(insert_map(m_processed_mon_ol, key)); + return false; +} + // We look for monics e = m.rvars()[k]*d and see if we can create an order lemma for m and e void order::order_lemma_on_factor_binomial_explore(const monic& ac, bool k) { TRACE(nla_solver, tout << "ac = " << pp_mon_with_vars(c(), ac);); @@ -187,6 +209,10 @@ void order::generate_mon_ol(const monic& ac, SASSERT(ab_cmp != llc::LT || (var_val(ac) >= var_val(bd) && val(a)*c_sign < val(b)*d_sign)); SASSERT(ab_cmp != llc::GT || (var_val(ac) <= var_val(bd) && val(a)*c_sign > val(b)*d_sign)); + // Check if this specific combination should be throttled + if (throttle_mon_ol(ac, a, c_sign, c, bd, b, d_sign, d, ab_cmp, __FUNCTION__)) + return; + lemma_builder lemma(_(), __FUNCTION__); lemma |= ineq(term(c_sign, c), llc::LE, 0); lemma &= c; // this explains c == +- d diff --git a/src/math/lp/nla_order_lemmas.h b/src/math/lp/nla_order_lemmas.h index dba858c82..20fa35bce 100644 --- a/src/math/lp/nla_order_lemmas.h +++ b/src/math/lp/nla_order_lemmas.h @@ -20,6 +20,50 @@ public: order(core *c) : common(c) {} void order_lemma(); + // Structure to represent the key parameters for throttling generate_mon_ol + struct mon_ol_key { + lpvar ac_var; + lpvar a; + rational c_sign; + lpvar c; + lpvar bd_var; + lpvar b_var; + rational d_sign; + lpvar d; + llc ab_cmp; + + // Default constructor for hashtable + mon_ol_key() : ac_var(0), a(0), c_sign(0), c(0), bd_var(0), b_var(0), d_sign(0), d(0), ab_cmp(llc::EQ) {} + + mon_ol_key(lpvar ac_var, lpvar a, const rational& c_sign, lpvar c, + lpvar bd_var, lpvar b_var, const rational& d_sign, lpvar d, llc ab_cmp) + : ac_var(ac_var), a(a), c_sign(c_sign), c(c), bd_var(bd_var), + b_var(b_var), d_sign(d_sign), d(d), ab_cmp(ab_cmp) {} + + bool operator==(const mon_ol_key& other) const { + return ac_var == other.ac_var && a == other.a && c_sign == other.c_sign && + c == other.c && bd_var == other.bd_var && b_var == other.b_var && + d_sign == other.d_sign && d == other.d && ab_cmp == other.ab_cmp; + } + }; + + struct mon_ol_key_hash { + unsigned operator()(const mon_ol_key& k) const { + return combine_hash(combine_hash(combine_hash(combine_hash( + combine_hash(combine_hash(combine_hash(combine_hash( + static_cast(k.ac_var), static_cast(k.a)), + k.c_sign.hash()), static_cast(k.c)), + static_cast(k.bd_var)), static_cast(k.b_var)), + k.d_sign.hash()), static_cast(k.d)), + static_cast(k.ab_cmp)); + } + }; + + hashtable> m_processed_mon_ol; + bool throttle_mon_ol(const monic& ac, lpvar a, const rational& c_sign, lpvar c_var, + const monic& bd, const factor& b, const rational& d_sign, + lpvar d, llc ab_cmp, const std::string& debug_location); + int_hashtable> m_processed_monics; bool throttle_monic(const monic&, const std::string & debug_location); private: