Skip to content

Factor a polynomial in any number of variables (#746 item 43) - #1058

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
feat/factorisation-in-any-number-of-variables
Aug 25, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
feat/factorisation-in-any-number-of-variables

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

#1055 factored a polynomial in two variables by Kronecker's substitution, because two is the case #746 item 43 names. Nothing in the method is about two.

The exponent pair (i, j) was packed as i + s·j — a two-digit numeral in radix s. An exponent vector of any length is a numeral in mixed radix: radices d_i + 1, place values s_0 = 1, s_(i+1) = s_i · (d_i + 1). A factor has degree at most d_i in each variable because it divides the polynomial, so the map stays injective on every monomial that can appear in the polynomial or in any of its factors, whatever the number of variables.

So the encoding and decoding become loops over the variables instead of two statements, the class is KroneckerFactorization rather than BivariateFactorization, and the caller stops refusing a third variable.

What it answers now

before now
Factor("x ^ 2 - (y + z) ^ 2", "x") null (x + y + z) * (x - y - z)
Factor("x ^ 2 + 2 * x * y + y ^ 2 - z ^ 2", "x") null (x + y + z) * (x + y - z)
Factor("x * y - x - y + 1", "x") null (y - 1) * (x - 1)
Factor("(x + y) * (x + z + w)", "x") null (w + x + z) * (x + y)
Factor("(x + y) * (x + z) * (x + w)", "x") null (x + y) * (w + x) * (x + z)

Everything two-variable answers exactly as before.

The ceiling moves sharply, and it is still a refusal

The image has degree Π (d_i + 1) - 1 — a product, not a sum — against the one-variable factoriser's MaxDegree of 32. Three variables of degree 2 fit (27); four do not (81). A new test pins three shapes that factor mathematically and are declined:

(x + y + z + w) * (x - y)              degrees (2,2,1,1) -> image degree 35
(x + y) * (x + z) * (x + w) * (x + v)  degrees (4,1,1,1,1) -> image degree 79
x ^ 12 - y ^ 12                        two variables, past it on its own

A wrong answer is still not among the things this can do. Every candidate is checked by exact division before it is kept, and the assembled factors are divided back into the input. Lifting the ceiling is Hensel lifting with an evaluation homomorphism, which is a different piece of work and stays open on item 43.

Also

BREAKING-CHANGES.md held two entries disagreeing about x ^ 2 - y ^ 2 — #1053's said it is null and needs factorisation over ℚ(y), #1055's said it is (x + y) * (x - y). The second had overtaken the first without the first being updated. The earlier entry now points at the later one instead of contradicting it.

Full suite: Failed: 0, Passed: 8583, Skipped: 14, Total: 8597.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Bjumi5K7fg8yx6UK1mZTQd

Kronecker's substitution was written for two variables because that is the case
#746 item 43 names, but
nothing in it is about two. The exponent pair (i, j) was being packed as
i + s*j, which is a two-digit numeral in radix s -- and an exponent vector of
any length is a numeral in mixed radix, with radices d_i + 1 and place values
s_0 = 1, s_(i+1) = s_i * (d_i + 1). A factor has degree at most d_i in each
variable because it divides the polynomial, so the map is injective on every
monomial that can appear in the polynomial or in any of its factors, whatever
the number of variables.

So the class is now KroneckerFactorization rather than BivariateFactorization,
the encoding and the decoding are loops over the variables instead of two
statements, and the caller no longer refuses a third one.

    x ^ 2 - (y + z) ^ 2                 ->  (x + y + z) * (x - y - z)
    x ^ 2 + 2 * x * y + y ^ 2 - z ^ 2   ->  (x + y + z) * (x + y - z)
    (x + y) * (x + z) * (x + w)         ->  (x + y) * (w + x) * (x + z)

What changes with the number of variables is the ceiling, and it changes
sharply: the image has degree the product of the radices less one, not their
sum, so three variables of degree 2 fit within the one-variable factoriser's 32
and four do not. That is a refusal and never a wrong answer -- every candidate
is still checked by exact division and the assembled factors are still divided
back into the input -- and a test now pins three shapes that factor
mathematically and are declined.

BREAKING-CHANGES had two entries disagreeing about x ^ 2 - y ^ 2, the second
having overtaken the first; the earlier one now points at the later instead of
contradicting it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bjumi5K7fg8yx6UK1mZTQd
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.

2 participants