-
-
Notifications
You must be signed in to change notification settings - Fork 692
Faster implementation of is_invertible() by checking full rank #39876
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
Conversation
|
Documentation preview for this PR (built with commit cce4350; changes) is ready! 🎉 |
|
Could probably be implemented for all matrix over exact fields (such as QQ) |
|
On another note, the check was originally added in #30161, since the bug has been fixed in m4rie the check in (actually it suffices to check if element at |
Hi so I've checked this note, totally agree on the checks part and adjusted accordingly. This should be reflected in the latest commit and should be ok if all checks pan out.
I've checked matrix_rational_dense and matrix_integer_dense, both of which integrated the "check full-rank" and "check square" in their |
|
This is changing behaviour: until now, for this type of matrices, one could call (I would say that this behaviour change is actually a good thing, but this means at least checking that this is not breaking anything elsewhere in Sage.) |
|
|
||
| def is_invertible(self): | ||
| """ | ||
| Return if invertible by checking full rank. |
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.
Suggestion: use the same description as the general function.
| Return if invertible by checking full rank. | |
| Return "True" if this matrix is invertible. |
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.
use ``True`` instead.
| def is_invertible(self): | ||
| """ | ||
| Return if invertible by checking full rank. | ||
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| if not self.is_invertible(): | ||
| raise ZeroDivisionError("Matrix does not have full rank.") | ||
|
|
||
| if self._nrows: |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
For some exact fields it might help, but why would it help for all of them? Here it seems to help mostly because there is no determinant method for this type of matrices, so sage is calling a slow determinant to determine if the matrix is invertible (this is my understanding after a quick review, please correct me if you have better insight). For example over prime fields or the rationals, why would this approach (computing the rank) be better than computing the determinant? |
If I follow the comment of @user202729 correctly, I think that the check that can be removed is the |
Yes I'm afraid that's right. At first I thought the check in newton_john is checking for 0 row, but on 2nd look it's checking for full rank. Will revert that change.
From what I see in either rational_dense or integer_dense, it checks for invertible still via checking square + checking full rank (though integrated somehow in different functions), even both have the determinant method. I guess that was initially designed so; no class that I know of checks for det not 0. |
The general method in In fact, for matrices in rational_dense, I'm not sure to follow. I don't see an implementation of |
The naive algorithm for determinant over (exact) field is to compute the row echelon form then multiply entries on the diagonal, and for rank is to compute the row echelon form then count number of nonzero entries on the diagonal. Both are O(n^3) but you eliminate some multiplication? Or is it because there happen to have more efficient rank method for this particular class of matrix? Or some other reason? |
Ok, I see the reasoning, thanks for the explanation. Yes we can expect several types of matrices over exact fields to use this strategy: the bulk of the work is done by the computation of some echelon form or triangularization (including "non-naive" fast PLE / PLUQ decompositions), and then the rank or determinant is deduced rather directly. For the determinant this multiplication step is only O(n) multiplications, so it should not influence performance much, except possibly in rare corner cases. For matrices over finite fields the different types in Sage (based on FFLAS-FFPACK or on M4RI or on M4RIE from what I see) all use some fast triangularization, so indeed it should be a bit cleaner to rely on the rank. On the other hand, for other types of matrices especially when coefficient growth is possible, things are less clear to me. And for matrices not over a field, one should be extra careful (e.g.
In the present case of this issue (matrix over GF(2**e)), the rank method is significantly more efficient than the determinant one, but not for a good (algorithmic) reason: this only seems to be due to the absence of a dedicated determinant method. Yesterday I checked the M4RIE code and could not find a determinant procedure there (but several fast triangularization procedures, so one can expect that adding the determinant will not be difficult). |
Okay that makes sense. My complaint is that a lot of boilerplate is added, for example the docstring need to be mostly copied. I'd rather not doing that unless absolutely necessary. So… I guess you can add a timing thing and make the test fail once determinant get fast? That or add the explanation why the method need to exist (link here). If the benchmark sounds like too much work/too flaky, the latter would be good for me also. |
Yes, that is not nice. I'm not sure how to avoid this.
Maybe that would be a good option (the other one you propose looks good as well but actually doing it looks trickier). I have seen such notes sometimes in docstrings. |
|
Probably better to do #39912 first. Then we decide whether rank is still faster than determinant(algorithm=rref) later. (though I doubt) Then we need to benchmark whether it makes sense to switch to algorithm=rref by default on other fields. If that works, the docstring duplication etc. wouldn't be needed. |
Honestly I would like to understand what does |
Following the discussion above, you will end up at this question where this was discussed, and a related issue and fix (#30161). The fix with the rank check was not complete as it still "inverts" full row rank matrices... While these links explain well what is being computed, this behaviour should probably be changed. |
|
might as well get this in, I don't see any other issue. (apart from #39911 , but not sure what can be done about that.) |
sagemathgh-39876: Faster implementation of is_invertible() by checking full rank sagemath#31274 As mentioned in the issue, a faster invertibility check for matrix in `Matrix_gf2e_dense` by checking full rank. <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> <!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method to calculate 1 + 2". --> <!-- v Describe your changes below in detail. --> <!-- v Why is this change required? What problem does it solve? --> <!-- v If this PR resolves an open issue, please link to it here. For example, "Fixes sagemath#12345". --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#39876 Reported by: Henry Wu Reviewer(s): user202729, Vincent Neiger
#31274
As mentioned in the issue, a faster invertibility check for matrix in
Matrix_gf2e_denseby checking full rank.📝 Checklist
⌛ Dependencies