The determinant is computed by fraction-free elimination where it can be (#999) - #1129
Merged
Merged
Conversation
`Matrix.Determinant` expanded by Laplace, which is O(n!). For a fully symbolic matrix that is optimal -- the determinant genuinely has n! terms and no algorithm returns it smaller in expanded form. For a numeric one it is pure waste: the answer is a single number and O(n^3) work suffices. Bareiss' fraction-free elimination now runs wherever the entries are polynomials over the rationals, and Laplace answers everything else. What decides it is not the size but whether the entries can be read, settled per matrix by trying -- a 12x12 with two variables and a 4x4 with sixteen are different problems and n alone does not tell them apart. Numeric, both arms built from source on one machine: 8x8 from 382 ms to under 1 ms, 10x10 from 14 415 ms to 2 ms, and 11x11, 12x12, 20x20 and 30x30 from not returning at all to 2, 3, 11 and 22 ms. **The elimination was already here.** `PolynomialResultant.SylvesterDeterminant` is a Bareiss elimination over `MultivariatePolynomial`, written for the Sylvester matrix and carrying everything this needs: exact division, row swaps, sign tracking, a work budget and a cancellation check. It is split into `FractionFreeDeterminant` and shared rather than written twice, which is worth saying out loud: a sign convention or an off-by-one in an elimination is a wrong answer that looks entirely plausible, and one implementation exercised by two callers is tested by both. **No condition is introduced.** The issue is right that this is the thing to check rather than argue: exactness is a fact about the ring, and `Entity` division would not notice it -- `(a * b) / a` stays written as a quotient. The arithmetic here never touches `Entity` division. It happens in `MultivariatePolynomial`, which has no quotients to leave behind, and `DivideExact` returns null rather than a remainder, so a division that does not come out stops the elimination and sends the caller to Laplace. The answer is a polynomial in the entries, or it is Laplace's. Declined, and answered by Laplace exactly as before: an entry that is not a polynomial over the rationals, a matrix in more than eight indeterminates, and a matrix mentioning `e` or `pi`, since a constant is a value rather than an indeterminate and this ring cannot hold one. The printed form of a symbolic determinant changes, because an elimination produces an expanded polynomial where Laplace produces a nested one. Recorded in BREAKING-CHANGES.md with the shapes measured on both arms; the expression is no larger in any case measured, and `x * (x ^ 2 + -1) + -x` becomes `x ^ 3 - 2 * x`. The two algorithms are compared on 300 generated matrices where both apply, as a difference simplified to zero rather than as trees -- they group the same polynomial differently and that is not a disagreement. No disagreements. The comparison also asserts that it read more than a third of what it generated, so a change making the elimination decline everything fails rather than passes vacuously. Part of #999.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #999.
The ceiling, removed
Both arms built from source on one machine:
Bareiss' fraction-free elimination runs wherever the entries are polynomials over the rationals; Laplace answers everything else. The switch is decided by the entries, not by
n— as the issue asks, since a 12×12 with two variables and a 4×4 with sixteen are different problems. It is settled per matrix, by trying.The elimination was already in the repository
PolynomialResultant.SylvesterDeterminantis a Bareiss elimination overMultivariatePolynomial, written for the Sylvester matrix and already carrying exact division, row swaps, sign tracking, a work budget and a cancellation check. It is split out intoFractionFreeDeterminantand shared rather than written twice.That is worth stating rather than doing quietly: a sign convention or an off-by-one in an elimination is a wrong answer that looks entirely plausible, and one implementation exercised by two callers is tested by both.
The condition question, which is the one the issue says to check rather than argue
Right — and the answer is that this arithmetic never touches
Entitydivision. It happens inMultivariatePolynomial, which has no quotients to leave behind at all, andDivideExactreturns null rather than a remainder. So a division that does not come out stops the elimination and sends the caller to Laplace. The answer is a polynomial in the entries, or it is Laplace's; there is no third outcome in which a quotient survives to exclude a point.That is the property #992 was about, and it is why
Determinantused Laplace in the first place: an ordinary Gaussian elimination leaves its pivots as literal divisions, so its answer is undefined wherever a pivot vanishes — at points where the determinant is perfectly well defined.What it declines
Each is a refusal to try, not a wrong answer, and Laplace answers all of them exactly as before:
sin(x),1 / x,2 ^ xeorpi: a constant is a value, not an indeterminate, and this ring cannot hold oneMeasured
The two algorithms agree on 300 generated matrices where both apply, with no disagreements — compared as a difference that simplifies to zero rather than as trees, since they group the same polynomial differently and that is not a disagreement. The test also asserts it read more than a third of what it generated, so a change that made the elimination decline everything fails here rather than passing vacuously.
The printed form of a symbolic determinant changes, because an elimination produces an expanded polynomial where Laplace produces a nested one. Recorded in
BREAKING-CHANGES.mdwith both arms measured. The expression is no larger in any case measured:[[a, b], [c, d]]a * d + -b * ca * d - b * c[[x, 1, 0], [1, x, 1], [0, 1, x]]x * (x ^ 2 + -1) + -xx ^ 3 - 2 * x[[x, 1], [1, x]],[[1/2, 1/3], [1/4, 1/5]]Failed: 0, Passed: 9154, Skipped: 14locally on net10.0.One thing found on the way
Collecting the matrix's variables by name and rebuilding them with
MathS.Varthrows on names a caller is entitled to have built —x2parses back asx ^ 2, which is the implicit-power rule the grammar has for a reason. TheVariableobjects are kept instead.🤖 Generated with Claude Code
https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura