mirror of
https://github.com/Z3Prover/z3
synced 2026-07-15 03:25:43 +00:00
Z3 4.16.0 introduced a cube-and-conquer parallel solver that regressed easy QF_LIRA problems from <1s to hanging indefinitely. Workers start with a 1000-conflict budget and multiply by 1.5× on each timeout, but after ~38 escalations the `unsigned` cast overflows, causing the budget to oscillate chaotically (e.g. 3.27B → 618M → 927M → … never reaching a stable large value). For sub-cubes that require more conflicts than any value in the oscillation window, the worker loops forever. ## Changes - **`src/smt/smt_parallel.h`** – `update_max_thread_conflicts()`: replace raw `(unsigned)(mul * val)` cast with saturating arithmetic that caps at `UINT_MAX`, eliminating the UB and the oscillation: ```cpp // Before – UB when product > UINT_MAX, budget oscillates after ~38 escalations m_config.m_threads_max_conflicts = (unsigned)(m_config.m_max_conflict_mul * m_config.m_threads_max_conflicts); // After – saturates at UINT_MAX double next = m_config.m_max_conflict_mul * m_config.m_threads_max_conflicts; m_config.m_threads_max_conflicts = (next >= (double)UINT_MAX) ? UINT_MAX : (unsigned)next; ``` - **`src/solver/parallel_tactical.cpp`** – Identical saturating-arithmetic fix in the `parallel_tactical2` worker's `update_max_thread_conflicts()`, which is the code path actually exercised for QF_LIRA problems. - **`src/smt/smt_parallel.cpp`** – Worker's initial per-cube conflict budget is now sourced from `m_smt_params.m_threads_max_conflicts` (the user-visible `smt.threads.max_conflicts` parameter) instead of being hardcoded to 1000, so users who leave the parameter at its default get an unlimited initial budget matching Z3 4.12.x portfolio behaviour. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com> |
||
|---|---|---|
| .. | ||
| assertions | ||
| check_logic.cpp | ||
| check_logic.h | ||
| check_sat_result.cpp | ||
| check_sat_result.h | ||
| CMakeLists.txt | ||
| combined_solver.cpp | ||
| combined_solver.h | ||
| combined_solver_params.pyg | ||
| mus.cpp | ||
| mus.h | ||
| parallel_params.pyg | ||
| parallel_tactical.cpp | ||
| parallel_tactical.h | ||
| preferred_value_propagator.h | ||
| progress_callback.h | ||
| simplifier_solver.cpp | ||
| simplifier_solver.h | ||
| slice_solver.cpp | ||
| slice_solver.h | ||
| smt_logics.cpp | ||
| smt_logics.h | ||
| solver.cpp | ||
| solver.h | ||
| solver2tactic.cpp | ||
| solver2tactic.h | ||
| solver_na2as.cpp | ||
| solver_na2as.h | ||
| solver_pool.cpp | ||
| solver_pool.h | ||
| solver_preprocess.cpp | ||
| solver_preprocess.h | ||
| tactic2solver.cpp | ||
| tactic2solver.h | ||