3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-06-29 11:58:51 +00:00
z3/src/math/lp/lp_settings.cpp
Lev Nachmanson 57fb719007
lp: gate Gomory-with-dio on genuine dio failures; separate config from runtime state (#9958)
## 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>
2026-06-25 14:21:44 -07:00

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();
}