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

Add sparse modules to update dynamics by arraylias #286

Merged
merged 22 commits into from
Nov 17, 2023

Conversation

to24toro
Copy link
Contributor

@to24toro to24toro commented Nov 7, 2023

Summary

I added some modules of jax_sparse and numpy_sparse. I wrote the code, looking at the model class and don't know if it is suite for other classes.
In order to make Operator input work, I think it is necessary to add Operator as a new type to dynamics arraylias. Maybe, we need to add list too, but I cannot conclude the necessarily of the list now because it is on going about integrating the model.

Details and comments

@DanPuzzuoli
Copy link
Collaborator

In order to make Operator input work, I think it is necessary to add Operator as a new type to dynamics arraylias.

Hmm possibly. I do know though that Operator implements __array__, so:

unp.asarray(Operator.from_label('X'))

works, and even

unp.asarray([Operator.from_label('X'), Operator.from_label('Y')])

already works as is. Maybe this is enough?

Copy link
Collaborator

@DanPuzzuoli DanPuzzuoli left a comment

Choose a reason for hiding this comment

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

Overall looks good - excited for these changes.

Comments:

  • I made a bunch of suggestions - just making sure the file and function doc strings are full sentences.
  • Can we get rid of to_numeric_matrix_type by registering a suitable default for asarray instead?
  • Do we need rmatmul anymore? I think we had set this up to originally so we could dispatch on the second argument of matmul, but we may just be able to use the _numpy_multi_dispatch function with matmul instead.

Beyond this, I guess an issue with scipy sparse is that we store lists of them in numpy arrays, e.g.

np.array([csr_matrix(...), csr_matrix(...)])

so the library inference doesn't work. One solution to this could be to define a new class with a name like SparseMatrixList that just stores the numpy object array of sparse matrices, is registered as a scipy_sparse type, and passes all ufuncs/numpy function calls through to the underlying numpy object array.

from qiskit_dynamics.type_utils import isinstance_qutip_qobj


def register_to_numeric_matrix_type(alias):
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm wondering now if this is actually necessary - this basically functions as unp.asarray except it has a default. Can we instead just register a default for asarray? I think this should work - is there some intended distinction between asarray and to_numeric_matrix_type that I'm not remembering?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. I'm just considering it, but I cannot decide it because it is used in model files I have not seen yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Certainly, I also feel we can integrate it to asarray.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps for now just remove it and we'll see if it can be replaced effectively with asarray in the model files.

qiskit_dynamics/arraylias/register_functions/to_sparse.py Outdated Show resolved Hide resolved
qiskit_dynamics/arraylias/register_functions/to_sparse.py Outdated Show resolved Hide resolved
qiskit_dynamics/arraylias/register_functions/to_dense.py Outdated Show resolved Hide resolved
qiskit_dynamics/arraylias/register_functions/to_dense.py Outdated Show resolved Hide resolved
qiskit_dynamics/arraylias/register_functions/rmatmul.py Outdated Show resolved Hide resolved
qiskit_dynamics/arraylias/register_functions/multiply.py Outdated Show resolved Hide resolved
qiskit_dynamics/arraylias/register_functions/multiply.py Outdated Show resolved Hide resolved
qiskit_dynamics/arraylias/register_functions/matmul.py Outdated Show resolved Hide resolved
qiskit_dynamics/arraylias/register_functions/matmul.py Outdated Show resolved Hide resolved
@to24toro
Copy link
Contributor Author

to24toro commented Nov 8, 2023

@to24toro
Copy link
Contributor Author

to24toro commented Nov 8, 2023

Do we need rmatmul anymore? I think we had set this up to originally so we could dispatch on the second argument of matmul, but we may just be able to use the _numpy_multi_dispatch function with matmul instead.

Yes, it makes sense but I don't think we can use _numpy_multi_dispatch which only judges whether the array type is "numpy" or "jax" not "sparse. We need to add sparse types to _prefer_libs.

@to24toro
Copy link
Contributor Author

to24toro commented Nov 8, 2023

Beyond this, I guess an issue with scipy sparse is that we store lists of them in numpy arrays, e.g.
np.array([csr_matrix(...), csr_matrix(...)])
so the library inference doesn't work. One solution to this could be to define a new class with a name like SparseMatrixList that just stores the numpy object array of sparse matrices, is registered as a scipy_sparse type, and passes all ufuncs/numpy function calls through to the underlying numpy object array.

I think the reason we want to add list type to alias is to treat such as List[spase_matrix]. Therefore, it is a good idea.

Copy link
Collaborator

@DanPuzzuoli DanPuzzuoli left a comment

Choose a reason for hiding this comment

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

Aside from the direct comments, another change I would suggest is to put the register_fallback and register_default functions together in the files (currently the default functions appear at the beginning, and the fallback functions appear at the end).

I believe these suggestions should fix the current issues. There is another problem with tests raising warnings, but I think these are the result of a JAX update possibly. I will see if I can resolve these in a separate PR.

Edit: the docs build warnings should be fixed in #287 .

qiskit_dynamics/arraylias/register_functions/asarray.py Outdated Show resolved Hide resolved
qiskit_dynamics/arraylias/register_functions/to_dense.py Outdated Show resolved Hide resolved
from qiskit_dynamics.type_utils import isinstance_qutip_qobj


def register_to_numeric_matrix_type(alias):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps for now just remove it and we'll see if it can be replaced effectively with asarray in the model files.

Copy link
Collaborator

@DanPuzzuoli DanPuzzuoli left a comment

Choose a reason for hiding this comment

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

This LGTM. The only thing missing is some tests - can you add a few test cases for the new types/functions?

Copy link
Collaborator

@DanPuzzuoli DanPuzzuoli left a comment

Choose a reason for hiding this comment

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

Thanks Kento - the tests look good. I've left a few comments.

The main thing is to add validation for the output type of the dispatched functions. I've commented in a few places, but I think this should be done everywhere.

"""Test matmul for scipy_sparse."""
x = csr_matrix([[1, 0], [0, 1]])
y = csr_matrix([[2, 2], [2, 2]])
self.assertAllClose(csr_matrix.toarray(unp.matmul(x, y)), [[2, 2], [2, 2]])
Copy link
Collaborator

Choose a reason for hiding this comment

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

validate type of unp.matmul(x, y)


x = BCOO.fromdense([[1, 0], [0, 1]])
y = BCOO.fromdense([[2, 2], [2, 2]])
self.assertAllClose(BCOO.todense(unp.matmul(x, y)), [[2, 2], [2, 2]])
Copy link
Collaborator

Choose a reason for hiding this comment

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

same thing here, validate type of unp.matmul(x, y)

from ...common import QiskitDynamicsTestCase


class TestMultiplyFunction(QiskitDynamicsTestCase):
Copy link
Collaborator

Choose a reason for hiding this comment

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

TestMatmulFunction

from ...common import QiskitDynamicsTestCase


class TestMultiplyFunction(QiskitDynamicsTestCase):
Copy link
Collaborator

Choose a reason for hiding this comment

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

TestRmatmulFunction

@DanPuzzuoli DanPuzzuoli merged commit f44c721 into qiskit-community:main Nov 17, 2023
16 checks passed
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