3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-15 11:35:42 +00:00
z3/src/math/lp
Lev Nachmanson becb995757
lp: avoid heap allocation when relocating coefficients in static_matrix::remove_element (#10115)
## Summary

Optimizes `lp::static_matrix<..>::remove_element`, reported as a hotspot
in
[Z3Prover/bench#3143](https://github.com/Z3Prover/bench/discussions/3143)
(the #1 exclusive-time function, ~19.6%, on
`inputs/issues/iss-5131/bug-1.smt2`).

`remove_element` uses swap-remove but **deep-copied** the relocated tail
coefficient:

```cpp
auto & rc = row_vals[row_offset] = row_vals.back(); // copy from the tail
```

In namespace `lp`, `mpq` is a typedef for the copyable `rational`, so
this copy-assign allocates a fresh bignum whenever the **source (the
tail)** is big — matching the `malloc`/`_int_malloc` entries in the
reported profile. The tail element is `pop_back`'d immediately
afterwards, so the allocation is wasteful.

## Change

A copy-assign allocates only when the **source** is big
(`mpz_manager::set` → `big_set`). So relocate the tail coefficient by
**swapping** exactly in that case — stealing its already-allocated
storage, zero `malloc`. When the tail is small, a plain copy never
allocates and is cheaper than swapping the `mpz` internals; the
destination's size is irrelevant. The column-cell relocation is
unchanged (a `column_cell` carries no coefficient).

Single-file change; no new parameters.

## Benchmarks

A/B produced by toggling the new code path against the original
deep-copy (via a temporary parameter, not included here).

- **rise-runner-2** (initial `is_big()||is_big()` variant): QF_LIA_small
neutral; certora identical outcomes, −1.5% paired solve-time.
- **128-core Linux box**, `run_on_dir.py`, `-max_workers 32` (final
tail-only variant):

| Set | Files | `-T` | Solved (new = orig) | Avg-time ratio new/orig |
Correctness |
|---|---|---|---|---|---|
| QF_LIA (SMT-LIB) | 6947 | 20s | 5817 ≈ 5815 | 1.00000 | identical (±2
timeout-edge) |
| certora | 308 | 120s | 186 = 186 | 0.9977 | identical, 0 unique
timeouts |
| QF_LRA (SMT-LIB 2025) | 1753 | 120s | 1552 = 1552 | 0.9985–0.9991 |
identical, 0 real regressions |

Consistently **correctness-neutral and marginally faster** (~0.1–0.5%)
on large-coefficient LP sets, flat on small-coefficient inputs. The
per-`remove_element` allocation saved is small relative to total solve
time, so the whole-solver delta is a fraction of a percent — a clean
micro-optimization with no downside.

## Validation
- `make`/`ninja` build clean; `test-z3 /a` — 92/92 pass.
- Baseline vs patched output byte-identical on the reported benchmark;
identical solve sets across all three benchmark suites above.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-14 13:04:12 -07:00
..
bound_analyzer_on_row.h capture row by pointer (#9973) 2026-06-27 17:43:08 -07:00
CMakeLists.txt factor out coi, use polynomial elaboration for nlsat solver (#8039) 2025-11-23 08:59:55 -08:00
column.h add scaffolding for experiments with slack 2025-04-23 17:07:50 -07:00
column_namer.h pretty printing for lp 2025-06-06 11:34:28 +02:00
core_solver_pretty_printer.cpp remove default destructors 2024-10-02 22:20:12 +01:00
core_solver_pretty_printer.h remove default destructors 2024-10-02 22:20:12 +01:00
core_solver_pretty_printer_def.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
cross_nested.h Fix 13 compiler warnings: sign-comparison and unused parameters (#8215) 2026-01-16 16:00:42 -08:00
dense_matrix.cpp set clang format off for lp files (#6795) 2023-07-03 17:35:16 -07:00
dense_matrix.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
dense_matrix_def.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
dioph_eq.cpp Use "override" keyword where needed. (#9892) 2026-06-18 13:36:14 -06:00
dioph_eq.h change the default of running dio to true, and running gcd to false, remove branching in dio 2025-04-18 18:24:50 -07:00
emonics.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
emonics.h Migrate codebase to std::string_view (except z3++.h) (#8266) 2026-01-21 09:30:41 -08:00
explanation.h remove a few copies 2026-02-10 09:52:03 +00:00
factorization.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
factorization.h remove unneeded iterator functions 2024-09-23 12:59:04 +01:00
factorization_factory_imp.cpp remove the line with clang-format off 2023-07-10 12:05:59 -07:00
factorization_factory_imp.h remove the line with clang-format off 2023-07-10 12:05:59 -07:00
general_matrix.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
gomory.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
gomory.h remove an unused declaration 2024-01-13 19:11:17 -10:00
hnf.h [coz3-deepperf-fix] lp: hoist loop-invariant pivot reads in HNF pivot_column_non_fractional (#10073) 2026-07-09 07:02:47 -07:00
hnf_cutter.cpp Fix #7951: add cancellation checks to polynomial gcd_prs and HNF computation 2026-02-27 10:26:28 -10:00
hnf_cutter.h Api (#7097) 2024-01-24 16:05:18 -08:00
horner.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
horner.h u_set replaced by indexed_uint_set (#6841) 2023-08-03 16:01:27 -07:00
implied_bound.h remove a few default constructors 2024-09-23 08:17:58 +01:00
incremental_vector.h remove lp_assert 2025-04-14 11:10:26 -07:00
indexed_value.h delete more default constructors 2024-09-23 12:59:04 +01:00
indexed_vector.cpp print output file name 2025-02-11 12:23:00 -10:00
indexed_vector.h fix out of bounds bug 2025-02-11 12:23:00 -10:00
indexed_vector_def.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
int_branch.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
int_branch.h remove the line with clang-format off 2023-07-10 12:05:59 -07:00
int_cube.cpp [code-simplifier] Simplify int_cube: remove goto, use aggregate/brace init (#9874) 2026-06-29 19:18:04 -07:00
int_cube.h Lcube (#9858) 2026-06-14 16:25:21 -07:00
int_gcd_test.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
int_gcd_test.h remove the line with clang-format off 2023-07-10 12:05:59 -07:00
int_solver.cpp lp: gate Gomory-with-dio on genuine dio failures; separate config from runtime state (#9958) 2026-06-25 14:21:44 -07:00
int_solver.h slack 2025-05-12 14:02:17 -07:00
lar_constraints.h opt: validate strict optimization optima faithfully with delta-rational bounds (#10059) 2026-07-09 10:39:23 -07:00
lar_core_solver.cpp remove the line with clang-format off 2023-07-10 12:05:59 -07:00
lar_core_solver.h Fix NLA optimization regression and relax restore_x 2026-03-10 16:38:08 -10:00
lar_core_solver_def.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
lar_solver.cpp opt: validate strict optimization optima faithfully with delta-rational bounds (#10059) 2026-07-09 10:39:23 -07:00
lar_solver.h opt: validate strict optimization optima faithfully with delta-rational bounds (#10059) 2026-07-09 10:39:23 -07:00
lar_term.h Fixes for lar_term== operator (#9284) 2026-04-12 14:31:18 -07:00
lia_move.h remove 'unsat' move, we already have 'conflict'. Add display for cancelled 2025-03-24 07:44:13 -10:00
lp_api.h opt: validate strict optimization optima faithfully with delta-rational bounds (#10059) 2026-07-09 10:39:23 -07:00
lp_bound_propagator.h [coz3-deepperf-fix] Batch fixed-column bound-witness linearization per row in lar_solver (#10029) 2026-07-06 10:39:22 -07:00
lp_core_solver_base.cpp use std_vector more and getting NOT_IMPLEMENTING in C:\dev\z3\src\math\lp\dioph_eq.cpp 2025-02-11 12:23:00 -10:00
lp_core_solver_base.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
lp_core_solver_base_def.h Avoid invalidated column-cell references in LP pivot paths (#9783) 2026-06-09 07:36:05 -07:00
lp_params_helper.pyg make the batch explanation of fixed in row the default 2026-07-07 10:15:07 -07:00
lp_primal_core_solver.cpp remove the line with clang-format off 2023-07-10 12:05:59 -07:00
lp_primal_core_solver.h Remove unnecessary semicolons (Attempt 2) (#10020) 2026-07-02 12:47:29 -07:00
lp_primal_core_solver_def.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
lp_primal_core_solver_tableau_def.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
lp_settings.cpp make the batch explanation of fixed in row the default 2026-07-07 10:15:07 -07:00
lp_settings.h make the batch explanation of fixed in row the default 2026-07-07 10:15:07 -07:00
lp_settings_def.h Eliminate unnecessary copy operations in function parameters and range-based loops (#8589) 2026-02-11 21:14:32 +00:00
lp_types.h Api (#7097) 2024-01-24 16:05:18 -08:00
lp_utils.h [WIP] Find and update std::optional usage in code base (#8272) 2026-01-21 19:55:36 -08:00
matrix.cpp remove the line with clang-format off 2023-07-10 12:05:59 -07:00
matrix.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
matrix_def.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
mon_eq.cpp
monic.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
monomial_bounds.cpp Improvements to NLA lemmas (#9391) 2026-04-26 21:07:28 +02:00
monomial_bounds.h Improvements to NLA lemmas (#9391) 2026-04-26 21:07:28 +02:00
nex.h Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
nex_creator.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
nex_creator.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
nla_basics_lemmas.cpp fix latent bug in factorization 2025-09-23 10:47:24 +03:00
nla_basics_lemmas.h rename new_lemma to lemma_builder 2025-06-26 16:33:16 -07:00
nla_coi.cpp Nl2lin - integrate a linear under approximation of a CAD cell by Valentin Promies. (#8982) 2026-03-15 06:13:04 -10:00
nla_coi.h Nl2lin - integrate a linear under approximation of a CAD cell by Valentin Promies. (#8982) 2026-03-15 06:13:04 -10:00
nla_common.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
nla_common.h Arith min max (#6864) 2023-08-19 17:44:09 -07:00
nla_core.cpp Nl2lin - integrate a linear under approximation of a CAD cell by Valentin Promies. (#8982) 2026-03-15 06:13:04 -10:00
nla_core.h Add symbolic-modulus congruence rule to nla_divisions (#10119) 2026-07-14 12:31:17 -07:00
nla_defs.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
nla_divisions.cpp Add symbolic-modulus congruence rule to nla_divisions (#10119) 2026-07-14 12:31:17 -07:00
nla_divisions.h Add symbolic-modulus congruence rule to nla_divisions (#10119) 2026-07-14 12:31:17 -07:00
nla_grobner.cpp nla_grobner: add mod_residue pattern to propagate_quotients (#9597) 2026-05-26 18:12:38 -07:00
nla_grobner.h Add adaptive growth knobs for Gröbner under arith.nl.grobner_adaptive (#9390) 2026-04-28 08:50:38 -07:00
nla_intervals.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
nla_intervals.h Arith min max (#6864) 2023-08-19 17:44:09 -07:00
nla_monotone_lemmas.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
nla_monotone_lemmas.h consolidate throttling 2025-06-26 16:33:16 -07:00
nla_order_lemmas.cpp Improvements to NLA lemmas (#9391) 2026-04-26 21:07:28 +02:00
nla_order_lemmas.h use the new throttle in order lemmas 2025-06-26 16:33:16 -07:00
nla_powers.cpp evaluate unhandled arithmetic operators based on an initialized model #7876 2025-09-14 06:45:36 -07:00
nla_powers.h remove the line with clang-format off 2023-07-10 12:05:59 -07:00
nla_pp.cpp Nl2lin - integrate a linear under approximation of a CAD cell by Valentin Promies. (#8982) 2026-03-15 06:13:04 -10:00
nla_solver.cpp Add symbolic-modulus congruence rule to nla_divisions (#10119) 2026-07-14 12:31:17 -07:00
nla_solver.h Add symbolic-modulus congruence rule to nla_divisions (#10119) 2026-07-14 12:31:17 -07:00
nla_tangent_lemmas.cpp Improvements to NLA lemmas (#9391) 2026-04-26 21:07:28 +02:00
nla_tangent_lemmas.h remove a few default constructors 2024-09-23 08:17:58 +01:00
nla_throttle.cpp remove the parameter for throttling nla lemmas 2025-06-26 16:33:16 -07:00
nla_throttle.h Improvements to NLA lemmas (#9391) 2026-04-26 21:07:28 +02:00
nla_throttle_example.cpp consolidate throttling 2025-06-26 16:33:16 -07:00
nla_types.h Remove unnecessary semicolons (Attempt 2) (#10020) 2026-07-02 12:47:29 -07:00
nra_solver.cpp Remove leaked check-assignment output from debug GCC CMake runs (#9978) 2026-06-27 11:22:47 -07:00
nra_solver.h Nl2lin - integrate a linear under approximation of a CAD cell by Valentin Promies. (#8982) 2026-03-15 06:13:04 -10:00
numeric_pair.h improved dio handler 2025-03-24 07:44:13 -10:00
permutation_matrix.cpp remove the line with clang-format off 2023-07-10 12:05:59 -07:00
permutation_matrix.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
permutation_matrix_def.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
random_updater.cpp remove the line with clang-format off 2023-07-10 12:05:59 -07:00
random_updater.h u_set replaced by indexed_uint_set (#6841) 2023-08-03 16:01:27 -07:00
random_updater_def.h Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
stacked_vector.h remove lp_assert 2025-04-14 11:10:26 -07:00
static_matrix.cpp Avoid invalidated column-cell references in LP pivot paths (#9783) 2026-06-09 07:36:05 -07:00
static_matrix.h Use "override" keyword where needed. (#9892) 2026-06-18 13:36:14 -06:00
static_matrix_def.h lp: avoid heap allocation when relocating coefficients in static_matrix::remove_element (#10115) 2026-07-14 13:04:12 -07:00
test_bound_analyzer.h Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
var_eqs.h Remove redundant default constructors when they're the only constructor (#8461) 2026-02-01 16:51:26 -08:00
var_register.h Eliminate unnecessary copy operations in function parameters and range-based loops (#8589) 2026-02-11 21:14:32 +00:00