Skip to content

Instantly share code, notes, and snippets.

@Spacerat
Created July 20, 2026 06:58
Show Gist options
  • Select an option

  • Save Spacerat/08b4a43f6b6ca57178efabc220170ce8 to your computer and use it in GitHub Desktop.

Select an option

Save Spacerat/08b4a43f6b6ca57178efabc220170ce8 to your computer and use it in GitHub Desktop.
11 variable cubic jacobian conjecture counterexample
#!/usr/bin/env python3
r"""
AN EXPLICIT DEGREE-3 JACOBIAN COUNTEREXAMPLE IN 11 VARIABLES
============================================================
Result
------
This file gives an explicit polynomial map
Phi: C^11 -> C^11
with:
* total degree exactly 3;
* 52 nonzero monomial terms;
* constant Jacobian determinant -2;
* three distinct rational inputs with the same output.
The construction is a factor-aware stable degree reduction of the degree-7
three-variable counterexample publicly posted by Levent Alpöge. It improves a
straight monomial-by-monomial Bass-Connell-Wright reduction from 39 variables
to 11 variables by:
1. reducing shared polynomial factors simultaneously;
2. reusing previously introduced auxiliary coordinates;
3. cancelling x^2 y^2 with the square of an existing coordinate;
4. removing a one-dimensional triangular extension.
Credits and sources
-------------------
Starting counterexample (public X/Twitter post by Levent Alpöge):
https://x.com/__alpoge__/status/2079028340955197566
Reddit suggestion by u/zongshu to apply cubic degree reduction:
https://www.reddit.com/r/math/s/gtTu8JkLsS
William Garland, "An Introduction to the Jacobian Conjecture" (2018),
especially Theorem 3.3:
https://math.uchicago.edu/~may/REU2018/REUPapers/Garland.pdf
Hyman Bass, Edwin H. Connell, and David Wright,
"The Jacobian Conjecture: Reduction of Degree and Formal Expansion of the
Inverse", Bulletin of the AMS 7(2), 287-330 (1982):
https://doi.org/10.1090/S0273-0979-1982-15032-7
The explicit 11-variable construction, simplification, and verification code
in this file were generated by ChatGPT (OpenAI).
The explicit map
----------------
Use input coordinates
(x, y, z, a, b, c, d, q, s, h, k).
Then Phi = (Phi_1, ..., Phi_11), where:
Phi_1 =
-a*c - a*d*z - 3*a*y^2 - 2*a*z
- c*d^2 + d^2*z - d*s + 7*d*y^2
+ s*x*y + 3*x*y*z + 4*y^2 + z
Phi_2 =
-b*c - b*d*z - 3*b*y^2 - 2*b*z
- 3*c*d*x - d*q + q*x*y
+ 12*x*y^2 + 3*x*z + y
Phi_3 =
-h*k - h*x*z + k*x^2 - 3*x^2*y + 2*x
Phi_4 =
a - d^2 + 2*d*x*y
Phi_5 =
b + 3*x^2*y
Phi_6 =
c + x*y*z + 3*y^2 + 2*z
Phi_7 =
d - x*y
Phi_8 =
b*z + 3*c*x + q
Phi_9 =
s + a*z + c*x*y - x*y*z - 7*y^2 + c*d - d*z
Phi_10 =
h - x^2
Phi_11 =
k + x*z
Three colliding inputs
----------------------
p1 =
(0, 0, -1/4, 0, 0, 1/2, 0, 0, 0, 0, 0)
p2 =
(1, -3/2, 13/2, -9/4, 9/2, -10, -3/2, 3/4,
-153/8, 1, -13/2)
p3 =
(-1, 3/2, 13/2, -9/4, -9/2, -10, -3/2, -3/4,
-153/8, 1, 13/2)
All three map to:
(-1/4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
Why the Jacobian determinant is -2
----------------------------------
The original three-variable map has Jacobian determinant -2.
Every degree-lowering operation below is a composition of:
* stabilization by identity coordinates;
* a triangular source automorphism;
* a triangular target automorphism.
Each has Jacobian determinant 1. One additional target shear subtracts the
square of an auxiliary output and likewise has determinant 1.
The intermediate 12-variable map has two variables f,g that occur
nonlinearly only through s=f+g. After the determinant-one pair of linear
changes
inputs: f=t, g=s-t
outputs: (Y_s,Y_t)=(Phi_f+Phi_g, Phi_f),
the full map is a triangular extension of the displayed 11-variable map:
(Phi_11_variable(...), t + A(...)).
The derivative of the last coordinate with respect to t is 1, so deleting
that triangular coordinate preserves the determinant. Consequently the
displayed map has constant Jacobian determinant -2.
This file reconstructs that chain exactly and checks that the resulting
11-variable formulas equal the displayed map.
"""
from __future__ import annotations
from typing import Sequence
import sympy as sp
def total_degree(expr: sp.Expr, variables: Sequence[sp.Symbol]) -> int:
return sp.Poly(sp.expand(expr), *variables).total_degree()
def term_count(expr: sp.Expr, variables: Sequence[sp.Symbol]) -> int:
return len(sp.Poly(sp.expand(expr), *variables).terms())
def pair_step(
expressions: list[sp.Expr],
variables: list[sp.Symbol],
target: int,
left: sp.Expr,
right: sp.Expr,
left_name: str,
right_name: str,
) -> tuple[list[sp.Expr], list[sp.Symbol]]:
"""Bass-Connell-Wright product-elimination step.
Append u,v and replace a summand left*right in coordinate target by:
-(u+left)(v+right) + left*right
after stabilization. Equivalently:
target -> target - left*right - u*right - left*v - u*v
u -> u + left
v -> v + right.
"""
u = sp.Symbol(left_name)
v = sp.Symbol(right_name)
result = [sp.expand(expr) for expr in expressions]
result[target] = sp.expand(
result[target]
- left * right
- u * right
- left * v
- u * v
)
result.extend([sp.expand(u + left), sp.expand(v + right)])
return result, variables + [u, v]
def shared_right_step(
expressions: list[sp.Expr],
variables: list[sp.Symbol],
targets: Sequence[int],
left_factors: Sequence[sp.Expr],
right: sp.Expr,
left_names: Sequence[str],
right_name: str,
) -> tuple[list[sp.Expr], list[sp.Symbol]]:
"""Eliminate several products P_i*Q using one shared Q coordinate."""
left_variables = [sp.Symbol(name) for name in left_names]
right_variable = sp.Symbol(right_name)
result = [sp.expand(expr) for expr in expressions]
for target, left, u in zip(targets, left_factors, left_variables):
result[target] = sp.expand(
result[target]
- left * right
- u * right
- left * right_variable
- u * right_variable
)
result.extend(
sp.expand(u + left)
for u, left in zip(left_variables, left_factors)
)
result.append(sp.expand(right_variable + right))
return result, variables + left_variables + [right_variable]
def reuse_feature_step(
expressions: list[sp.Expr],
variables: list[sp.Symbol],
target: int,
feature_coordinate: int,
new_feature: sp.Expr,
new_name: str,
) -> tuple[list[sp.Expr], list[sp.Symbol]]:
"""Reuse an existing output u+P instead of introducing P a second time."""
new_variable = sp.Symbol(new_name)
result = [sp.expand(expr) for expr in expressions]
result[target] = sp.expand(
result[target]
- result[feature_coordinate] * (new_variable + new_feature)
)
result.append(sp.expand(new_variable + new_feature))
return result, variables + [new_variable]
# ---------------------------------------------------------------------------
# 1. Starting three-variable counterexample.
# ---------------------------------------------------------------------------
x, y, z = sp.symbols("x y z")
starting_map = [
sp.expand(
(1 + x*y)**3*z
+ y**2*(1 + x*y)*(4 + 3*x*y)
),
sp.expand(
y
+ 3*x*(1 + x*y)**2*z
+ 3*x*y**2*(4 + 3*x*y)
),
sp.expand(
2*x - 3*x**2*y - x**3*z
),
]
starting_jacobian = sp.Matrix(starting_map).jacobian([x, y, z])
assert sp.factor(starting_jacobian.det()) == -2
expressions = starting_map
variables = [x, y, z]
# ---------------------------------------------------------------------------
# 2. Shared reduction of the first two coordinates.
#
# Let S = xyz + 3y^2 + 2z. The high-degree pieces include:
#
# Phi_1: x^2 y^2 S
# Phi_2: 3 x^2 y S.
#
# One shared S coordinate handles both products.
# ---------------------------------------------------------------------------
S = x*y*z + 3*y**2 + 2*z
expressions, variables = shared_right_step(
expressions,
variables,
targets=[0, 1],
left_factors=[x**2*y**2, 3*x**2*y],
right=S,
left_names=["a", "b"],
right_name="c",
)
a, b, c = variables[-3:]
# ---------------------------------------------------------------------------
# 3. Resolve the remaining degree-4 part of coordinate 2.
#
# This creates the reusable coordinate d - xy.
# ---------------------------------------------------------------------------
expressions, variables = pair_step(
expressions,
variables,
target=1,
left=-x*y,
right=b*z + 3*c*x,
left_name="d",
right_name="q",
)
d, q = variables[-2:]
assert sp.expand(expressions[6] - (d - x*y)) == 0
# ---------------------------------------------------------------------------
# 4. Reuse d-xy to reduce the first coordinate.
# ---------------------------------------------------------------------------
R = -a*z - c*x*y + x*y*z + 7*y**2
expressions, variables = reuse_feature_step(
expressions,
variables,
target=0,
feature_coordinate=6,
new_feature=-R,
new_name="f",
)
f = variables[-1]
# Cancel x^2 y^2 in the a coordinate using (d-xy)^2.
expressions[3] = sp.expand(expressions[3] - expressions[6]**2)
# Reuse d-xy a second time to remove the final quartic term in coordinate 1.
expressions, variables = reuse_feature_step(
expressions,
variables,
target=0,
feature_coordinate=6,
new_feature=d*(c-z),
new_name="g",
)
g = variables[-1]
# ---------------------------------------------------------------------------
# 5. Resolve the degree-4 term -x^3 z in the third coordinate.
# ---------------------------------------------------------------------------
expressions, variables = pair_step(
expressions,
variables,
target=2,
left=-x**2,
right=x*z,
left_name="h",
right_name="k",
)
h, k = variables[-2:]
assert variables == [x, y, z, a, b, c, d, q, f, g, h, k]
assert len(expressions) == 12
assert max(total_degree(expr, variables) for expr in expressions) == 3
# ---------------------------------------------------------------------------
# 6. Remove the triangular f-g direction.
#
# Put f=t and g=s-t. Replace the two corresponding outputs by:
#
# Y_s = Phi_f + Phi_g
# Y_t = Phi_f.
#
# The first eleven outputs are independent of t, while Y_t=t+A(...).
# ---------------------------------------------------------------------------
s, t = sp.symbols("s t")
substitution = {f: t, g: s-t}
transformed = [sp.expand(expr.subs(substitution)) for expr in expressions]
reduced_from_construction = (
transformed[:8]
+ [sp.expand(transformed[8] + transformed[9])]
+ transformed[10:12]
)
triangular_last_output = transformed[8]
reduced_variables = [x, y, z, a, b, c, d, q, s, h, k]
assert all(not expr.has(t) for expr in reduced_from_construction)
assert sp.diff(triangular_last_output, t) == 1
# The input and output two-by-two linear changes both have determinant -1.
input_change = sp.Matrix([[0, 1], [1, -1]]) # (f,g) from (s,t)
output_change = sp.Matrix([[1, 1], [1, 0]]) # (Y_s,Y_t) from (Phi_f,Phi_g)
assert input_change.det() == -1
assert output_change.det() == -1
# ---------------------------------------------------------------------------
# 7. The concise explicit 11-variable map.
# ---------------------------------------------------------------------------
explicit_map = [
-a*c - a*d*z - 3*a*y**2 - 2*a*z
- c*d**2 + d**2*z - d*s + 7*d*y**2
+ s*x*y + 3*x*y*z + 4*y**2 + z,
-b*c - b*d*z - 3*b*y**2 - 2*b*z
- 3*c*d*x - d*q + q*x*y
+ 12*x*y**2 + 3*x*z + y,
-h*k - h*x*z + k*x**2 - 3*x**2*y + 2*x,
a - d**2 + 2*d*x*y,
b + 3*x**2*y,
c + x*y*z + 3*y**2 + 2*z,
d - x*y,
b*z + 3*c*x + q,
s + a*z + c*x*y - x*y*z - 7*y**2 + c*d - d*z,
h - x**2,
k + x*z,
]
explicit_map = [sp.expand(expr) for expr in explicit_map]
assert all(
sp.expand(left - right) == 0
for left, right in zip(reduced_from_construction, explicit_map)
)
assert len(explicit_map) == 11
assert max(total_degree(expr, reduced_variables) for expr in explicit_map) == 3
assert sum(term_count(expr, reduced_variables) for expr in explicit_map) == 52
# ---------------------------------------------------------------------------
# 8. Exact collision verification.
# ---------------------------------------------------------------------------
collision_points = [
(
sp.Rational(0),
sp.Rational(0),
sp.Rational(-1, 4),
sp.Rational(0),
sp.Rational(0),
sp.Rational(1, 2),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
),
(
sp.Rational(1),
sp.Rational(-3, 2),
sp.Rational(13, 2),
sp.Rational(-9, 4),
sp.Rational(9, 2),
sp.Rational(-10),
sp.Rational(-3, 2),
sp.Rational(3, 4),
sp.Rational(-153, 8),
sp.Rational(1),
sp.Rational(-13, 2),
),
(
sp.Rational(-1),
sp.Rational(3, 2),
sp.Rational(13, 2),
sp.Rational(-9, 4),
sp.Rational(-9, 2),
sp.Rational(-10),
sp.Rational(-3, 2),
sp.Rational(-3, 4),
sp.Rational(-153, 8),
sp.Rational(1),
sp.Rational(13, 2),
),
]
common_image = (
sp.Rational(-1, 4),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
sp.Rational(0),
)
def evaluate(point: Sequence[sp.Rational]) -> tuple[sp.Expr, ...]:
substitution = dict(zip(reduced_variables, point))
return tuple(sp.simplify(expr.subs(substitution)) for expr in explicit_map)
assert len(set(collision_points)) == 3
assert all(evaluate(point) == common_image for point in collision_points)
print("Verified explicit cubic Jacobian counterexample:")
print(" dimension: 11")
print(" degree: 3")
print(" nonzero monomial terms: 52")
print(" determinant: -2 (exact stable-equivalence certificate)")
print(" three distinct rational inputs share the image:")
print(" ", common_image)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment