emu-mps 2.0.0__py3-none-any.whl → 2.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
emu_mps/__init__.py CHANGED
@@ -13,6 +13,7 @@ from .mps_config import MPSConfig
13
13
  from .mpo import MPO
14
14
  from .mps import MPS, inner
15
15
  from .mps_backend import MPSBackend
16
+ from .observables import EntanglementEntropy
16
17
  from emu_base import aggregate
17
18
 
18
19
 
@@ -33,6 +34,7 @@ __all__ = [
33
34
  "EnergyVariance",
34
35
  "EnergySecondMoment",
35
36
  "aggregate",
37
+ "EntanglementEntropy",
36
38
  ]
37
39
 
38
- __version__ = "2.0.0"
40
+ __version__ = "2.0.1"
emu_mps/mps.py CHANGED
@@ -307,6 +307,25 @@ class MPS(State[complex, torch.Tensor]):
307
307
  """
308
308
  return torch.abs(self.inner(other)) ** 2 # type: ignore[no-any-return]
309
309
 
310
+ def entanglement_entropy(self, mps_site: int) -> torch.Tensor:
311
+ """
312
+ Returns
313
+ the Von Neumann entanglement entropy of the state `mps` at the bond between sites b and b+1
314
+ S = -Σᵢsᵢ² log(sᵢ²)),
315
+ where sᵢ are the singular values at the chosen bond.
316
+ """
317
+ self.orthogonalize(mps_site)
318
+
319
+ # perform svd on reshaped matrix at site b
320
+ matrix = self.factors[mps_site].flatten(end_dim=1)
321
+ s = torch.linalg.svdvals(matrix)
322
+
323
+ s_e = torch.Tensor(torch.special.entr(s**2))
324
+ s_e = torch.sum(s_e)
325
+
326
+ self.orthogonalize(0)
327
+ return s_e.cpu()
328
+
310
329
  def get_memory_footprint(self) -> float:
311
330
  """
312
331
  Returns the number of MBs of memory occupied to store the state
@@ -151,14 +151,14 @@ class MPSBackendImpl:
151
151
  def __getstate__(self) -> dict:
152
152
  for obs in self.config.observables:
153
153
  obs.apply = MethodType(type(obs).apply, obs) # type: ignore[method-assign]
154
- d = self.__dict__
154
+ d = self.__dict__.copy()
155
155
  # mypy thinks the method below is an attribute, because of the __getattr__ override
156
156
  d["results"] = self.results._to_abstract_repr() # type: ignore[operator]
157
157
  return d
158
158
 
159
159
  def __setstate__(self, d: dict) -> None:
160
- d["results"] = Results._from_abstract_repr(d["results"]) # type: ignore [attr-defined]
161
160
  self.__dict__ = d
161
+ self.results = Results._from_abstract_repr(d["results"]) # type: ignore [attr-defined]
162
162
  self.config.monkeypatch_observables()
163
163
 
164
164
  @staticmethod
@@ -444,7 +444,6 @@ class MPSBackendImpl:
444
444
  basename = self.autosave_file
445
445
  with open(basename.with_suffix(".new"), "wb") as file_handle:
446
446
  pickle.dump(self, file_handle)
447
-
448
447
  if basename.is_file():
449
448
  os.rename(basename, basename.with_suffix(".bak"))
450
449
 
emu_mps/observables.py ADDED
@@ -0,0 +1,40 @@
1
+ from pulser.backend.state import State
2
+ from pulser.backend.observable import Observable
3
+ from emu_mps.mps import MPS
4
+ from typing import Sequence, Any
5
+ import torch
6
+
7
+
8
+ class EntanglementEntropy(Observable):
9
+ """Entanglement Entropy subclass used only in emu_mps"""
10
+
11
+ def __init__(
12
+ self,
13
+ mps_site: int,
14
+ *,
15
+ evaluation_times: Sequence[float] | None = None,
16
+ tag_suffix: str | None = None,
17
+ ):
18
+ super().__init__(evaluation_times=evaluation_times, tag_suffix=tag_suffix)
19
+ self.mps_site = mps_site
20
+
21
+ @property
22
+ def _base_tag(self) -> str:
23
+ return "entanglement_entropy"
24
+
25
+ def _to_abstract_repr(self) -> dict[str, Any]:
26
+ repr = super()._to_abstract_repr()
27
+ repr["mps_site"] = self.mps_site
28
+ return repr
29
+
30
+ def apply(self, *, state: State, **kwargs: Any) -> torch.Tensor:
31
+ if not isinstance(state, MPS):
32
+ raise NotImplementedError(
33
+ "Entanglement entropy observable is only available for emu_mps emulator."
34
+ )
35
+ if not (0 <= self.mps_site <= len(state.factors) - 2):
36
+ raise ValueError(
37
+ f"Invalid bond index {self.mps_site}. "
38
+ f"Expected value in range 0 <= bond_index <= {len(state.factors)-2}."
39
+ )
40
+ return state.entanglement_entropy(self.mps_site)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: emu-mps
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: Pasqal MPS based pulse emulator built on PyTorch
5
5
  Project-URL: Documentation, https://pasqal-io.github.io/emulators/
