Skip to content

inverse of matrix is not well defined #3738

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
mahrud opened this issue Apr 18, 2025 · 5 comments
Open

inverse of matrix is not well defined #3738

mahrud opened this issue Apr 18, 2025 · 5 comments

Comments

@mahrud
Copy link
Member

mahrud commented Apr 18, 2025

I have a well defined, surjective map of non-free modules, but its inverse is not well defined. What is causing this?

n = 4
S = ZZ/11[x_0..x_(n-1)]
R = quotient minors_2 matrix { S_*_{0..n-2}, S_*_{1..n-1}}

g = map(cokernel(map(R^{3:{-3}},R^{6:{-4}},{{x_2-4*x_3, x_1, 5*x_3, x_0, 0, 0}, {-x_3, 0, x_2+4*x_3, 0, x_1, x_0}, {0,
       3*x_3, 3*x_3, 3*x_2, 3*x_2-x_3, 3*x_1-x_2}})),cokernel(map(R^{6:{-3}},R^{12:{-4}},{{2*x_2, 2*x_0+4*x_1-x_2, -5*x_2,
       2*x_2, 2*x_1+4*x_2, 2*x_1+4*x_2, 4*x_3, -5*x_1-4*x_2, -5*x_0-4*x_1, 5*x_2, 5*x_1-3*x_2, 5*x_0-3*x_1+2*x_2},
       {5*x_2+2*x_3, 5*x_0-4*x_1+5*x_2-x_3, 3*x_2-5*x_3, 5*x_2+x_3, 5*x_1-4*x_2+4*x_3, 5*x_1-4*x_2+4*x_3, 4*x_3,
       3*x_1+2*x_2-4*x_3, 3*x_0+2*x_1-5*x_2, 5*x_3, -2*x_2-3*x_3, -2*x_1-x_2+2*x_3}, {x_1, 0, 0, 0, x_0, 0, x_2, 0, 0, 0, 0,
       0}, {0, x_0, 0, x_2, 0, x_1, 4*x_3, 0, 0, 0, 0, 0}, {2*x_3, x_3, x_2+5*x_3, -2*x_3, -4*x_3, -4*x_3, 4*x_3, x_1+4*x_3,
       x_0, -5*x_3, 3*x_3, -2*x_3}, {-x_3, -x_3, -3*x_3, -5*x_3, -5*x_3, 5*x_3, 5*x_3, 4*x_3, x_3, x_2, x_1-4*x_3,
       x_0-2*x_3}})),{{4, -5, 1, 0, 0, 0}, {0, -4, 0, 1, 0, 0}, {2, -3, 0, 0, -3, 1}})

isWellDefined g and isSurjective g -- g should be invertible
(g * inverse g) == id_(target g) -- and it can be inverted
isWellDefined inverse g -- but the inverse is not well defined

isWellDefined (id_(target g) // g) -- this one works, but is much slower

cc: @Devlin-Mallory

@Devlin-Mallory
Copy link
Contributor

I think inverse g doesn't work for a map where the target is non-free, although no warning is given. In the code above, inverse g calls quotientRemainder(id_(target g), g); the first line of quotientRemainder(f, g) is L := source f; -- result may not be well defined if L is not free.

In your example, inverse g is the same matrix as inverse cover g, so I suspect it's essentially treating g as a map of free modules; the "naive" choice of inverse then may or may not respect the defining relations of the module M.

(Also, just a note that in general isWellDefined g and isSurjective g is not enough to guarantee g is invertible - this is sufficient in general only when target g is a projective module. I think maybe id_(target g) // g is the way to go.)

@mahrud
Copy link
Member Author

mahrud commented Apr 19, 2025

I agree with you in general, but in this case g is a split surjection. I'm not sure what the algorithm does exactly, but I would expect that at least in this case there should be an easier way to compute the inverse.

@mahrud
Copy link
Member Author

mahrud commented Apr 19, 2025

As you mention, id_(target g) // g works fine, but I think g \\ id_(source g) should also work, except it seems to be failing in this example:

R = ZZ/32003[x,y,z]/(x^3, x^2*y, x*y^2, y^4, y^3*z)
M = cokernel(map(R^{5:{1}, 6:{0}, 2:{-1}}, R^{7:{0}, 20:{-1}, 9:{-2}}, {{0, z, 0, y, 0, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, z, 0, y, 0, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {-x, 0, 0, 0, 0, 0, 0, x*y, 0, 0, 0, x^2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, y^2*z, 0, 0, 0, 0, y^3, 0, 0, 0}, {z, 0, 0, 0, 0, 0, 0, -y*z, y^2, 0, 0, -x*z, x*y, 0, 0, x^2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x^2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, z, -y, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, y*z, 0, 0, 0, 0, y^2, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, y, z, 0, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, y, 0, z, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, z, 0, 0, y, 0, 0, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, z, 0, 0, y, 0, 0, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, z, 0, 0, y, 0, 0, x, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -z, 0, y, 0, x, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, z, 0, 0, 0, y, x}}))
N = cokernel(map(R^{2:{1}}, R^6, {{z, y, x, 0, 0, 0}, {0, 0, 0, z, y, x}}))
g = map(N, M, {{10821, -12119, 15659, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {-7155, -15464, 7853, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}})

g * (id_N // g) -- identity
g * (g \\ id_M) -- zero!!
isWellDefined (g \\ id_M) -- true

@Devlin-Mallory
Copy link
Contributor

Devlin-Mallory commented Apr 20, 2025

Maybe I'm missing something, but I think the difference here is between being a left and right inverse.

Given g: N -> M, id_N // g asks for a map h: N -> M such that g * h is id_N, while g \ id_M asks for a map h': N -> M such that h' * g is id_M. In the example, g is a surjection with nontrivial kernel, so a right inverse can (and does) exist, while a left inverse never exists, so in particular (g \ id_M) returns 0.

(If you were trying to split an injection g, then g \ id_(source g) would be the one to use.)

@mahrud
Copy link
Member Author

mahrud commented Apr 20, 2025

Ah, of course, I drew my diagram wrong, thanks!

(The original issue still stands)

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

No branches or pull requests

2 participants