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 Qobj method for getting data as a numpy array shaped like a tensor rather than an array #2353

Open
nlupugla opened this issue Mar 18, 2024 · 4 comments

Comments

@nlupugla
Copy link

Problem Description

There is no built in method for converting a Qobj into a numpy array such that the shape of the numpy array reflects the dims of the Qobj. While fixing this is a oneliner with np.reshape, there are many opportunities for mistakes here, such as making sure the numpy reshape convention (row-major or column-major) matches the Qutip convention.

Proposed Solution

Add a full_tensor and get_data_tensor method to Qobj which behave like full and get_data except the returned numpy array has a shape equal to dims flattened into a 1D list.

Alternate Solutions

Instead of a new method, full and get_data could be given an optional parameter keep_shape: bool = false

Additional Context

No response

@Ericgig
Copy link
Member

Ericgig commented Mar 18, 2024

In the development version qutip.core.dimensions.to_tensor_rep does just that.
I would be easy to add to a Qobj method.

In the release version, dims_to_tensor_perm and dims_to_tensor_shape can be used to create the array.

@nlupugla
Copy link
Author

Ah, that would be great!

Thanks for pointing out those other functions as well.

In the release version, would the implementation be something like the following?

np.transpose(np.reshape(my_qobj.full(), dims_to_tensor_shape(my_qobj.dims)), dims_to_tensor_perm(my_qobj.dims))

Do I perhaps want the inverse permutation of dims_to_tensor_perm? Should the numpy reshape use 'F' for the order parameter?

@Ericgig
Copy link
Member

Ericgig commented Mar 18, 2024

It seems fine like this.

@nlupugla
Copy link
Author

I'll add that it might be worth addressing the fact that there are two common conventions for representing quantum states as tensors that each have their pros and cons. Perhaps this would be better placed in a separate issue, but I'll explain here anyway.

Consider a joint state like $|\psi_1 \psi_2 \rangle \langle \psi_3 \psi_4 |$ where the dimensions of $|\psi_i\rangle$ are $d_i$.

Two common representations of this abstract state as a tensor are

  1. $(|\psi_1\rangle \otimes |\psi_2\rangle) \otimes (\langle \psi_3| \otimes \langle \psi_4|)$, which has shape $(d_1, d_2, d_3, d_4)$
  2. $(|\psi_1\rangle \otimes \langle \psi_3|) \otimes (|\psi_2\rangle \otimes \langle \psi_4|)$, which has shape $(d_1, d_3, d_2, d_4)$.

These two conventions essentially correspond to the "super" and "choi" representations for channels. Representation 1. is nice when you are doing most of your calculations with pure states, but then want a density matrix towards the end, which you can do with just np.tensordot(my_ket_tensor, np.conj(my_ket_tensor), 0). Representation 2. is nice when you are working with density matrices and want to combine multiple subsystems, which you can do with np.tensordot(my_density_tensor_1, my_density_tensor_2, 0). Doing either of these operations in the other representation involves very error-prone index permutation in my experience.

When I said above that these two conventions should be "addressed" in some way, I was intentionally vague because I'm honestly not sure what the best way to do that would be. One option would be to simply mention it in the user guide somewhere, perhaps near the section on the Super and Choi representations. Another would be to support both conventions via optional parameters like to_tensor_rep(my_qobj, convention='super') or to_tensor_rep(my_qobj, convention='choi').

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants