Skip to content

Commit 832cfb3

Browse files
committed
consolidate throttling
1 parent f320667 commit 832cfb3

File tree

5 files changed

+148
-0
lines changed

5 files changed

+148
-0
lines changed

src/math/lp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ z3_add_component(lp
3434
nla_powers.cpp
3535
nla_solver.cpp
3636
nla_tangent_lemmas.cpp
37+
nla_throttle.cpp
3738
nra_solver.cpp
3839
permutation_matrix.cpp
3940
random_updater.cpp

src/math/lp/nla_core.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ core::core(lp::lar_solver& s, params_ref const& p, reslimit & lim) :
3737
m_horner(this),
3838
m_grobner(this),
3939
m_emons(m_evars),
40+
m_throttle(lra.trail()),
4041
m_use_nra_model(false),
4142
m_nra(s, m_nra_lim, *this)
4243
{
4344
m_nlsat_delay_bound = lp_settings().nlsat_delay();
45+
m_throttle.set_enabled(m_params.arith_nl_thrl());
4446
lra.m_find_monics_with_changed_bounds_func = [&](const indexed_uint_set& columns_with_changed_bounds) {
4547
for (lpvar j : columns_with_changed_bounds) {
4648
if (is_monic_var(j))

src/math/lp/nla_core.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "math/lp/nla_intervals.h"
2929
#include "nlsat/nlsat_solver.h"
3030
#include "params/smt_params_helper.hpp"
31+
#include "math/lp/nla_throttle.h"
3132

3233
namespace nra {
3334
class solver;
@@ -102,6 +103,9 @@ class core {
102103
lpvar m_patched_var = 0;
103104
monic const* m_patched_monic = nullptr;
104105

106+
nla_throttle m_throttle;
107+
bool m_throttle_enabled = true;
108+
105109

106110

107111
void check_weighted(unsigned sz, std::pair<unsigned, std::function<void(void)>>* checks);
@@ -432,6 +436,11 @@ class core {
432436
void add_fixed_equality(lp::lpvar v, rational const& k, lp::explanation const& e) { m_fixed_equalities.push_back({v, k, e}); }
433437
void add_equality(lp::lpvar i, lp::lpvar j, lp::explanation const& e) { m_equalities.push_back({i, j, e}); }
434438

439+
void set_throttle_enabled(bool enabled) { m_throttle_enabled = enabled; m_throttle.set_enabled(enabled); }
440+
bool throttle_enabled() const { return m_throttle_enabled; }
441+
nla_throttle& throttle() { return m_throttle; }
442+
const nla_throttle& throttle() const { return m_throttle; }
443+
435444
}; // end of core
436445

437446
struct pp_mon {

src/math/lp/nla_throttle.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*++
2+
Copyright (c) 2017 Microsoft Corporation
3+
4+
Author:
5+
Lev Nachmanson (levnach)
6+
7+
--*/
8+
#include "math/lp/nla_throttle.h"
9+
#include "util/trace.h"
10+
11+
namespace nla {
12+
13+
bool nla_throttle::insert_new_impl(const signature& sig) {
14+
if (m_seen.contains(sig)) {
15+
TRACE(nla_solver, tout << "throttled lemma generation\n";);
16+
return true; // Already seen, throttle
17+
}
18+
19+
m_seen.insert(sig);
20+
m_trail.push(insert_map(m_seen, sig));
21+
return false; // New, don't throttle
22+
}
23+
24+
} // namespace nla

src/math/lp/nla_throttle.h

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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

Comments
 (0)