mirror of
https://github.com/Z3Prover/z3
synced 2026-06-29 11:58:51 +00:00
## Summary Improves the Diophantine (`dio`) integer-feasibility controller in `int_solver`, and fixes a latent bug where the user's Gomory-cut configuration could be silently overridden at runtime. Also includes the earlier `lia_w` work: randomized hammer gates, the `int_hammer_period` / `random_hammers` parameters, and the linear `dio_calls_period` recovery. ## Motivation The controller used a **single field** both as the static `lp.dio_cuts_enable_gomory` parameter and as the live "is Gomory running" flag. It started running Gomory (and the gcd test) once `dio_calls_period` crossed a hard-coded `16`. Because `dio_calls_period` is also driven by the randomized hammer gate, on instances where `dio` is only intermittently productive the period could be ratcheted past 16 *by chance*, turning on Gomory + gcd and thrashing — e.g. `dillig/20-14` went from a 100s solve (deterministic) to a 600s timeout (randomized) purely from this spurious activation. ## Changes - **Separate config from runtime state.** Split the shared field into `m_dio_cuts_enable_gomory` (static config, never mutated) and `m_run_gomory_with_dio` (runtime flag). Toggling the runtime state can no longer clobber the user's `dio_cuts_enable_gomory` parameter. - **Trigger on genuine dio failures, not the period proxy.** Running Gomory-with-dio now starts after a count of **consecutive `undef` dio returns** (reset on a dio conflict) rather than when the randomization-inflated period crosses a threshold — robust to `random_hammers` gate variance. - **Parameterize the threshold.** New `lp.dio_gomory_enable_period` (default 16). Set it very large to never auto-start Gomory, so Gomory follows `dio_cuts_enable_gomory` only. - **Try `dio` before Gomory** in `check()` so a productive dio conflict preempts Gomory on dio-dominated instances. ## Evaluation (QF_LIA, full set, 600s, seed 555 paired) - Dio-before-Gomory: **+33** problems across the 6 `random_hammers x int_hammer_period` cells (5/6 cells improve). - New trigger (`dio_gomory_enable_period=32`, random): **6417** vs the period-16 baseline **6409**; no short-cutoff regression. - Linear `dio_calls_period` recovery: keeping it on is worth ~+20 vs off; `decrease=1` slightly ahead of the default 2. Default behavior (`dio_gomory_enable_period=16`) is byte-for-byte equivalent to the previous threshold logic. ## Notes Debug-only tracing used during analysis (the `dio_calls_period_trace` parameter plus per-hammer / period-evolution verbose output) is **not** included. --------- Signed-off-by: Lev Nachmanson <levnach@hotmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
57 lines
1.8 KiB
C++
57 lines
1.8 KiB
C++
/*++
|
|
Copyright (c) 2017 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
<name>
|
|
|
|
Abstract:
|
|
|
|
<abstract>
|
|
|
|
Author:
|
|
|
|
Lev Nachmanson (levnach)
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
#include "math/lp/lp_params_helper.hpp"
|
|
#include <memory>
|
|
#include "util/vector.h"
|
|
#include "params/smt_params_helper.hpp"
|
|
#include "math/lp/lp_settings_def.h"
|
|
template bool lp::vectors_are_equal<lp::mpq>(vector<lp::mpq > const&, vector<lp::mpq> const&);
|
|
|
|
void lp::lp_settings::updt_params(params_ref const& _p) {
|
|
smt_params_helper p(_p);
|
|
lp_params_helper lp_p(_p);
|
|
m_enable_hnf = p.arith_enable_hnf();
|
|
m_propagate_eqs = p.arith_propagate_eqs();
|
|
print_statistics = p.arith_print_stats();
|
|
m_print_external_var_name = p.arith_print_ext_var_names();
|
|
report_frequency = p.arith_rep_freq();
|
|
m_simplex_strategy = static_cast<lp::simplex_strategy_enum>(p.arith_simplex_strategy());
|
|
m_nlsat_delay = p.arith_nl_delay();
|
|
auto eps = p.arith_epsilon();
|
|
m_epsilon = rational(std::max(1, (int)(100000*eps)), 100000);
|
|
m_dio = lp_p.dio();
|
|
m_dio_cuts_enable_gomory = lp_p.dio_cuts_enable_gomory();
|
|
m_dio_gomory_enable_period = lp_p.dio_gomory_enable_period();
|
|
m_dio_enable_hnf_cuts = lp_p.dio_cuts_enable_hnf();
|
|
m_dump_bound_lemmas = p.arith_dump_bound_lemmas();
|
|
m_dio_ignore_big_nums = lp_p.dio_ignore_big_nums();
|
|
m_dio_calls_period = lp_p.dio_calls_period();
|
|
m_dio_calls_period_decrease = lp_p.dio_calls_period_decrease();
|
|
m_dio_run_gcd = lp_p.dio_run_gcd();
|
|
m_random_hammers = lp_p.random_hammers();
|
|
m_lcube = lp_p.lcube();
|
|
m_lcube_flips = lp_p.lcube_flips();
|
|
unsigned hammer_period = lp_p.int_hammer_period();
|
|
SASSERT(hammer_period != 0);
|
|
m_int_find_cube_period = hammer_period;
|
|
m_int_gomory_cut_period = hammer_period;
|
|
m_hnf_cut_period = hammer_period;
|
|
m_max_conflicts = p.max_conflicts();
|
|
}
|