Skip to content
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

Implement the canonical metric on the Stiefel manifold #335

Merged
merged 37 commits into from
Mar 22, 2021

Conversation

kellertuer
Copy link
Member

@kellertuer kellertuer commented Mar 6, 2021

This PR adds a second metric to the Stiefel Manifold that provides both a exp and a log map.

  • check documentation (I seem to have locally a problem with Plots/PyPlot)
  • implement tests

@kellertuer kellertuer added the preview docs Add this label if you want to see a PR-preview of the documentation label Mar 6, 2021
Copy link
Member

@sethaxen sethaxen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked at this super closely, but I had some suggestions to reduce allocations and improve efficiency

src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelEuclideanMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelEuclideanMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelEuclideanMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Show resolved Hide resolved
src/manifolds/StiefelEuclideanMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
@kellertuer
Copy link
Member Author

kellertuer commented Mar 8, 2021

Hm, setting plots to "1.6, =1.10.5" loads for the extra of Plots` in the tests - ... 1.10.6. Here locally tests run fine with 1.10.5, on Julia 1.4 this loads the last working version (1.6), but for Julia 1.5 – or maybe in general? compat constraints for extra test packages seem to be ignored.

Similarly, I can also not convince the documenters Project.toml to respect this idea.

@codecov
Copy link

codecov bot commented Mar 8, 2021

Codecov Report

Merging #335 (07d8598) into master (b3d7787) will decrease coverage by 0.01%.
The diff coverage is 97.75%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #335      +/-   ##
==========================================
- Coverage   97.63%   97.62%   -0.02%     
==========================================
  Files          74       76       +2     
  Lines        5794     5848      +54     
==========================================
+ Hits         5657     5709      +52     
- Misses        137      139       +2     
Impacted Files Coverage Δ
src/Manifolds.jl 100.00% <ø> (ø)
src/manifolds/Stiefel.jl 99.21% <ø> (-0.16%) ⬇️
src/manifolds/StiefelEuclideanMetric.jl 97.61% <97.61%> (ø)
src/manifolds/StiefelCanonicalMetric.jl 97.77% <97.77%> (ø)
src/manifolds/SymmetricPositiveDefinite.jl 100.00% <100.00%> (ø)
...anifolds/SymmetricPositiveSemidefiniteFixedRank.jl 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b3d7787...07d8598. Read the comment docs.

@kellertuer
Copy link
Member Author

I just checked your code – at one point the small/economic Q or QR was expanded to the full one, which I would avoid using a view – and I forgot one line of code.

Now testing should work and cover all new functions.

@kellertuer
Copy link
Member Author

I am not yet sure, whether the inner for loop is now correct. In the old form I

  1. forgot about the counter
  2. we lost some updates in the code optimization
  3. I think we have to do this in complex numbers

Though I am still looking for an example that

  1. is not finished before the door loop (currently our examples directly have a norm of C less than 1e-15)
  2. is within objectivity radius and indeed does invert exp.

I wrote the author of the algorithm about that last point.

@kellertuer kellertuer added the Ready-for-Review A label for pull requests that are feature-ready label Mar 11, 2021
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
test/stiefel.jl Outdated Show resolved Hide resolved
test/stiefel.jl Show resolved Hide resolved
@kellertuer
Copy link
Member Author

What is "warst"?

some strange autocorrect (German past participle of “sein” - to be) who I meant to type kwargs.

@mateuszbaran
Copy link
Member

My only issue with introducing that on a generic level is that last time I checked Julia did a relatively poor job at optimizing out kwargs. Maybe it's better now, I'll have to check it carefully before this change is made.

@kellertuer
Copy link
Member Author

Sure. I am also not 100% sure a global level would be that good, also for further usage (in algorithms say). We can keep it the current way for not, surely.

@mateuszbaran
Copy link
Member

Regarding the failure on Julia 1.4, I think it's fine to check ambiguities only on Julia >=1.5. By the way, Julia nightly also has a similar problem: JuliaLang/julia#37711 .

@kellertuer
Copy link
Member Author

Ok, I till change that as soon as I find time to look for the remaining code lines to be covered.

@sethaxen
Copy link
Member

Perhaps unrelated, but the ambiguity test stackoverflows for me on Windows only on Julia 1.5: https://github.com/JuliaManifolds/Manifolds.jl/pull/249/checks?check_run_id=2093697330#step:5:329.

@kellertuer
Copy link
Member Author

Yes, here in the checks the same happens for Julia 1.4, seems to be unrelated, though I have not yet seen how to fix that.

@kellertuer
Copy link
Member Author

So with the commit from today this should be feature complete and all new lines tested. If you could take another look and check if all changes are good and the changes are good, that would be great.

Concerning the avoidance of allocations, the only thing I had to revert is the use of svd! (back to svd) since the input matrix is still needed afterwards.

Copy link
Member

@sethaxen sethaxen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few comments and a few more allocation-reductions. There are more allocations that can be removed using e.g. qr! but I don't think they'll have a huge impact on performance, and it's less likely that qr! will be overloaded for some special matrix than qr will be.

docs/src/manifolds/stiefel.md Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Show resolved Hide resolved
n == k && return mul!(q, p, exp(A))
QR = qr(X - p * A)
BC_ext = exp([A -QR.R'; QR.R 0*I])
q .= [p Matrix(QR.Q)] * @view(BC_ext[:, 1:k])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you blockwise multiply here, then instead of the 3 allocations here, I think you can do with none.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would I do that? I twiddled so much with these few lines of code, before and after your allocation reduction (about 2 days to find that we can not use the svd!) that I don't see directly how to do this block wise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a stab at it.

src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/StiefelCanonicalMetric.jl Outdated Show resolved Hide resolved
src/manifolds/SymmetricPositiveDefinite.jl Outdated Show resolved Hide resolved
@kellertuer
Copy link
Member Author

Just a few comments and a few more allocation-reductions. There are more allocations that can be removed using e.g. qr! but I don't think they'll have a huge impact on performance, and it's less likely that qr! will be overloaded for some special matrix than qr will be.

I don't feel comfortable currently trying that after it took me two full days changing to svd! to see that it had too many side effects and made the calculation wrong, since the input matrix was still used afterwards. So my fear is not the overwriting but the side effects from working in place. Debugging this log! here is not really much fun. So if you want to give it a try, feel free to do so. I would like to not do that, to not again take a few full days getting log! back up working (possibly in the form it is now).

@kellertuer
Copy link
Member Author

Should we maybe deactivate the windows test or at least ambiguities thereon until it has come to conclusion not to do stack overflows when looking for those?

@sethaxen
Copy link
Member

Just a few comments and a few more allocation-reductions. There are more allocations that can be removed using e.g. qr! but I don't think they'll have a huge impact on performance, and it's less likely that qr! will be overloaded for some special matrix than qr will be.

I don't feel comfortable currently trying that after it took me two full days changing to svd! to see that it had too many side effects and made the calculation wrong, since the input matrix was still used afterwards. So my fear is not the overwriting but the side effects from working in place. Debugging this log! here is not really much fun. So if you want to give it a try, feel free to do so. I would like to not do that, to not again take a few full days getting log! back up working (possibly in the form it is now).

Oh, I meant to say that these changes are probably not worth the code complexity or effort. I'm sorry for not being clear.

@sethaxen
Copy link
Member

Should we maybe deactivate the windows test or at least ambiguities thereon until it has come to conclusion not to do stack overflows when looking for those?

This is probably a good idea.

Copy link
Member

@sethaxen sethaxen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming tests pass and you approve of the changes, I think this is ready to merge. Nice work!

@kellertuer kellertuer merged commit f6b302a into master Mar 22, 2021
@kellertuer kellertuer deleted the kellertuer/steifel-canonical-metric branch June 4, 2021 21:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
preview docs Add this label if you want to see a PR-preview of the documentation Ready-for-Review A label for pull requests that are feature-ready
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants