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

[Enhancement] Add singular value decomposition #16

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

lkdvos
Copy link
Contributor

@lkdvos lkdvos commented Dec 17, 2024

This PR is a migration of ITensor/ITensors.jl#1572, which aims to add support for SVDs.

Copy link

codecov bot commented Dec 17, 2024

Codecov Report

Attention: Patch coverage is 0% with 92 lines in your changes missing coverage. Please review.

Project coverage is 24.65%. Comparing base (c15f643) to head (611de00).

Files with missing lines Patch % Lines
src/factorizations/svd.jl 0.00% 43 Missing ⚠️
src/blocksparsearray/blockdiagonalarray.jl 0.00% 30 Missing ⚠️
src/BlockArraysExtensions/BlockArraysExtensions.jl 0.00% 10 Missing ⚠️
...tractblocksparsearray/abstractblocksparsematrix.jl 0.00% 9 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #16      +/-   ##
==========================================
- Coverage   27.30%   24.65%   -2.65%     
==========================================
  Files          26       29       +3     
  Lines         857      949      +92     
==========================================
  Hits          234      234              
- Misses        623      715      +92     
Flag Coverage Δ
docs ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.


# SVD implementation
function eigencopy_oftype(A::BlockDiagonal, S)
diag = map(Base.Fix2(eigencopy_oftype, S), A.blocks.diag)
Copy link
Member

Choose a reason for hiding this comment

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

We should make a proper function/API to access A.blocks.diag.

Some ideas are:

  1. eachstoredblock
  2. DiagonalArrays.diagview(blocks(a)) (from https://github.com/ITensor/DiagonalArrays.jl)

Copy link
Member

@mtfishman mtfishman Dec 18, 2024

Choose a reason for hiding this comment

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

I think ideally we would have eachstoredblock special cased to output the same thing as diagview(blocks(a)) in the case of block diagonal arrays, though that may be a more involved thing beyond this PR. It may just require defining storedvalues(a::AbstractDiagonalArray/Diagonal) = diagview(a), and then eachstoredblock(a) is already defined as storedvalues(blocks(a)) so then eachstoredblock(a) would output diagview(blocks(a)).

if isnothing(A′)
# not block-diagonal, fall back to dense case
Adense = eigencopy_oftype(A, T)
return svd!(Adense; full, alg)
Copy link
Member

Choose a reason for hiding this comment

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

Does this output an SVD object?

Copy link
Member

Choose a reason for hiding this comment

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

(I see from the definition below that it does.)

# SVD is implemented by trying to
# 1. Attempt to find a block-diagonal implementation by permuting
# 2. Fallback to AbstractBlockArray implementation via BlockedArray
function svd(
Copy link
Member

Choose a reason for hiding this comment

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

So I see this is designed around a private BlockSparseArrays.svd function, is the plan to overload LinearAlgebra.svd? Probably we should define this as:

@interface ::AbstractBlockSparseArrayInterface function svd(...)

(I would like to make the AbstractArrayInterface interface types take an ndims parameter so it could be AbstractBlockSparseMatrixInterface but that isn't supported yet) and then derive that function for LinearAlgebra.svd(::AnyAbstractBlockSparseMatrix) in the style of Derive.jl.

A::AbstractBlockSparseMatrix; full::Bool=false, alg::Algorithm=default_svd_alg(A)
)
T = LinearAlgebra.eigtype(eltype(A))
A′ = try_to_blockdiagonal(A)
Copy link
Member

Choose a reason for hiding this comment

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

I found it confusing that this is call A′ but if it is a blocked permutation it is actually a composite object of the block diagonal matrix and the block permutations, we should make that clearer in the variable name, i.e. A′_and_blockperms.

# compute block-by-block and permute back
A″, (I, J) = A′
F = svd!(eigencopy_oftype(A″, T); full, alg)
return SVD(F.U[Block.(I), Block.(J)], F.S, F.Vt)
Copy link
Member

Choose a reason for hiding this comment

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

Can I and J already be designed as lists of Block?

Copy link
Member

Choose a reason for hiding this comment

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

Actually it looks like that is already the case so it seems like Block.(...) may not be necessary.

Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit confused by this code, I would have though it would be something like:

SVD(F.U[I, :], F.S, F.Vt[:, J])

i.e. I and J are block permutations of the outer spaces but maybe I have the wrong mental model for how this function is being designed.

@mtfishman
Copy link
Member

Overall this code looks really nice and simple, thanks @lkdvos. I think this is a nice payoff for the BlockSparseArrays.jl design.

I have more of a conceptual question, how does this code handle rectangular block structures?

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

Successfully merging this pull request may close these issues.

2 participants