6
6
  Project-URL: Repository, https://github.com/pasqal-io/emulators
@@ -25,7 +25,7 @@ Classifier: Programming Language :: Python :: 3.10
25
25
  Classifier: Programming Language :: Python :: Implementation :: CPython
26
26
  Classifier: Programming Language :: Python :: Implementation :: PyPy
27
27
  Requires-Python: >=3.10
28
- Requires-Dist: emu-base==2.0.0
28
+ Requires-Dist: emu-base==2.0.1
29
29
  Description-Content-Type: text/markdown
30
30
 
31
31
  <div align="center">
@@ -1,18 +1,19 @@
1
- emu_mps/__init__.py,sha256=N7maf5x7U6ewsK1hMebl0OBga9dSB0NoesSbtKtgN0c,662
1
+ emu_mps/__init__.py,sha256=GIR0FJOvmMHby7Vx_Da3w7YqqLpOxa0E8E3poxXsapY,734
2
2
  emu_mps/algebra.py,sha256=ngPtTH-j2ZCBWoaJZXlkUyIlug7dY7Q92gzfnRlpPMA,5485
3
3
  emu_mps/custom_callback_implementations.py,sha256=CUs0kW3HRaPE7UeFNQOFbeWJMsz4hS2q4rgS57BBp-A,2411
4
4
  emu_mps/hamiltonian.py,sha256=LcBs6CKBb643a1e9AAVtQoUfa4L_0dIhLOKecx5OOWs,15864
5
5
  emu_mps/mpo.py,sha256=wSonS6i3zEt3yRTgyZ7F6vT51pUKavFcLOxFFphBv8k,8793
6
- emu_mps/mps.py,sha256=3g-iL8ZpLd2ueMFXlFgY2qk3CEf8_cd4UEm8TDOAxRI,18972
6
+ emu_mps/mps.py,sha256=KqAjo-nxgM-xQSg1NFNchwXKoPRcrKuuycFMsWr7iX8,19610
7
7
  emu_mps/mps_backend.py,sha256=_3rlg6XeI4fHaDiJRfPL6pDkX9k48hAHKXd8fkvkOFs,2004
8
- emu_mps/mps_backend_impl.py,sha256=tg-ZMXmQNU5CeT4fi9yVhuHrJ35Nt4qi2l-UtEgAFOE,22952
8
+ emu_mps/mps_backend_impl.py,sha256=M_do7QRBLAoHfwF_EpyMCb6g7w7BSs5hsPa5UE0z9Zs,22958
9
9
  emu_mps/mps_config.py,sha256=89nu5OhNUX31eAeeYvvKnAHegpPVD43jH5Nmp635HVU,6984
10
10
  emu_mps/noise.py,sha256=h4X2EFjoC_Ok0gZ8I9wN77RANXaVehTBbjkcbY_GAmY,784
11
+ emu_mps/observables.py,sha256=7GQDH5kyaVNrwckk2f8ZJRV9Ca4jKhWWDsOCqYWsoEk,1349
11
12
  emu_mps/tdvp.py,sha256=pIQ2NXA2Mrkp3elhqQbX3pdJVbtKkG3c5r9fFlJo7pI,5755
12
13
  emu_mps/utils.py,sha256=BqRJYAcXqprtZVJ0V_j954ON2bhTdtZiaTojsYyrWrg,8193
13
14
  emu_mps/optimatrix/__init__.py,sha256=lHWYNeThHp57ZrwTwXd0p8bNvcCv0w_AZ31iCWflBUo,226
14
15
  emu_mps/optimatrix/optimiser.py,sha256=7j9_jMQC-Uh2DzdIVB44InRzZO6AbbGhvmm7lC6N3tk,6737
15
16
  emu_mps/optimatrix/permutations.py,sha256=JRXGont8B4QgbkV9CzrA0w7uzLgBrmZ1J9aa0G52hPo,1979
16
- emu_mps-2.0.0.dist-info/METADATA,sha256=Is92e2JsE9NzvRFbpsI44W16pmVm-bJq-pQd7g736Ss,3505
17
- emu_mps-2.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
- emu_mps-2.0.0.dist-info/RECORD,,
17
+ emu_mps-2.0.1.dist-info/METADATA,sha256=aGt2cFa9rplEaJAo8z4J5uoAkqq9WnQIlOhciUc6vkg,3505
18
+ emu_mps-2.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
19
+ emu_mps-2.0.1.dist-info/RECORD,,