-
Notifications
You must be signed in to change notification settings - Fork 152
Implement solve (\
) for general rectangular static matrices
#1313
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
base: master
Are you sure you want to change the base?
Conversation
src/solve.jl
Outdated
R₁ = SMatrix{Sa[2], Sa[2]}(q.R[SOneTo(Sa[2]), SOneTo(Sa[2])]) | ||
R₁ \ y | ||
else | ||
q.R' * ((q.R * q.R') \ y) |
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.
q.R' * ((q.R * q.R') \ y) | |
q.R' * (q.R' \ (q.R \ y)) |
should be a lot faster, if q.R
is annotated as UpperTriangular
(you could wrap it if not).
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.
Thanks for the review, couple questions:
q.R
has dimensions (Sa[1], Sa[2])
with Sa[1] < Sa[2]
. I don't see how to use UpperTriangular
on a non-square matrix as, for example, UpperTriangular(rand(2,3))
gives ERROR: DimensionMismatch: matrix is not square: dimensions are (2, 3)
. Am I missing something?
Using the expression q.R' * (q.R' \ (q.R \ y))
you provided results in a stack overflow error, I believe because of the (q.R \ y)
which will recurse infinitely because q.R
has the same dimensions as argument a
and y
has the same dimensions as argument b
. Any suggestions to improve this are welcome
It's a good idea but why don't just copy the logic from https://github.com/JuliaLang/LinearAlgebra.jl/blob/16f64e78769d788376df0f36447affdb7b1b3df6/src/qr.jl#L700 and adapt to StaticArrays.jl? Also, I'd prefer to have the logic for wide/thin case in I also support the use of the |
Updates implementing suggestions have been pushed |
Thanks for the updates. Could you also address the last remaining point from my post? To be more specific, I think we could use the logic of |
I spent some time look at the code in Is your concern one of accuracy/correctness or performance? If my solution is correct, I would ask that it be accepted as it is many times faster than the current LinearAlgebra fallback and does not allocate, which solves issues like #1292. I could add a |
…voted QR by default in solve
I've ported that method myself and added some tests which revealed a problem. The good news is that it works fast, without any allocations (Julia can stack-allocate non-escaping mutable structs). The bad news is that LinearAlgebra by default uses pivoted QR which is necessary for rank-deficient problems (see the new test case 4). Which is slower and currently not handled correctly by So, the two remaining issues:
Could you address point 2? It's actually a matter of correctness as you can see in the failing tests. |
Thanks for the help! One new problem is that with the pivoted QR we need to permute the result from Edit: It's our |
One risk of calling a non- |
This should close #1292. Results are much faster now that it no longer falls back to LinearAlgebra.jl.
Note that in the calculation for the underdetermined case on line 77,
q.R' * ((q.R * q.R') \ y)
is an approximation for the pseudoinversepinv
which in general may be more accurate, but it also seemed a lot slower in my testing so I did not use it here. It looks like there might a better-conditioned way to calculate it using the results of the QR decomposition but I am not a linear algebra expect so some help there would be appreciated.