-
Notifications
You must be signed in to change notification settings - Fork 8
Bath compression #228
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
Open
kbidzhiev
wants to merge
26
commits into
main
Choose a base branch
from
kb/bath_compression
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Bath compression #228
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
e40320f
minor preparation
kbidzhiev 725752e
deep copy
kbidzhiev 84c092d
Merge branch 'main' of github.com:pasqal-io/emulators into kb/bath_co…
kbidzhiev adf7b31
preliminary res
kbidzhiev 1b37a83
packed class
kbidzhiev 6b36929
Merge branch 'main' of github.com:pasqal-io/emulators into kb/bath_co…
kbidzhiev 785924a
packed
kbidzhiev d781945
rm unused functions
kbidzhiev a0c6860
Merge branch 'kb/bath_compression' of github.com:pasqal-io/emulators …
kbidzhiev a17f92d
tests
kbidzhiev 691d870
dealloc
kbidzhiev ccdb8d6
shrinked code
kbidzhiev 726f5b6
dmrg test
kbidzhiev c976925
Merge branch 'main' into kb/bath_compression
kbidzhiev 6c87844
better naming for internals
kbidzhiev f96b095
append shorter expression
kbidzhiev ae6a3d7
tests and BathNode alias
kbidzhiev 652c331
diff shape
kbidzhiev 8b0f2a3
docstring
kbidzhiev 63e695c
shorter init_baths
kbidzhiev 496cd4f
rm comment
kbidzhiev a10653f
Merge branch 'main' into kb/bath_compression
kbidzhiev 8d02101
Merge branch 'main' into kb/bath_compression
a-quelle-pasqal 48f3faa
fix memory issue
a-quelle-pasqal b11037c
Merge branch 'main' into kb/bath_compression
a-quelle-pasqal e83deaf
change tensor init order
a-quelle-pasqal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,26 +1,28 @@ | ||
| from .constants import DEVICE_COUNT | ||
| from .pulser_adapter import PulserData, HamiltonianType, SequenceData | ||
| from .math.brents_root_finding import find_root_brents | ||
| from .math.krylov_exp import krylov_exp, DEFAULT_MAX_KRYLOV_DIM | ||
| from .jump_lindblad_operators import compute_noise_from_lindbladians | ||
| from .math.brents_root_finding import find_root_brents | ||
| from .math.krylov_exp import DEFAULT_MAX_KRYLOV_DIM, krylov_exp | ||
| from .math.matmul import matmul_2x2_with_batched | ||
| from .utils import get_max_rss, apply_measurement_errors, unix_like, init_logging | ||
| from .math.packed_tensor import PackedHermitianTensor | ||
| from .pulser_adapter import HamiltonianType, PulserData, SequenceData | ||
| from .utils import apply_measurement_errors, get_max_rss, init_logging, unix_like | ||
|
|
||
| __all__ = [ | ||
| "__version__", | ||
| "get_max_rss", | ||
| "compute_noise_from_lindbladians", | ||
| "matmul_2x2_with_batched", | ||
| "DEFAULT_MAX_KRYLOV_DIM", | ||
| "DEVICE_COUNT", | ||
| "HamiltonianType", | ||
| "PackedHermitianTensor", | ||
| "PulserData", | ||
| "SequenceData", | ||
| "apply_measurement_errors", | ||
| "compute_noise_from_lindbladians", | ||
| "find_root_brents", | ||
| "get_max_rss", | ||
| "init_logging", | ||
| "krylov_exp", | ||
| "HamiltonianType", | ||
| "DEFAULT_MAX_KRYLOV_DIM", | ||
| "DEVICE_COUNT", | ||
| "apply_measurement_errors", | ||
| "matmul_2x2_with_batched", | ||
| "unix_like", | ||
| "init_logging", | ||
| ] | ||
|
|
||
| __version__ = "2.9.1" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import torch | ||
|
|
||
|
|
||
| class PackedHermitianTensor: | ||
| """ | ||
| Pack a tensor of shape (χ, m, χ), Hermitian in axes 0 and 2, | ||
| into shape (χ(χ+1)/2, m) by storing the lower triangle | ||
| of each (χ, χ) slice at fixed middle index m. | ||
| The `PackedHermitianTensor` is used to represent left and right | ||
| baths nodes in TDVP/DMRG algorithms. | ||
| """ | ||
|
|
||
| def __init__( | ||
| self, | ||
| chi: int, | ||
| m: int, | ||
| *, | ||
| check_hermitian: bool = True, | ||
| rtol: float = 1e-5, | ||
| atol: float = 1e-8, | ||
| ) -> None: | ||
| self._packed_data = torch.zeros( | ||
| int(chi * (chi + 1) / 2), m, dtype=torch.complex128 | ||
| ) | ||
| self.check_hermitian = check_hermitian | ||
| self.rtol = rtol | ||
| self.atol = atol | ||
| self.chi = chi | ||
| self.m = m | ||
|
|
||
| def pack(self, h: torch.Tensor) -> None: | ||
| if h.ndim != 3 or h.shape[0] != h.shape[2]: | ||
| raise ValueError(f"Expected shape (χ, m, χ), got {tuple(h.shape)}") | ||
| if self.chi != h.shape[0] or self.m != h.shape[1]: | ||
| raise ValueError( | ||
| f"Initialized for ({self.chi},{self.m},{self.chi}), got {h.shape}" | ||
| ) | ||
|
|
||
| if self.check_hermitian and not torch.allclose( | ||
| h, h.transpose(0, 2).conj(), rtol=self.rtol, atol=self.atol | ||
| ): | ||
| raise ValueError("Tensor is not Hermitian in axes 0 and 2") | ||
|
|
||
| self._ii, self._kk = torch.tril_indices(self.chi, self.chi, device=h.device) | ||
| self._packed_data[:, :] = h[self._ii, :, self._kk] | ||
| self._packed_data = self._packed_data.to(h.device) | ||
|
|
||
| def unpack(self) -> torch.Tensor: | ||
| vals = self._packed_data | ||
| m = vals.shape[1] | ||
|
|
||
| h = torch.zeros( | ||
| (self.chi, m, self.chi), | ||
| dtype=self._packed_data.dtype, | ||
| device=self._packed_data.device, | ||
| ) | ||
| h[self._ii, :, self._kk] = vals | ||
|
|
||
| offdiag = self._ii != self._kk | ||
| h[self._kk[offdiag], :, self._ii[offdiag]] = vals[offdiag].conj() | ||
| return h |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| import pytest | ||
| import torch | ||
| from emu_base import PackedHermitianTensor | ||
|
|
||
|
|
||
| def test_roundtrip(): | ||
| n, b = 4, 3 | ||
| x = torch.randn(n, b, n, dtype=torch.complex64) | ||
| h = 0.5 * (x + x.transpose(0, 2).conj()) | ||
|
|
||
| packedht = PackedHermitianTensor(h) | ||
| h2 = packedht.unpack() | ||
|
|
||
| assert h2.shape == h.shape | ||
| assert torch.allclose(h2, h) | ||
|
|
||
|
|
||
| def test_rejects_non_hermitian(): | ||
| h = torch.randn(3, 2, 3, dtype=torch.complex64) | ||
|
|
||
| with pytest.raises(ValueError, match="not Hermitian"): | ||
| PackedHermitianTensor(h) | ||
|
|
||
|
|
||
| def test_rejects_wrong_shape(): | ||
| h = torch.randn(3, 2, 4) | ||
|
|
||
| with pytest.raises(ValueError, match="Expected shape"): | ||
| PackedHermitianTensor(h) | ||
|
|
||
|
|
||
| def test_packed_shape(): | ||
| n, b = 4, 3 | ||
| x = torch.randn(n, b, n, dtype=torch.complex64) | ||
| h = 0.5 * (x + x.transpose(0, 2).conj()) | ||
|
|
||
| packedht = PackedHermitianTensor(h) | ||
|
|
||
| assert packedht._packed_data.shape == (n * (n + 1) / 2, b) | ||
|
|
||
|
|
||
| def test_unpack_preserves_dtype(): | ||
| n, b = 4, 2 | ||
| x = torch.randn(n, b, n, dtype=torch.complex128) | ||
| h = 0.5 * (x + x.transpose(0, 2).conj()) | ||
|
|
||
| packedht = PackedHermitianTensor(h) | ||
| h2 = packedht.unpack() | ||
|
|
||
| assert h2.dtype == h.dtype | ||
|
|
||
|
|
||
| def test_skip_hermitian_check(): | ||
| # check_hermitian=False is needed for hot paths: this test ensures the | ||
| # class accepts structurally valid input without paying for symmetry checks. | ||
| h = torch.randn(3, 2, 3, dtype=torch.complex64) | ||
|
|
||
| # the tensor above should not pass for `check_hermitian=True` | ||
| packedht = PackedHermitianTensor(h, check_hermitian=False) | ||
|
|
||
| # Data loss happened | ||
| assert packedht._packed_data.shape == (6, 2) | ||
|
|
||
|
|
||
| def test_packed_is_contiguous(): | ||
| n, b = 4, 3 | ||
| x = torch.randn(n, b, n, dtype=torch.complex64) | ||
| h = 0.5 * (x + x.transpose(0, 2).conj()) | ||
|
|
||
| packedht = PackedHermitianTensor(h) | ||
|
|
||
| assert packedht._packed_data.is_contiguous() | ||
|
|
||
|
|
||
| def test_custom_tolerance_controls_hermitian_check(): | ||
| n, b = 4, 2 | ||
| x = torch.randn(n, b, n, dtype=torch.complex64) | ||
| h = 0.5 * (x + x.transpose(0, 2).conj()) | ||
|
|
||
| h_perturbed = h.clone() | ||
| h_perturbed[0, 0, 1] += 1e-4 | ||
|
|
||
| with pytest.raises(ValueError, match="not Hermitian"): | ||
| # Not convertable within given tolerance | ||
| PackedHermitianTensor(h_perturbed, atol=1e-8) | ||
|
|
||
| PackedHermitianTensor(h_perturbed, atol=1e-3) | ||
|
|
||
|
|
||
| def test_rejects_non_3d_input(): | ||
| h = torch.randn(3, 3) | ||
|
|
||
| with pytest.raises(ValueError, match="Expected shape"): | ||
| PackedHermitianTensor(h) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the file is sorted in alphabetic order