Arithmetic Solving in Z3#
Bibliographic record#
Publication: [5]. Section references use the CAV 2024 edition.
Source refresh, 2026-09-25: §§2–3 and 6 were reread from the supplied PDF for the replacement LRA chapter. The chapter retains direct/indirect propagation and the optional §3.2 model-unit producer, including its unpromoted status. The implementation and experiment trail below remains available for the integer and combination chapters; this refresh does not rerun its evaluations.
Read 2026-08-17: Sections 2, 3, 6, and 8 in full; the integer and nonlinear sections were read only to delimit their relevance to what was then Primo’s QF_LRA/QF_UFLRA-only fragment.
Re-read 2026-08-21, Section 4 in full. The original reading deliberately skipped the integer section because QF_LIA did not exist in Primo yet. It does now, with four stages shipped, so Section 4 is the directly relevant part of this paper and is summarized below. Sections 5 (non-linear) and 7 (evaluation) remain out of scope; Section 7’s headline numbers are noted only where they calibrate expectations.
This note records the paper’s algorithmic content independently of the Z3 source code. Z3 source is not an implementation source for Primo.
Relevant scope#
The paper describes the arithmetic solver introduced in Z3 4.8.8 and later made default. Its complete waterfall also covers non-linear arithmetic, which is outside Primo’s current fragment. The parts that matter:
Section 2 motivates an exact, sparse dual-simplex tableau integrated with CDCL and efficient backtracking.
Section 3.1 restates the bound-assertion dual-simplex architecture used by Primo’s LRA solver.
Sections 3.2 and 3.3 describe inexpensive equality and bound propagation.
Section 4 is the integer waterfall Primo’s QF_LIA path is a partial implementation of – see the dedicated section below.
Section 6 states how arithmetic participates in model-based theory combination and how Z3 caches shared-term membership.
The paper does not describe primitive-integer normalization of input atoms. Monniaux CAV 2009 Section 2.1 remains the source for Primo’s early arithmetic atom canonicalization.
Section 4: the integer waterfall#
The paper states the order explicitly: first patch real solutions into integer ones; if patching leaves integer variables fractional, check light-weight Diophantine infeasibility criteria; then resort to Gomory cuts and branch-and-bound. Primo implemented the third and fourth layers first; patching (4.1) followed on 2026-08-21, leaving cubes (4.2) as the one absent layer.
4.1 Patching – IMPLEMENTED 2026-08-21 (stage 5)#
The observation is that in a feasible tableau with all non-basic variables at
their bounds, integer-sorted non-basics already hold integer values, so only
basic variables can be fractional. Patching changes non-basic values to make
basic ones integral: for a row with basic xb, find a delta of minimal
absolute value such that moving one non-basic y by delta stays within y’s
bounds, makes xb integral, and breaks no other bound.
The paper’s example: y - x/2 = 0, z - x/3 = 0, with x in [3,10], y in
[-3,4], z in [-5,12]. Starting at x = 3 gives y = 3/2. Moving x
within its freedom interval [3,8] to x = 6 makes both y = 3 and z = 2
integral.
The paper explicitly reports a negative result worth recording: the related
method of diversifying values via freedom intervals (their citation [18]) “does
not preserve integral assignments”. So freedom intervals bound the search space
for delta, but the diversification heuristic itself is not the technique.
Two things the paper’s description leaves implicit, both found by building
Example 3 as a test rather than trusting the prose. First, “|delta| is minimal”
cannot be read per-variable: the nearest fix for y moves x to 4 and breaks
z, and the nearest fix for z then moves it straight back, so a naive
implementation oscillates. Candidates have to be scored by their effect on
all integer variables. Second, the two integers bracketing the current value
are not a sufficient candidate set – Example 3’s own answer x = 6
corresponds to y = 3, two integers above y’s current 3/2, so floor/ceil
alone never proposes it. See QF_LIA: Branch-and-Bound, GCD-Consistency, and Gomory Cuts on the Existing Simplex‘s “Patching”.
4.2 Cubes – not implemented in Primo#
Bromberger and Weidenbach’s test: Ax <= b is integer feasible if
Ax <= b - (1/2)||A||_1 has a solution over the reals, where ||A||_1
taken as a column vector has entry i equal to the sum of absolute values in
row i. So one real-feasibility check on a uniformly tightened system decides
integer feasibility positively, and the real solution rounds to an integer one.
The paper’s example: for 3x + y <= 9 AND -3y <= -2, solve
3x + y <= 9 - (1/2)(3+1) = 7 and -3y <= -2 - (1/2)3 = -3.5; a real model
y = 7/6, x = 0 rounds to an integer solution of the original.
Z3’s refinement over the original method: difference inequalities x - y <= k
with integer k never need strengthening (real-feasible iff integer-feasible),
and octagon constraints ±x ±y <= k need it only when the two variables sit at
midpoints between integral solutions.
The paper calls this “an important factor in solving more satisfiable integer arithmetic instances” – which is exactly where Primo’s measured deficit is (see the gap analysis below).
Read against the primary source, 2026-08-29. Bromberger’s thesis (Decision Procedures for Linear Arithmetic (Bromberger’s thesis), Chapters 4–5) is the origin of this test, and it changes two things this section implied.
The precondition that blocks Primo (an asserted equality fixes a slack, so the tightened system is contradictory) is a named, cheap skip condition in the original, not a defect: skip when an integer variable has
U - L = 1or a slack hasU - L = 0, and substitute out fixed integer variables first (§7.2.4). z3’s difference/octagon twist does not address it and is therefore not the prerequisite Open leads register lead 12c recorded.The actual prerequisite for equality-heavy inputs is the implied-equality basis of the thesis’s Chapter 5, which exists precisely because equalities break the cube tests; §5.7 lists equality elimination as “useful as a preprocessing step for our cube tests”.
Size, from the thesis’s own ablation on the full QF_LIA SMT-LIB division: 6806 with the unit cube test vs. 6750 without (+56), over a population of 1483 absolutely unbounded instances, with the test removing the need for branch-and-bound entirely on 1271 of them.
4.3 GCD consistency – Primo has the basic test, not the extended one#
The basic test is the one Primo’s stage 2 implements: fold fixed variables into a constant offset and check that the gcd of the remaining coefficients divides it.
The paper then extends it in a way Primo does not have. For a row
a.x + b.y + c = 0 where the coefficients in a are all equal and smaller
than those in b, and the variables x are bounded but not necessarily
fixed, let l := a.lb(x) and u := a.ub(x) be the achievable range of the
bounded part. If that range contains no value congruent to the required residue
modulo gcd(b, c), there is no solution.
Caution on the printed inequality. The paper renders the condition as
floor(u/gcd) > ceil(l/gcd), which is backwards as written – that direction
would report infeasibility precisely when a solution exists. The intended test
is floor(u/gcd) < ceil(l/gcd), i.e. no multiple of the gcd lies in [l, u].
Checked against the paper’s own shape with l = 2, u = 3, g = 4:
floor(3/4) = 0 < ceil(2/4) = 1, correctly infeasible. Anyone implementing
this should not transcribe the printed direction.
This extension matters concretely: it closes the exact case
docs/qf-lia-branch-and-bound.md documents as caught by neither stage 2 nor
stage 3 – 4x + 4y bounded to [2,3] with x, y unbounded, which currently
diverges to --lia-branch-limit and is pinned by
gcd_uncatchable_divergent_system_hits_the_node_limit in
tests/unit/qf_lia_solver_tests.cpp. Primo’s stage 2 misses it because
fixed_value() requires equal lower and upper bounds, and here the slack is
bounded but not fixed.
4.4 Branching – Primo’s is theory-internal, Z3’s is a SAT literal#
Z3 “creates somewhat eagerly case splits on bounds of integer variables”; for a
variable assigned 1/2 it creates a literal x <= 0 that triggers the two
branches. That is CDCL-integrated branching, so conflict learning generalizes
across branches. Primo’s branch_and_bound runs an explicit-stack DFS entirely
inside the theory with synthetic kDerivedBoundReason bounds – a deliberate
scoping decision recorded in docs/qf-lia-branch-and-bound.md’s “Where
branching lives”, not an oversight.
4.5 Cuts – Primo has the base method, none of the enhancements#
Z3 implements Chvatal-Gomory cuts plus cuts derived after transforming the linear system into Hermite normal form. Primo implements one mixed Gomory cut (King’s thesis eq. 4.9). The paper adds five things Primo lacks:
A relaxed Gomory-row definition. The strict definition requires every non-basic
xjin the row to sit at a non-strict bound. Z3 relaxes this: a non-basic integralxjmay be away from its bounds providedbeta(xj)andajare both integers – suchxjis called row integral. This directly widens eligibility, which is Primo’s measured failure mode (the instrumentedf_unboundedcount).Explanations must track the relaxation. The paper notes the Gomory term’s explanation does not include constraints on the relaxed (row-integral) variables – but that in the extremum case below, those constraints do have to be added. This is a direct constraint on Primo’s new
LiaExplanationantecedent rule if the relaxation is adopted.A cut-selection heuristic. Sort Gomory rows by the distance of
beta(xb)from the nearest integer and take a few with minimal distance, breaking ties toward variables occurring in more terms. The paper notes earlier heuristics used distance to bounds instead. Primo takes the first eligible row.Extremum detection. If every
xjis at its lower bound and everyaj > 0, thenxbis at its maximum and one can deducexb <= floor(beta(xb))directly – a bound, not a cut.Large-numeral discipline. Cuts with large coefficients are added to a temporary scope first and only re-added to the main scope if the temporary tableau is infeasible; bounds propagation is likewise skipped when it would need big-num arithmetic. Primo uses
--lia-gomory-cut-limitas a blunt substitute.
The paper also states plainly that “cuts are consequences of the current bounds”, which is the same justification Primo’s stage 4 explanation rests on.
What Section 7 says about expectations#
On QF_LIA the paper reports z3 solving 6,276 and CVC5 3,556 of the same set at 600 s, with MathSat5 at 6,368 and Yices2 at 6,035. The relevant lesson for Primo is the paper’s own summary of its ablation: apart from incremental linearization (a non-linear feature), “other features have each a relative minor effect in isolation. The solver relies on their cumulative effect.” A single missing layer should not be expected to close a large gap on its own.
Gap analysis against Primo (2026-08-21)#
Primo’s own full-corpus measurement points at the same place the paper does. Over all 13,306 QF_LIA files at 60 s (Slurm 127949 and 127709):
solver |
sat |
unsat |
total |
|---|---|---|---|
primo |
5,866 |
2,859 |
8,725 |
cvc5 |
6,527 |
2,712 |
9,239 |
z3 |
7,825 |
4,322 |
12,147 |
Primo is ahead of cvc5 on unsat by 147 and behind on sat by 661. The entire deficit to cvc5 is on satisfiable instances. That is a precise match for what is missing: sections 4.1 (patching) and 4.2 (cubes) are the two layers aimed squarely at finding integer models, and Primo implements neither, while the layers Primo does implement – GCD consistency, Gomory cuts, branch-and-bound, and now conflict generalization – are all refutation machinery.
Complete audit of what Primo has and lacks (2026-08-22)#
paper |
technique |
status |
|---|---|---|
3.1 |
dual simplex, bound assertion |
have |
3.2 |
cheap equal-variable discovery |
N/A for QF_LIA – the paper states equality propagation is disabled for pure arithmetic theories, QF_LIA and QF_LRA included. Relevant only to QF_UFLRA, where Primo now has both: the legacy exact producer (default) and the 2024 fast path behind |
3.3 |
direct bounds propagation |
have, on by default |
3.3 |
indirect (row-based) bounds propagation |
implemented but off by default – and now measured on QF_LIA: it does not help (see below) |
4.1 |
patching |
have (stage 5, +300 solves) |
4.2 |
cube test |
missing, deferred behind z3’s difference/octagon twist |
4.3 |
GCD consistency, basic |
have (stage 2) |
4.3 |
GCD consistency, extended to bounded-not-fixed rows |
missing (lead 12e) |
4.4 |
branching on integer bounds |
have, but theory-internal DFS |
4.4 |
branching as CDCL literals |
missing – z3 creates a real SAT literal so conflict analysis generalizes across branches; Sect. 2 names this eager-case-split design as deliberate |
4.5 |
Gomory cuts |
have (stage 3, King’s mixed cut) |
4.5 |
relaxed “row-integral” Gomory rows |
missing; has measured evidence behind it (the instrumented |
4.5 |
cut selection by distance to nearest integer |
missing; Primo takes the first eligible row |
4.5 |
extremum bound deduction |
missing |
4.5 |
Hermite-normal-form cuts |
missing, large |
4.5 |
large-numeral temporary scope |
missing; |
Row-based propagation does not transfer to QF_LIA#
Sect. 3.3’s indirect propagation is the one paper technique Primo already
implements and simply leaves off (lra_row_propagation = false). It had been
fuzz-gated and A/B-tested repeatedly – 17 run-log entries – but every one of
those was QF_LRA or QF_UFLRA, and none was QF_LIA, which is now the fragment
where profiling says the bottleneck lives.
Measured on the per-family sample (94 files, 10 s), including the exact widened
caps sandbox/paper.tex’s RamParILS tuning selected for its primo+
configuration (max-row-size 256, max-fanout 1024, against defaults of 64):
arm |
solved |
sat |
unsat |
wrong |
PAR2 |
|---|---|---|---|---|---|
default |
58 |
30 |
28 |
0 |
7.83 |
row propagation, default caps |
57 |
29 |
28 |
0 |
8.09 |
row + bidirectional |
58 |
30 |
28 |
0 |
7.94 |
row propagation, paper caps |
57 |
29 |
28 |
0 |
8.12 |
|
55 |
27 |
28 |
0 |
8.42 |
both (the paper’s |
56 |
28 |
28 |
0 |
8.37 |
Zero gains in any arm. Individual losses of one to three could be sample
noise, but the absence of a single gain across six configurations is not. The
QF_LRA tuning does not transfer: lra_row_propagation and lra_model_phase
are both worth keeping off for QF_LIA, and that is now measured rather than
inherited. This is also a result for the paper itself – its tuned
configuration is fragment-specific, not a better default.
What is worth attempting next, and the caveat over all of it#
Ranked by expected value for Primo:
Section 3.2: cheap equal-variable discovery#
The goal is to propagate equalities between shared arithmetic variables without subtracting large rows or enumerating every shared pair. The paper first limits attention to variables equal in the current arithmetic assignment. Model equality is only a candidate condition; the tableau shape and fixed variables establish entailment.
The reported useful shapes are:
a shared basic variable
xhas a rowx - y + alpha = 0, whereyis shared and every variable inalphais fixed;two shared basic variables
xandyhave rows connected through the same non-basicz, with the same unit sign onz, while all remaining terms in both rows are fixed.
Because the current assignment already has beta(x) = beta(y), feasibility of
the rows establishes that the fixed remainders agree. The implementation need
not construct or hash their potentially large exact numeric offsets. The paper
reports that Z3’s older offset-equality table was costly specifically because
computing those offsets can involve large numerals and because the hash-table
operations add overhead. It also reports no measurable gain from generalizing
the connecting variable beyond unit coefficients.
Mapping to Primo#
LraTableau::model_equal_classes() already provides the required candidate
filter over exact DeltaRational values. LraTableau::entailed_equalities()
implements the sound FixedEq, EqRow, EqOffsetRows, and general EqRows
rules from de Moura and Bjørner 2008, with explanations.
The default legacy producer is not the 2024 fast path:
EqRowcomputes the exact value of the fixed remainder;EqOffsetRowsconstructs and hashes an exact fixed offset;EqRowsconstructs and hashes the complete non-fixed polynomial plus exact fixed offset;the producer scans all supplied shared variables before the model-equality partition is used as a narrow candidate frontier.
These operations are sound, but they include the offset arithmetic and hashing
that the paper identifies as avoidable. The general EqRows rule may still be
useful; the paper’s negative result for non-unit generalization makes it an A/B
question rather than a reason to delete it without measurement.
Implementation checklist and experimental producer#
The model-unit producer implements this mechanism behind
--qf-uflra-lra-equality-producer=model-unit. The completed differential
fuzzing and full-corpus A/B do not justify replacing the default legacy
producer; the measured tradeoff is recorded below. The implementation
obligations are:
Build the exact current-model equality classes once and inspect only non-singleton shared classes.
Recognize the one-row and same-sign two-row unit-coefficient shapes without constructing fixed offsets.
Collect every fixing lower/upper bound used by the matched rows so the published equality retains a checkable explanation.
Emit a deterministic spanning set, not all pairs in a model class.
Keep the existing exact producer or strict-orientation fallback as the completeness path; failure to match a cheap shape is not disequality.
Preserve the distinction between model-equal conjectures and entailed equalities.
Expected work is linear in the shared variables and nonzeros of candidate rows, plus emitted explanation literals. Required counters are candidate model classes and pairs, one-row matches, two-row matches, rows/nonzeros inspected, and fallthrough to offset/general/exact producers. Tests need large fixed numerals so they exercise avoidance of offset arithmetic, both signs of the connecting unit variable, non-unit rejection, transitive spanning output, and explanation invalidation when any fixing bound is removed.
Detailed implementation contract#
The fast producer is a read-only query on a feasible LraTableau. It receives
only the LRA variables corresponding to the solve-scoped shared Real interface;
pure QF_LRA never calls it. It first partitions those variables by their exact
DeltaRational assignment. Singleton classes cannot produce a model-guided
equality and are discarded. A variable-to-class map then lets the row scan
reject candidates from different model classes without arithmetic.
For a shared basic variable x, write its stored row as x = sum a_i x_i.
The one-row rule accepts a shared y in the same model class when a_y = 1
and every other row variable is fixed. Since beta(x) = beta(y), the fixed
remainder evaluates to zero in the current model; because every variable in
that remainder is fixed, it evaluates to zero in every model satisfying the
current bounds. Therefore x = y is entailed without constructing the
remainder’s value.
The two-row rule records a shared basic variable when its row has exactly one
non-fixed variable z, whose coefficient is 1 or -1; every other row
variable must be fixed. Two records in the same model class with the same z
and coefficient have equal fixed remainders, again because their basic
variables have equal current values. Their equality is therefore entailed.
Opposite signs, non-unit coefficients, or another non-fixed term do not match.
Each fixing premise contributes both bound reasons. Reasons are sorted and
deduplicated before publication. A deterministic disjoint-set structure over
each model class emits an edge only when it joins two previously disconnected
components, bounding output by n - 1 equalities per class. Missing a match is
not a negative result: the mixed coordinator retains its complete
strict-orientation fallback for unresolved pairs.
With expected constant-time hash-table operations, the structural scan costs
O(S + N), where S is the number of supplied shared variables and N is the
number of nonzeros in rows of candidate shared basic variables. If emitted
equality i has r_i explanation literals, sorting and deduplication adds
O(sum_i r_i log r_i). The query must not pivot, add rows, assert bounds,
create terms, or compute/hash fixed numeric offsets. The legacy producer
remains available and is the default.
Counters under :no.interface.lra-model-unit-* expose classes, candidate
pairs, rows, nonzeros, matches, rejections, and reasons;
:time.no-lra-equality-producer-us records aggregate query time.
Evaluation and default decision#
Commit 5e9371a was tested on SLURM with the option enabled. Job 127110
passed 3,000 generated mixed QF_UFLRA cases, 1,000 finite-domain cases, and
3,500 model checks; 1,947 SAT models passed Dolmen. Job 127111 then checked
all 11 tracked QF_UFLRA seeds and completed 43,936 YinYang solver calls with no
bug trigger. The full 1,284-file, 120-second A/B used jobs 127115 (legacy)
and 127116 (model-unit). Both had zero wrong answers, errors, or unsupported
rows.
The fast producer reduced aggregate producer time from 2,579,190 to 698,229
microseconds and explanation literals from 26,234,347 to 7,116,559. On the
1,271 common solves, aggregate wall time improved from 760.05 to 740.33
seconds. However, legacy solved 1,272 files and model-unit solved 1,271. The
lost CPAchecker induction row was SAT in 77.12 seconds under legacy and timed
out at 120 seconds under model-unit. On that row the legacy producer found
2,226 general EqRows matches that the unit-only producer deliberately does
not implement; the candidate delivered fewer opportunistic equalities and did
not invoke its strict-orientation fallback for those pairs.
This is a search-strength regression, not a correctness failure. The result
validates the paper’s local cost observation, but rejects replacing Primo’s
broader producer wholesale. legacy therefore remains the default.
Three exact-commit repetitions made the loss reproducible rather than a
120-second boundary effect. At commit fcc8d0e, legacy solved the row in
70.62–70.67 seconds, while model-unit needed 180.53–182.60 seconds. Enabling
the candidate final scan produced the same search statistics and
180.82–182.34-second times. The missing early lemmas, rather than the final
completeness check, are decisive: legacy reaches a fixed point in three
convex rounds after 2,226 general EqRows matches, whereas model-unit takes
33 rounds, 22 shared-model splits, 86 assumption solve calls, and 842 equality
assumptions. Its solve-phase time increases by about 112 seconds even though
the producer itself remains cheap.
The follow-up adaptive mode is a Primo scheduling experiment around the
paper mechanism. It runs legacy until an opportunistic producer round causes
no SAT recheck, uses model-unit on later rounds, and returns permanently to
legacy when shared-model reconciliation still has to materialize a SAT
equality split after a model-unit round. A split reached directly from the
bootstrap instead starts the cheap phase; model-unit has not failed yet. This
propagation-fixed-point bootstrap preserves general EqRow clauses that
actively change the initial SAT search trajectory. A later split means the
cheap entailed equalities were
insufficient to reconcile the current theory models; it is therefore a
semantic escalation trigger rather than a tuned numeric threshold. The
fallback is permanent within one check-sat call because later SAT assignments
can expose additional fixed-row equalities. Counters distinguish the bootstrap,
unit rounds, legacy rounds, and the single fallback activation. This adaptive
policy is not from the paper.
The completed evaluation at commit d8fc162 shows that this scheduling rule
repairs the regression conservatively. The lost row solved three times in
73.65–74.02 seconds with exactly the legacy decision and propagation counts.
The fresh gate passed 3,000 mixed cases, 500 finite QF_UF cases, 500 finite
QF_UFLRA cases, and 3,500 model checks; all 1,991 SAT models passed Dolmen. On
the productive mutation replay, all 11 tracked seeds were valid and 43,854
solver calls found no bug trigger. On the complete 1,284-file corpus, adaptive
and legacy both solved 1,272 files with the same 12 timeouts and no wrong
answers. Adaptive entered model-unit on 77 files (93 rounds) and activated the
permanent fallback on 40 files.
The result does not justify changing the default. Aggregate producer time fell
only from 2,579,190 to 2,459,320 microseconds (4.6 percent), and 67 of the 77
files that entered the cheap phase retained identical SAT/combination search
statistics. The old and new full runs were not concurrent; their 52.57-second
wall-time difference is therefore not attributable to the mechanism, especially
because an earlier adaptive version that selected model-unit zero times showed
a similar cluster-time shift. adaptive remains an explicit experimental
profile, while legacy remains the default.
Section 3.3: bounds propagation#
The paper separates direct from indirect propagation. Direct propagation uses an index from an arithmetic variable to existing bound atoms, so asserting a stronger bound can immediately imply weaker visible bounds. Indirect propagation inspects updated tableau rows for bounds stronger than those already asserted, then routes them through the same index.
Primo has direct bound sharing and optional row-bound propagation, but this paper is a useful independent source for their architecture and scheduling. It does not justify enabling broader row propagation by default: the existing QF_UFLRA A/B exchanged one solve for one loss, so default policy remains an empirical decision.
Resulting priority#
For QF_LRA/QF_UFLRA (the 2026-08-18 producer experiments): for current
convex QF_UFLRA the paper does not reveal a missing correctness
transition. It reveals a narrower performance opportunity inside an existing
correct transition: replace exact-offset row bucketing with the
current-model-filtered unit-row recognizer, retain explanations, and leave the
strict-orientation oracle as the completeness path. The opt-in model-unit
producer is the completed experiment. It substantially reduces producer-local
work, but the recorded full-corpus loss rejects default promotion. The
experimental adaptive policy tests whether a propagation-fixed-point legacy
bootstrap can recover useful general EqRows lemmas without paying their
exact-offset cost on every later round. It recovers the lost row and preserves
the full solved set, but its small producer-local saving does not justify
changing the default.
For QF_LIA (the 2026-08-21 re-reading): the paper reveals two entire missing layers, not a tuning opportunity. Primo’s integer waterfall started at the paper’s third layer. Patching (4.1) and cubes (4.2) both exist to find integer models, and Primo’s measured weakness is precisely and only on satisfiable instances.
Patching shipped the same day as stage 5 – see QF_LIA: Branch-and-Bound, GCD-Consistency, and Gomory Cuts on the Existing Simplex‘s “Patching” section. Cubes was considered first (cheaper, no tableau change) and rejected on a measurement: 249 of 300 sampled instances contain equality atoms, and an asserted equality fixes a slack, which makes the tightened cube system contradictory. Cubes would be inconclusive on most rounds without also building z3’s difference/octagon twist, so it stays deferred behind that twist rather than as a standalone item. The extended GCD test (4.3) is the smaller, well-scoped next candidate, and closes an already-documented divergence.
Both should be measured against the same-binary control the stage 4 evaluation established, and neither should be expected to close the cvc5 gap alone – the paper’s own ablation reports that its features matter cumulatively rather than individually.