google / TensorNetwork

A library for easy and efficient manipulation of tensor networks.
Apache License 2.0
1.8k stars 355 forks source link

Order of eigenvalues in blocksparse eigh #605

Open gevenbly opened 4 years ago

gevenbly commented 4 years ago

Currently the blocksparse eigh returns eigenvalues sorted by symmetry charge sector, then by eigenvalue size within each sector. I think it would be more consistent with the numpy version of eigh to return eigenvalues sorted by size alone (numpy eigh gives eigenvalues in increasing order by default). Having sorted eigenvalues is also more convenient in a lot of common operations (e.g. when truncating a density matrix to retain only the dominant eigenvectors, or when diagonalizing a Hamiltonian for its ground state).

This could also be handled by an optional argument to set the order, i.e. order = 'charge' for current behavior, order = 'ascending' or order = 'descending' for sorted eigenvalues.

It would be a very useful option to have eigh be able to only return a set amount of the dominant eigenvalues/eigenvectors, i.e. setting an optional argument m=6 would tell eigh to return only the 6 largest eigenvalues and their eigenvectors, consistent with the behavior of the scipy eigsh which provides this option.

mganahl commented 4 years ago

That would be easy to add, and indeed be useful. The same applies to svd and eig. I will have a look into it

gevenbly commented 4 years ago

I started to try to implement this myself. For the API, I think it would be sensible to follow eigsh and have an optional argument which that sets the order that the eigenvalues are given, which the usual options 'LA', 'SA', 'LM', 'SM' as well as an additional option 'CH' for ordering by symmetry charge.

I have some thoughts on some additional features that could be useful: (1) It could also be accept an optional threshold argument, such that eigenvalues whose magnitude are smaller than the threshold are automatically truncated (as this is a common task in many algorithms). (2) It could also accept an optional Index or Charge object, which could allow one to specify the set of charge sectors to take eigenvalues from. For instance, if I only wanted two eigenvectors/ eigenvalues from the charge=0 sector and one from the charge=1 sector, then I could pass the optional argument charges=U1Charge([0,0,1]). This functionality would make things like constructing the ground state of a Hamiltonian much easier.

mganahl commented 4 years ago

Sounds good. Would it make sense to have ther 'CH' option as addition the which flag such that eigenvalues within each sector could be ordered according to which?

mganahl commented 4 years ago

If you are working on eigh already, would you mind doing eig as well? That would essentially be a copy paste thing

mganahl commented 4 years ago

Actually, I'll be happy to do it (one has to write the tests well ...)

chaserileyroberts commented 4 years ago

Hold up lets pump the breaks on this for a second. Are you doing node.backend.eigs outside of the library? I think its unreasonable to expect users to every call the backend object, so we should think about how to access this from the tn module instead.

mganahl commented 4 years ago

I think @gevenbly is referring to tn.block_sparse.linalg.eigh, the function that implements actual diagonalization for symmetric tensors. It makes sense to add this functionality there and for now keep the interface with SymmetricBackend unchanged for now, and later on propagate the functionality up towards the end user.

chaserileyroberts commented 4 years ago

Aw ok perfect. Ignore my comment then.