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
feat(linear_algebra): Matrix inverses for square nonsingular matrices #1816
feat(linear_algebra): Matrix inverses for square nonsingular matrices #1816
Conversation
a650ed5
to
3aeed02
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments on the PR. I haven't gone through the whole thing yet.
We use this to partition permutations in the expression for the determinant, | ||
such that each partitions sums up to `0`. | ||
-/ | ||
def mod_swap {n : Type u} [decidable_eq n] (i j : n) : setoid (perm n) := |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same as quotienting by the subgroup generated by swap i j
. This is probably a nicer statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried rewording the statement, but unfortunately it seems like the original version is easier to work with.
The argument I want to use is that the determinant is a sum adding up to 0
because the term corresponding to σ
cancels with the term corresponding to swap i j * σ
. Thus, I want to partition the permutations so that the classes are {σ, swap i j * σ}
, and then the sum over this class is x + -1 * x + 0 = 0
.
Using the quotient of group.closure {swap i j}
would then require as a first step showing that the classes are {σ, swap i j * σ}
, which was immediate from the original mod_swap
definition. (Is there a better way to show quotient_group.left_rel (group.closure {swap i j}) σ τ ↔ (σ = τ ∨ σ = swap i j * τ)
than first using group.closure {swap i j} = gpowers (swap i j) = {σ // ∃ k, σ = (swap i j)^k}
, then showing (∃ k, σ = (swap i j)^k) ↔ (∃ 0 ≤ k < order_of (swap i j), σ = (swap i j)^k) ↔ (σ = id ∨ σ = swap i j)
?) So I don't expect the change is really worth the extra work.
3bd8ddb
to
b073fd3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mostly cosmetic comments
Co-Authored-By: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com>
Co-Authored-By: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com>
Co-Authored-By: sgouezel <sebastien.gouezel@univ-rennes1.fr>
Insert space between `finset.filter` and the filter condition. Co-Authored-By: sgouezel <sebastien.gouezel@univ-rennes1.fr>
Newlines between all lemmas
Newline before 'begin'
fd7a84d
to
3a44403
Compare
This looks good to me. @ChrisHughes24, do you have more comments? |
…leanprover-community#1816) * Prove that some matrices have inverses * Finish the proof: show that the determinant is 0 if a column is repeated * Show that nonsingular_inv is also a right inverse * Cleanup and code movement * Small lemmata on transpose * WIP: some work on inverse matrices * Code cleanup and documentation * More cleanup and documentation * Generalize det_zero_of_column_eq to remove the linear order assumption * Fix linting issues. * Unneeded import can be removed * A little bit more cleanup * Generalize nonsing_inv to any ring with inverse * Improve comments for `nonsingular_inverse` * Remove the less general `det_zero_of_column_eq_of_char_ne_two` proof * Rename `cramer_map_val` -> `cramer_map_def` Co-Authored-By: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com> * whitespace Co-Authored-By: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com> * whitespace: indent tactic proofs * More renaming `cramer_map_val` -> `cramer_map_def` * `swap_mul_self_mul` can be a `simp` lemma * Make parameter σ to `swap_mul_eq_iff` implicit * Update usage of `function.update_same` and `function.update_noteq` * Replace `det_permute` with `det_permutation` Although the statement now gives the determinant of a permutation matrix, the proof is easier if we write it as a permuted identity matrix. Thus the proof is basically the same, except a different line showing that the entries are the same. * Re-introduce `matrix.det_permute` (now based on `matrix.det_permutation`) * Delete `cramer_at` and clean up the proofs depending on it * Replace `cramer_map` with `cramer` after defining `cramer` * Apply suggestions from code review Co-Authored-By: sgouezel <sebastien.gouezel@univ-rennes1.fr> * Clean up imports * Formatting: move } to previous lines * Move assumptions of `det_zero_of_repeated_column` from variable to argument * whitespace Insert space between `finset.filter` and the filter condition. Co-Authored-By: sgouezel <sebastien.gouezel@univ-rennes1.fr> * Improve docstrings * Make argument to `prod_cancels_of_partition_cancels` explicit * Rename `replace_column` and `replace_row` to `update_column` and `update_row` * Replace `update_column_eq` with `update_column_self` + rewriting step * whitespace Newlines between all lemmas * whitespace Newline before 'begin' * Fix conflicts with latest mathlib * Remove unnecessary explicitification of arguments Co-authored-by: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com> Co-authored-by: sgouezel <sebastien.gouezel@univ-rennes1.fr> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
…leanprover-community#1816) * Prove that some matrices have inverses * Finish the proof: show that the determinant is 0 if a column is repeated * Show that nonsingular_inv is also a right inverse * Cleanup and code movement * Small lemmata on transpose * WIP: some work on inverse matrices * Code cleanup and documentation * More cleanup and documentation * Generalize det_zero_of_column_eq to remove the linear order assumption * Fix linting issues. * Unneeded import can be removed * A little bit more cleanup * Generalize nonsing_inv to any ring with inverse * Improve comments for `nonsingular_inverse` * Remove the less general `det_zero_of_column_eq_of_char_ne_two` proof * Rename `cramer_map_val` -> `cramer_map_def` Co-Authored-By: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com> * whitespace Co-Authored-By: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com> * whitespace: indent tactic proofs * More renaming `cramer_map_val` -> `cramer_map_def` * `swap_mul_self_mul` can be a `simp` lemma * Make parameter σ to `swap_mul_eq_iff` implicit * Update usage of `function.update_same` and `function.update_noteq` * Replace `det_permute` with `det_permutation` Although the statement now gives the determinant of a permutation matrix, the proof is easier if we write it as a permuted identity matrix. Thus the proof is basically the same, except a different line showing that the entries are the same. * Re-introduce `matrix.det_permute` (now based on `matrix.det_permutation`) * Delete `cramer_at` and clean up the proofs depending on it * Replace `cramer_map` with `cramer` after defining `cramer` * Apply suggestions from code review Co-Authored-By: sgouezel <sebastien.gouezel@univ-rennes1.fr> * Clean up imports * Formatting: move } to previous lines * Move assumptions of `det_zero_of_repeated_column` from variable to argument * whitespace Insert space between `finset.filter` and the filter condition. Co-Authored-By: sgouezel <sebastien.gouezel@univ-rennes1.fr> * Improve docstrings * Make argument to `prod_cancels_of_partition_cancels` explicit * Rename `replace_column` and `replace_row` to `update_column` and `update_row` * Replace `update_column_eq` with `update_column_self` + rewriting step * whitespace Newlines between all lemmas * whitespace Newline before 'begin' * Fix conflicts with latest mathlib * Remove unnecessary explicitification of arguments Co-authored-by: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com> Co-authored-by: sgouezel <sebastien.gouezel@univ-rennes1.fr> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This splits out `row`/`col`/`updateRow`/`updateColumn` to their own file, as `Data/Matrix/Basic` is getting rather large. The copyright comes from leanprover-community/mathlib#1816 and leanprover-community/mathlib#2480 There are no new lemmas in this PR, nor were any existing lemmas deleted. It's possible that even more lemmas could migrate to this new file (for instance, flipping the import with `Matrix.Notation` or `LinearAlgebra.Matrix.Trace`), but I've taken the conservative option of leaving those lemmas alone for now.
This is intended as a first step towards defining the generic matrix inverse function. The function
nonsing_inv
applied to a square matrixA
gives its inverse, as long asA.det
is invertible. The more general pseudoinverse, which is also defined for singular / non-square matrices, should be defined in terms of thisnonsing_inv
, but that will be another pull request. I also propose thathas_inv (matrix n n R)
should be used for the pseudoinverse (but both should take the same value if they are (well-)defined).The computation of the inverse is done via Cramer's rule, which is definitely not the most optimized way. It should still be computable in a reasonable time, and the correctness proof of Cramer's rule is not too long.
TO CONTRIBUTORS:
Make sure you have:
If this PR is related to a discussion on Zulip, please include a link in the discussion.
For reviewers: code review check list