mirror of
https://github.com/Z3Prover/z3
synced 2026-05-16 15:15:35 +00:00
lll_cube: exponential delay throttle on bail
Mirrors the nla_grobner pattern. State on int_solver:👿
m_lll_cube_delay - ticks to skip
m_lll_cube_delay_base - current penalty size, doubles on bail
(capped at 1024), decrements on success
After each bail the next |delay_base| invocations are short-circuited
in should_find_lll_cube(). Eliminates the bail-tighten feedback loop
that turned plain-cube wins into timeouts on instances such as
rings/ring_2exp14_7vars_4ite_unsat (22.8s -> 1.3s) and
cut_lemmas/20-vars/cut_lemma_03_011 (timeout -> 8.3s).
Adds stat 'arith-lll-cube-throttled' for visibility.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
da9c720542
commit
8da9fc9779
2 changed files with 35 additions and 3 deletions
|
|
@ -45,7 +45,10 @@ namespace lp {
|
|||
dioph_eq m_dio;
|
||||
int_gcd_test m_gcd;
|
||||
unsigned m_initial_dio_calls_period;
|
||||
|
||||
unsigned m_lll_cube_delay = 0;
|
||||
unsigned m_lll_cube_delay_base = 0;
|
||||
static const unsigned LLL_CUBE_DELAY_CAP = 1024;
|
||||
|
||||
bool column_is_int_inf(unsigned j) const {
|
||||
return lra.column_is_int(j) && (!lia.value_is_int(j));
|
||||
}
|
||||
|
|
@ -201,7 +204,32 @@ namespace lp {
|
|||
unsigned period = settings().m_int_find_lll_cube_period;
|
||||
if (period == 0)
|
||||
return false;
|
||||
return m_number_of_calls % period == 0;
|
||||
if (m_number_of_calls % period != 0)
|
||||
return false;
|
||||
if (m_lll_cube_delay > 0) {
|
||||
--m_lll_cube_delay;
|
||||
settings().stats().m_lll_cube_throttled++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// After int_cube_lll fires we record the outcome here so the next
|
||||
// invocation gate (should_find_lll_cube) can back off when the
|
||||
// heuristic keeps bailing on an unchanged-looking state.
|
||||
void on_lll_cube_result(lia_move r) {
|
||||
if (r == lia_move::sat) {
|
||||
if (m_lll_cube_delay_base > 0)
|
||||
--m_lll_cube_delay_base;
|
||||
m_lll_cube_delay = 0;
|
||||
return;
|
||||
}
|
||||
// bail: grow the penalty exponentially up to the cap.
|
||||
if (m_lll_cube_delay_base == 0)
|
||||
m_lll_cube_delay_base = 1;
|
||||
else if (m_lll_cube_delay_base < LLL_CUBE_DELAY_CAP)
|
||||
m_lll_cube_delay_base = std::min(m_lll_cube_delay_base * 2u, LLL_CUBE_DELAY_CAP);
|
||||
m_lll_cube_delay = m_lll_cube_delay_base;
|
||||
}
|
||||
|
||||
bool should_gomory_cut() {
|
||||
|
|
@ -255,8 +283,10 @@ namespace lp {
|
|||
if (r == lia_move::undef) r = patch_basic_columns();
|
||||
if (r == lia_move::undef && should_find_cube()) {
|
||||
r = int_cube(lia)();
|
||||
if (r == lia_move::undef && settings().enable_lll_cube() && should_find_lll_cube())
|
||||
if (r == lia_move::undef && settings().enable_lll_cube() && should_find_lll_cube()) {
|
||||
r = int_cube_lll(lia)();
|
||||
on_lll_cube_result(r);
|
||||
}
|
||||
}
|
||||
if (r == lia_move::undef) lra.move_non_basic_columns_to_bounds();
|
||||
if (r == lia_move::undef && should_hnf_cut()) r = hnf_cut();
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ struct statistics {
|
|||
unsigned m_lll_cube_bail_basis = 0;
|
||||
unsigned m_lll_cube_bail_tighten = 0;
|
||||
unsigned m_lll_cube_bail_infeasible = 0;
|
||||
unsigned m_lll_cube_throttled = 0;
|
||||
unsigned m_patches = 0;
|
||||
unsigned m_patches_success = 0;
|
||||
unsigned m_hnf_cutter_calls = 0;
|
||||
|
|
@ -166,6 +167,7 @@ struct statistics {
|
|||
st.update("arith-lll-cube-bail-basis", m_lll_cube_bail_basis);
|
||||
st.update("arith-lll-cube-bail-tighten", m_lll_cube_bail_tighten);
|
||||
st.update("arith-lll-cube-bail-infeasible", m_lll_cube_bail_infeasible);
|
||||
st.update("arith-lll-cube-throttled", m_lll_cube_throttled);
|
||||
st.update("arith-patches", m_patches);
|
||||
st.update("arith-patches-success", m_patches_success);
|
||||
st.update("arith-hnf-calls", m_hnf_cutter_calls);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue