Jacobian Conjecture Counterexample Visualization

By Eldar · Published July 26, 2026

Symbolic verification and 3D visualization of the 2026 polynomial counterexample to the Jacobian Conjecture, showing three distinct preimages mapping to one output despite constant non-zero Jacobian determinant.

  • jacobian-conjecture
  • symbolic-math
  • 3d-visualization
  • counterexample
  • polynomial-maps
17 cells1 experiment16 views0 forks

Inside this notebook

# The Jacobian Conjecture counterexample — verified and visualized in 3D **What this notebook does.** In July 2026, mathematician Levent Alpöge (Anthropic) announced an explicit polynomial map $F:\mathbb{C}^3\to\mathbb{C}^3$ that **disproves the (generalized, $n$-variable) Jacobian Conjecture** — an open problem since 1939 — using a counterexample found with the Claude "Fable 5" model [^1]. The map has a **constant, nowhere-zero Jacobian determinant** ($-2$ everywhere), which by the inverse function theorem makes it **locally invertible at every single point** — yet **three distinct points map to the exact same output**, so the map is not globally one-to-one (and hence has no global polynomial inverse). **The Jacobian Conjecture, simply put:** if a polynomial map $F:\mathbb{K}^n \to \mathbb{K}^n$ has a Jacobian determinant that is a nonzero *constant*, must $F$ have a polynomial inverse (i.e. must it be a bijection)? It was known to be true for degree ≤ 2 and in various special/reduced cases, but remained open in general for 87 years [^1]. **The 2026 result:** false for every $n>2$. The explicit map (all coefficients real, so it is also a perfectly good real polynomial map $\mathbb{R}^3\to\mathbb{R}^3$) is $$F(x,y,z) = \Big((1+xy)^3 z + y^2(1+xy)(4+3xy),\; y + 3x(1+xy)^2 z + 3xy^2(4+3xy),\; 2x - 3x^2y - x^3 z\Big)$$ with $\det J_F \equiv -2$, and the three points $(0,0,-\tfrac14)$, $(1,-\tfrac32,\tfrac{13}{2})$, $(-1,\tfrac32,\tfrac{13}{2})$ all map to the **same** output…

%pip install -q sympy

import numpy as np
import sympy as sp
from sympy import Rational, symbols, simplify, Matrix, factor, nsimplify

import plotly.graph_objects as go
import plotly.io as pio
from plotly.subplots import make_subplots

pio.templates.default = "plotly_white"

# ---- Symbolic definition of the 2026 Jacobian-Conjecture counterexample F: C^3 -> C^3 ----
x, y, z = symbols('x y z', real=True)

u = 1 + x*y  # helper, matches the "algebraically simplified" form reported alongside the map

F1 = (1 + x*y)**3 * z + y**2 * (1 + x*y) * (4 + 3*x*y)
…
Note: you may need to restart the kernel to use updated packages.
F(x,y,z) =
⎡ 2                                    3       2                               ↪
⎣y ⋅(x⋅y + 1)⋅(3⋅x⋅y + 4) + z⋅(x⋅y + 1)   3⋅x⋅y ⋅(3⋅x⋅y + 4) + 3⋅x⋅z⋅(x⋅y + 1) ↪

↪ 2         3        2        ⎤
↪   + y  - x ⋅z - 3⋅x ⋅y + 2⋅x⎦
# ---- Jacobian matrix and determinant ----
J = F.jacobian(vars_)
detJ = sp.simplify(J.det())

print("Jacobian matrix J_F(x,y,z) =")
sp.pprint(J)
print("\ndet(J_F) simplified =", detJ)

assert detJ == -2, f"Expected constant Jacobian determinant -2, got {detJ}"
print("\n✅ Confirmed: the Jacobian determinant is the CONSTANT -2 for every (x,y,z) in R^3.")
print("   Since it is never zero, the Inverse Function Theorem guarantees F is a local")
print("   diffeomorphism (locally invertible) at EVERY point of the domain.")
Jacobian matrix J_F(x,y,z) =
⎡         3              3                              2             2        ↪
⎢      3⋅y ⋅(x⋅y + 1) + y ⋅(3⋅x⋅y + 4) + 3⋅y⋅z⋅(x⋅y + 1)         3⋅x⋅y ⋅(x⋅y + ↪
⎢                                                                              ↪
⎢     3                          2                            2                ↪
⎢9⋅x⋅y  + 6⋅x⋅y⋅z⋅(x⋅y + 1) + 3⋅y ⋅(3⋅x⋅y + 4) + 3⋅z⋅(x⋅y + 1)                 ↪
⎢…
# ---- Verify the three distinct preimages collapse to the same output (exact rational arithmetic) ----
preimages = {
    "P1": (Rational(0), Rational(0), Rational(-1, 4)),
    "P2": (Rational(1), Rational(-3, 2), Rational(13, 2)),
    "P3": (Rational(-1), Rational(3, 2), Rational(13, 2)),
}
target = sp.Matrix([Rational(-1, 4), Rational(0), Rational(0)])

print(f"{'point':<6}{'(x, y, z)':<26}{'F(x,y,z)':<30}")
outputs = {}
for name, (xv, yv, zv) in preimages.items():
    out = sp.simplify(F.subs({x: xv, y: yv, z: zv}))
    outputs[name] = out
    print(f"{name:<6}{str((xv, yv, zv)):<26}{str(tuple(out)):<30}")
    assert sp.simplify(out - target) == sp.Matrix([0, 0, 0]), f"{name} did not map to target!"

print("\n✅ Confirmed exactly (no floating point): P1, P2, P3 are three DISTINCT points in R^3,")
print(f"   yet F(P1) = F(P2) = F(P3) = {tuple(target)}  →  F is NOT globally injective.")
point (x, y, z)                 F(x,y,z)                      
P1    (0, 0, -1/4)              (-1/4, 0, 0)                  
P2    (1, -3/2, 13/2)           (-1/4, 0, 0)                  
P3    (-1, 3/2, 13/2)           (-1/4, 0, 0)                  

✅ Confirmed exactly (no floating point): P1, P2, P3 are three DISTINCT points in R^3,
   yet F(P1) = F(P2) = F(P3) = (-1/4, 0, 0)  →  F is NOT globally injective.

## Why this is a paradox (in plain language) Think of $F$ as a machine that takes a point and moves it somewhere else. The **Jacobian determinant** tells you, at each point, whether the machine "locally" behaves like a nice, non-degenerate stretch/rotate — if it's non-zero there, a tiny neighborhood around that point is squeezed/rotated into a tiny neighborhood around the image, with no folding or collapsing. Do that check at *every single point* in space and get a non-zero answer every time (here it's the same number, $-2$, everywhere) and it feels like you've checked "no folding happens anywhere" — so surely nothing from far away can double back and land on the same spot as something else... right? **Wrong — and that's exactly what makes this a genuine counterexample.** "Locally invertible at every point" is a purely **infinitesimal / neighborhood** statement — it only promises that a small ball around each point doesn't collapse *at that point*. It says nothing about what happens far away. Three completely different regions of space, $P_1$, $P_2$, and $P_3$, can each behave perfectly (no local collapsing near any of them) while their images independently drift and land on the exact same distant point. Nothing ever needs to fold, tear, or hit zero — the three "sheets" of the map simply converge from three different directions. Below we verify and then *see* this: the two side-by-side points, the point-clouds independently sliding to the same target without ever collapsin…

# ---- Numeric (fast) version of F for plotting ----
F_num = sp.lambdify((x, y, z), [F1, F2, F3], modules='numpy')

def F_np(pts):
    """pts: (...,3) array -> (...,3) array of F(pts)."""
    pts = np.asarray(pts, dtype=float)
    out = F_num(pts[..., 0], pts[..., 1], pts[..., 2])
    return np.stack(out, axis=-1)

P = {k: np.array([float(a), float(b), float(c)]) for k, (a, b, c) in preimages.items()}
target_np = np.array([float(v) for v in target])
colors = {"P1": "#2563eb", "P2": "#dc2626", "P3": "#16a34a"}
names = {"P1": "P₁ = (0, 0, -¼)", "P2": "P₂ = (1, -3/2, 13/2)", "P3": "P₃ = (-1, 3/2, 13/2)"}

# sanity check the numeric map matches the symbolic one
for k, p in P.items():
    assert np.allclose(F_np(p), target_np, atol=1e-9), f"numeric mismatch for {k}"
print("Numeric F matches symbolic F at all three preimages. Target =", target_np)
Numeric F matches symbolic F at all three preimages. Target = [-0.25  0.    0.  ]
# ---- Input space: the three distinct preimages, as its own full-size 3D plot ----
pts = np.array(list(P.values()))
pad_in = 0.25 * np.maximum(pts.max(axis=0) - pts.min(axis=0), 1.0)  # generous padding, min 1.0 per axis
rng_in = dict(
    x=[pts[:, 0].min() - pad_in[0], pts[:, 0].max() + pad_in[0]],
    y=[pts[:, 1].min() - pad_in[1], pts[:, 1].max() + pad_in[1]],
    z=[pts[:, 2].min() - pad_in[2], pts[:, 2].max() + pad_in[2]],
)

fig_in = go.Figure()

# faint connecting lines from origin to each preimage, for spatial context
for k, p in P.items():
    fig_in.add_trace(go.Scatter3d(
        x=[0, p[0]], y=[0, p[1]], z=[0, p[2]], mode='lines',
        line=dict(color=colors[k], width=2, dash='dot'),
        showlegend=False, legendgroup=k,
    ))
…
# ---- Output space: the single shared output point, as its own full-size 3D plot ----
half_out = 0.6  # box half-width around the shared target, for spatial context
rng_out = dict(
    x=[target_np[0] - half_out, target_np[0] + half_out],
    y=[target_np[1] - half_out, target_np[1] + half_out],
    z=[target_np[2] - half_out, target_np[2] + half_out],
)

fig_out = go.Figure()

# faint connecting lines from origin to the shared target, for spatial context
fig_out.add_trace(go.Scatter3d(
    x=[0, target_np[0]], y=[0, target_np[1]], z=[0, target_np[2]], mode='lines',
    line=dict(color='#555', width=2, dash='dot'), showlegend=False,
))

# all three F(P_i) coincide here — draw as concentric markers so every color is still visible
for i, (k, p) in enumerate(P.items()):
…

This is a preview. Open the live notebook to see all 17 cells with their charts and full outputs, or fork it into your own Clusy workspace.