Skip to content

Add faster implementation of ptrace for kets#2657

Merged
Ericgig merged 5 commits into
qutip:masterfrom
Sola85:master
Mar 25, 2025
Merged

Add faster implementation of ptrace for kets#2657
Ericgig merged 5 commits into
qutip:masterfrom
Sola85:master

Conversation

@Sola85

@Sola85 Sola85 commented Mar 20, 2025

Copy link
Copy Markdown
Contributor

Description
For my application, Qobj.ptrace() was a bottleneck, so I added a specialization for kets that is significantly faster.
The new implementation uses np.einsum to combine the computation of the outer product and the partial trace into one operation, instead of doing these two operations sequentially.

from qutip import rand_ket
from time import perf_counter

state = rand_ket([2, 3, 4, 5]*2, distribution="fill")
keep_dims = [1, 3, 7]

t0 = perf_counter()
reduced_dm2 = state.ptrace(keep_dims) # Uses new implementation
t1 = perf_counter()
print("New impementation:", t1 - t0) # ~ 0.01s on 8th-gen Intel quad-core


t0 = perf_counter()
reduced_dm1 = state.proj().ptrace(keep_dims) # Old implementation
t1 = perf_counter()
print("Old impementation:", t1 - t0) # ~ 6s on 8th-gen Intel quad-core

assert (reduced_dm1 - reduced_dm2).norm("tr") < 1e-10

In this example, the new implementation is around 600x faster on my machine.

The new implementation can also handle significantly larger states:
rand_ket([2, 3, 4, 5]*3, distribution="fill").ptrace(keep_dims) fails using the old implementation because the intermediate density matrix is too large, but the new implementation computes the result in less than 0.1s.

Note: I did not use qutip.einsum because this only seems to wrap the string-indexed version of np.einsum and not the array-indexed version. The latter is more useful is cases like the present one, since its easier do generate the einsum subscripts programatically.

@coveralls

coveralls commented Mar 20, 2025

Copy link
Copy Markdown

Coverage Status

coverage: 88.034% (+0.01%) from 88.022%
when pulling 40d759b on Sola85:master
into d5c98fe on qutip:master.

@Ericgig Ericgig left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you.
This look quite useful.

The function does not belong in tensor.py...
I know qobj.py is already too big, but it should probably come after the ptrace function already there for now. This would avoid adding a circular import.

Comment thread qutip/tests/core/test_ptrace.py Outdated
Comment thread qutip/core/tensor.py Outdated
@Sola85

Sola85 commented Mar 21, 2025

Copy link
Copy Markdown
Contributor Author

Thanks for the comments. I moved the implementation to qobj.py, added more interesting test cases and fixed the docstring.

@Ericgig Ericgig left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you!

@Ericgig Ericgig merged commit e060304 into qutip:master Mar 25, 2025
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.

3 participants