The boring definitions
A polynomial is something like x+1. “Poly” means many, “nomial” means terms. x is a term. 1 is a term. Many terms.
A function is something that takes some input and gives you some output. f(x) = x+1 is a function. If the input is 5, the output is 6. And look at the part after the equal sign. This is a polynomial function. Mathematicians like to be lazy and use cryptic names like f. But you can be descriptive and name it PlusOne.
A polynomial map is a function that takes 1 or more inputs and gives you 1 or more polynomials as output. So f(x) = x+1 is also a polynomial map. But let’s turn up the numbers and make it a bit more complicated: f(x,y) = [2x+y, x+y]. If the input is 3, 5, the output is 11, 8.
Now, some polynomial maps have an inverse. If our map has an inverse, we’d be able to input 11, 8 and get 3, 5 as the output. Is there one? Yes. It’s f(x,y) = [x−y, −x+2y]. And it doesn’t just work with 3, 5. No matter what numbers you use for x, y, passing them through the map and then the inverse always gives you back the originals.
What doesn’t have an inverse? f(x) = x² doesn’t. Because if the output is 4, the input could be either 2 or −2. We don’t know what went in originally. This function loses information.
The Jacobian conjecture
Now, there’s a test that’s supposed to tell you whether a polynomial map has an inverse. It’s called the Jacobian determinant. If the determinant is always the same number, and that number is not zero, then the map should have an inverse. Mathematicians call this the Jacobian conjecture.
Here’s a quick refresher on how to do derivatives in calculus. We only need the simplest form. Things like x³ become 3x², x² becomes 2x, 5x becomes 5, and numbers become zero. And partial derivative just means that when you do dx, you treat other variables like y and z as numbers. x²y becomes 2xy, xy becomes y, and so on.
Let’s look at our map again: f(x,y) = [2x+y, x+y]. We need to calculate 4 partial derivatives:
a. d(2x+y)/dx = 2 → how 2x+y changes when you change x
b. d(2x+y)/dy = 1 → how 2x+y changes when you change y
c. d(x+y)/dx = 1 → how x+y changes when you change x
d. d(x+y)/dy = 1 → how x+y changes when you change y
Now we arrange these 4 numbers in a 2x2 matrix:
|a b| |2 1|
|c d| = |1 1|
The determinant is just ad − bc, which is 2×1 − 1×1 = 1. A nonzero number. And sure enough, this map has an inverse, like we saw earlier.
Now let’s do the no-inverse f(x,y) = [x²,y²]:
d(x²)/dx = 2x, d(x²)/dy = 0
d(y²)/dx = 0, d(y²)/dy = 2y
The determinant is (2x)(2y) − 0×0 = 4xy. That doesn’t look like a nonzero constant number to me (it depends on x and y).
The counterexample
Now let’s look at this slightly more complicated polynomial map:
f(x,y,z) = [(1+xy)³z + y²(1+xy)(4+3xy), y + 3x(1+xy)²z + 3xy²(4+3xy), 2x - 3x²y - x³z]
Separate the 3 functions for a cleaner look:
f1 = (1+xy)³z + y²(1+xy)(4+3xy)
f2 = y + 3x(1+xy)²z + 3xy²(4+3xy)
f3 = 2x - 3x²y - x³z
First we check if the map has an inverse. If the input is 0, 1, -4:
f1 = (1+0)³(-4) + 1(1)(4+0)
= -4 + 4
= 0
f2 = 1 + 0 + 0
= 1
f3 = 0 - 0 - 0
= 0
The output is 0, 1, 0.
If the input is -2, 1, 2:
f1 = (1-2)³(2) + 1(1-2)(4-6)
= -2 + 2
= 0
f2 = 1 + 3(-2)(-1)²(2) + 3(-2)(1)(-2)
= 1 - 12 + 12
= 1
f3 = -4 - 3(4) - (-2)³(2)
= -4 - 12 + 16
= 0
The output is also 0, 1, 0. So the map does not have an inverse.
Now let’s calculate its Jacobian determinant. I’m going to write this as ruby code so you can copy and verify yourself:
# If you're allergic to calculus
# You can use WolframAlpha to calculate the derivatives
def df1_dx(x, y, z)
3*y*(1+x*y)**2 * z + y**3 * (7+6*x*y)
end
def df1_dy(x, y, z)
3*x*z*(1+x*y)**2 + 8*y + 21*x*y**2 + 12*x**2*y**3
end
def df1_dz(x, y, z)
(1+x*y)**3
end
def df2_dx(x, y, z)
3*z*(1+x*y)*(1+3*x*y) + 12*y**2 + 18*x*y**3
end
def df2_dy(x, y, z)
1 + 6*x**2*z*(1+x*y) + 24*x*y + 27*x**2*y**2
end
def df2_dz(x, y, z)
3*x*(1+x*y)**2
end
def df3_dx(x, y, z)
2 - 6*x*y - 3*x**2*z
end
def df3_dy(x, y, z)
-3*x**2
end
def df3_dz(x, y, z)
-x**3
end
# Formula at https://en.wikipedia.org/wiki/Determinant
def determinant(a,b,c,d,e,f,g,h,i)
a*(e*i - f*h) - b*(d*i - f*g) + c*(d*h - e*g)
end
10.times do
x = rand(-10..10)
y = rand(-10..10)
z = rand(-10..10)
jacob = determinant(
df1_dx(x,y,z), df1_dy(x,y,z), df1_dz(x,y,z),
df2_dx(x,y,z), df2_dy(x,y,z), df2_dz(x,y,z),
df3_dx(x,y,z), df3_dy(x,y,z), df3_dz(x,y,z)
)
puts "(#{x}, #{y}, #{z}) = #{jacob}"
end
We run the script:
(9, -7, 4) = -2
(-9, 2, -5) = -2
(9, 8, -10) = -2
(5, 7, -8) = -2
(4, 5, -6) = -2
(7, 7, 1) = -2
(2, 9, -3) = -2
(2, 0, 1) = -2
(2, 8, -7) = -2
(10, 5, -9) = -2
Holy cow. The determinant is a nonzero constant, and the map still has no inverse. After 80+ years, the Jacobian conjecture is dead.