Skip to content

fix: give up on Bareiss solves that grow past what is workable - #77

Merged
oameye merged 3 commits into
mainfrom
fix/bareiss-blowup
Jul 27, 2026
Merged

oameye merged 3 commits into
mainfrom
fix/bareiss-blowup

Conversation

@oameye

@oameye oameye commented Jul 27, 2026

Copy link
Copy Markdown
Member

The limit cycle tutorial hangs. A van der Pol ansatz in three harmonics gives a
dense 6x6 whose Bareiss entries grow combinatorially, and one multiplication can
exhaust memory before its result can even be measured. Bound the predicted width
of a product before multiplying, and the width of a finished entry after. The
systems this solve handles well sit far below the bounds: 10 monomials for a
Duffing oscillator, 28 for a parametron, 344 for a van der Pol with two harmonics.

Size raises BareissTooLarge, not BareissFailure. They're different conditions:
BareissFailure means the system isn't polynomial in the unknowns and
rearrange! answers it with the LU fallback, but that fallback grows without
bound on exactly the systems that are too large for Bareiss. Size has to reach a
caller with a cheaper route instead, which HarmonicBalance's add_jacobian! now
is.

Second commit collapses cos^2 + sin^2, which SymbolicUtils 4 stopped folding.
It's correct and the equations are unchanged, but I measured no benefit: Krylov
order 2 goes 3.61s -> 3.43s, which is noise. Split out so it can be dropped.

oameye added 2 commits July 27, 2026 14:29
Bareiss is fraction-free, which is what lets it sidestep the nested-fraction
growth of `symbolic_linear_solve`, but its entries are exact polynomials whose
degree grows with every pivot. On a dense system in many atoms that growth is
combinatorial: the harmonic equations of a van der Pol oscillator in three
harmonics never finish, and one multiplication can exhaust memory outright.

Bound both the predicted width of a product, checked before multiplying since a
single multiply can OOM before its result can be measured, and the width of a
finished entry. The systems this solve handles well are far below the bounds: 10
monomials for a Duffing oscillator, 28 for a parametron, 344 for a van der Pol
with two harmonics.

Raise `BareissTooLarge` rather than `BareissFailure`. The two are not the same
condition: `BareissFailure` means the system is not polynomial in the unknowns
and `rearrange!` answers it with the LU fallback, whereas the LU fallback grows
without bound on exactly the systems that are too large for Bareiss. Size has to
reach a caller that has a cheaper route instead.
SymbolicUtils 3 folded this identity away on its own and SymbolicUtils 4 does
not, which is why the determinant-carrying denominators of a symbolic linear
solve stopped simplifying. `collapse_pythagorean` applies it directly, in one
bottom-up walk rather than the exponential round trip `trig_reduce` needs, and
`rearrange!` uses it on the solutions.

No measurable speedup to report: the Krylov-Bogoliubov equations, the caller
whose systems actually carry trig, move from 3.61s to 3.43s at order 2, which is
noise. The resulting equations are unchanged. Worth having as the identity being
restored, not as a performance fix.
@oameye
oameye merged commit 6fb3160 into main Jul 27, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant