emu-base 2.4.2__py3-none-any.whl → 2.4.4__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_base/__init__.py CHANGED
@@ -4,7 +4,7 @@ from .math.brents_root_finding import find_root_brents
4
4
  from .math.krylov_exp import krylov_exp, DEFAULT_MAX_KRYLOV_DIM
5
5
  from .jump_lindblad_operators import compute_noise_from_lindbladians
6
6
  from .math.matmul import matmul_2x2_with_batched
7
- from .utils import get_max_rss, apply_measurement_errors, unix_like
7
+ from .utils import get_max_rss, apply_measurement_errors, unix_like, init_logging
8
8
 
9
9
  __all__ = [
10
10
  "__version__",
@@ -19,6 +19,7 @@ __all__ = [
19
19
  "DEVICE_COUNT",
20
20
  "apply_measurement_errors",
21
21
  "unix_like",
22
+ "init_logging",
22
23
  ]
23
24
 
24
- __version__ = "2.4.2"
25
+ __version__ = "2.4.4"
@@ -2,59 +2,91 @@ from pulser.noise_model import NoiseModel
2
2
  import torch
3
3
  import math
4
4
 
5
+ dtype = torch.complex128
6
+
5
7
 
6
8
  def get_lindblad_operators(
7
- *, noise_type: str, noise_model: NoiseModel
9
+ *,
10
+ noise_type: str,
11
+ noise_model: NoiseModel,
12
+ interact_type: str = "ising",
13
+ dim: int = 2,
8
14
  ) -> list[torch.Tensor]:
15
+
9
16
  assert noise_type in noise_model.noise_types
10
17
 
11
18
  if noise_type == "relaxation":
12
19
  c = math.sqrt(noise_model.relaxation_rate)
13
- return [
14
- torch.tensor([[0, c], [0, 0]], dtype=torch.complex128),
15
- ]
20
+ relaxation = torch.zeros(dim, dim, dtype=dtype)
21
+ relaxation[0, 1] = c
22
+ return [relaxation]
16
23
 
17
24
  if noise_type == "dephasing":
18
25
  if noise_model.hyperfine_dephasing_rate != 0.0:
19
26
  raise NotImplementedError("hyperfine_dephasing_rate is unsupported")
20
27
 
21
28
  c = math.sqrt(noise_model.dephasing_rate / 2)
22
- return [
23
- torch.tensor([[-c, 0], [0, c]], dtype=torch.complex128),
24
- ]
29
+ dephasing = torch.zeros(dim, dim, dtype=dtype)
30
+
31
+ dephasing[0, 0] = c
32
+ dephasing[1, 1] = -c
33
+
34
+ return [dephasing]
25
35
 
26
36
  if noise_type == "depolarizing":
27
37
  c = math.sqrt(noise_model.depolarizing_rate / 4)
28
- return [
29
- torch.tensor([[0, c], [c, 0]], dtype=torch.complex128),
30
- torch.tensor([[0, 1j * c], [-1j * c, 0]], dtype=torch.complex128),
31
- torch.tensor([[-c, 0], [0, c]], dtype=torch.complex128),
32
- ]
38
+ depolarizing_x = torch.zeros(dim, dim, dtype=dtype)
39
+ depolarizing_x[0, 1] = c
40
+ depolarizing_x[1, 0] = c
41
+
42
+ depolarizing_y = torch.zeros(dim, dim, dtype=dtype)
43
+ depolarizing_y[0, 1] = torch.tensor(-c * 1.0j, dtype=dtype)
44
+ depolarizing_y[1, 0] = torch.tensor(c * 1.0j, dtype=dtype)
45
+
46
+ depolarizing_z = torch.zeros(dim, dim, dtype=dtype)
47
+ depolarizing_z[0, 0] = c
48
+ depolarizing_z[1, 1] = -c
49
+
50
+ return [depolarizing_x, depolarizing_y, depolarizing_z]
33
51
 
34
52
  if noise_type == "eff_noise":
35
53
  if not all(
36
- isinstance(op, torch.Tensor) and op.shape == (2, 2)
54
+ isinstance(op, torch.Tensor) and op.shape == (dim, dim)
37
55
  for op in noise_model.eff_noise_opers
38
56
  ):
39
- raise ValueError("Only 2 * 2 effective noise operator matrices are supported")
40
-
41
- return [
42
- math.sqrt(rate)
43
- * torch.flip(op if isinstance(op, torch.Tensor) else torch.tensor(op), (0, 1))
44
- for rate, op in zip(noise_model.eff_noise_rates, noise_model.eff_noise_opers)
45
- ]
57
+ raise ValueError(
58
+ "Only 2 by 2 or 3 by 3 effective noise operator matrices are "
59
+ "supported and it should be given as torch tensors "
60
+ )
61
+ if interact_type == "ising":
62
+ return [ # lindblad operators in pulser ising basis
63
+ math.sqrt(rate) * torch.flip(torch.as_tensor(op), (0, 1))
64
+ for rate, op in zip(
65
+ noise_model.eff_noise_rates, noise_model.eff_noise_opers
66
+ )
67
+ ]
68
+ elif interact_type == "XY":
69
+ return [ # lindblad operators in pulser XY basis
70
+ math.sqrt(rate) * torch.as_tensor(op)
71
+ for rate, op in zip(
72
+ noise_model.eff_noise_rates, noise_model.eff_noise_opers
73
+ )
74
+ ]
46
75
 
47
76
  raise ValueError(f"Unknown noise type: {noise_type}")
48
77
 
49
78
 
50
- def compute_noise_from_lindbladians(lindbladians: list[torch.Tensor]) -> torch.Tensor:
79
+ def compute_noise_from_lindbladians(
80
+ lindbladians: list[torch.Tensor], dim: int = 2
81
+ ) -> torch.Tensor:
51
82
  """
52
- Compute the single-qubit Hamiltonian noise term -0.5i∑L†L from all the given lindbladians.
83
+ Compute the single-qubit Hamiltonian noise term -0.5i∑L†L from all the
84
+ given lindbladians.
53
85
  """
54
86
  assert all(
55
- lindbladian.shape == (2, 2) for lindbladian in lindbladians
87
+ lindbladian.shape == (dim, dim) for lindbladian in lindbladians
56
88
  ), "Only single-qubit lindblad operators are supported"
57
89
 
58
- zero = torch.zeros(2, 2, dtype=torch.complex128)
90
+ zero = torch.zeros(dim, dim, dtype=dtype)
59
91
 
60
92
  return -0.5j * sum((L.mH @ L for L in lindbladians), start=zero)
@@ -20,7 +20,7 @@ _NON_LINDBLADIAN_NOISE = {"SPAM", "doppler", "amplitude", "detuning", "register"
20
20
 
21
21
 
22
22
  def _get_all_lindblad_noise_operators(
23
- noise_model: NoiseModel | None,
23
+ noise_model: NoiseModel | None, dim: int = 2, interact_type: str = "ising"
24
24
  ) -> list[torch.Tensor]:
25
25
  if noise_model is None:
26
26
  return []
@@ -29,7 +29,12 @@ def _get_all_lindblad_noise_operators(
29
29
  op
30
30
  for noise_type in noise_model.noise_types
31
31
  if noise_type not in _NON_LINDBLADIAN_NOISE
32
- for op in get_lindblad_operators(noise_type=noise_type, noise_model=noise_model)
32
+ for op in get_lindblad_operators(
33
+ noise_type=noise_type,
34
+ noise_model=noise_model,
35
+ dim=dim,
36
+ interact_type=interact_type,
37
+ )
33
38
  ]
34
39
 
35
40
 
@@ -150,6 +155,7 @@ class PulserData:
150
155
  )
151
156
 
152
157
  int_type = self.hamiltonian.interaction_type
158
+ self.dim = self.hamiltonian.dim
153
159
  if int_type == "ising": # for local and global
154
160
  self.hamiltonian_type = HamiltonianType.Rydberg
155
161
  elif int_type == "XY":
@@ -157,7 +163,9 @@ class PulserData:
157
163
  else:
158
164
  raise ValueError(f"Unsupported basis: {int_type}")
159
165
 
160
- self.lindblad_ops = _get_all_lindblad_noise_operators(config.noise_model)
166
+ self.lindblad_ops = _get_all_lindblad_noise_operators(
167
+ config.noise_model, dim=self.dim, interact_type=int_type
168
+ )
161
169
  self.has_lindblad_noise: bool = self.lindblad_ops != []
162
170
 
163
171
  if config.interaction_matrix is not None:
emu_base/utils.py CHANGED
@@ -2,12 +2,33 @@ from collections import Counter
2
2
  import random
3
3
  import torch
4
4
  import os
5
+ import logging
6
+ import sys
7
+ from pathlib import Path
5
8
 
6
9
  unix_like = os.name != "nt"
7
10
  if unix_like:
8
11
  from resource import RUSAGE_SELF, getrusage
9
12
 
10
13
 
14
+ def init_logging(log_level: int, log_file: Path | None) -> logging.Logger:
15
+ logger = logging.getLogger("emulators")
16
+ logger.propagate = False
17
+
18
+ handler: logging.Handler
19
+ if log_file is None:
20
+ handler = logging.StreamHandler(sys.stdout)
21
+ else:
22
+ handler = logging.FileHandler(log_file, mode="w")
23
+
24
+ handler.setLevel(log_level)
25
+ handler.setFormatter(logging.Formatter("%(message)s"))
26
+ for h in logger.handlers:
27
+ logger.removeHandler(h)
28
+ logger.addHandler(handler)
29
+ return logger
30
+
31
+
11
32
  def deallocate_tensor(t: torch.Tensor) -> None:
12
33
  """
13
34
  Free the memory used by a tensor. This is done regardless of the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: emu-base
3
- Version: 2.4.2
3
+ Version: 2.4.4
4
4
  Summary: Pasqal base classes for emulators
5
5
  Project-URL: Documentation, https://pasqal-io.github.io/emulators/
6
6
  Project-URL: Repository, https://github.com/pasqal-io/emulators
@@ -1,14 +1,14 @@
1
- emu_base/__init__.py,sha256=xntCCkVdr3et_zsVcIsr2uEBnvt-gNMNFwstt4p5CM8,725
1
+ emu_base/__init__.py,sha256=D7NkoAkHyN0qILkIdfrzfs5-C2yl381TySMHwEWj14c,759
2
2
  emu_base/constants.py,sha256=41LYkKLUCz-oxPbd-j7nUDZuhIbUrnez6prT0uR0jcE,56
3
- emu_base/jump_lindblad_operators.py,sha256=Y30f8emVFS4Dazljc_Rh4lX9qU4QQY_AxPNahnzcsfY,2101
4
- emu_base/pulser_adapter.py,sha256=bb529P2tspLgX_EcJxCT4bJjFM8SOIttgsFIznTeN58,6979
5
- emu_base/utils.py,sha256=OoJ0GjL1K8m9Jq-BeBfmbWuFp9bvwXp8UcI3BMW94Js,2974
3
+ emu_base/jump_lindblad_operators.py,sha256=Wioao_EohYXBrIRZ1yd_qD9K4rPx9_B0NBKKKwiYr18,3033
4
+ emu_base/pulser_adapter.py,sha256=W5e1NLqqrXwCbGAkUdww7DneDaYX981II5chifB89ek,7219
5
+ emu_base/utils.py,sha256=kXfRFq31r_dfLbBC0SHiPpvf7Wll4behd2vqQJsTrVo,3553
6
6
  emu_base/math/__init__.py,sha256=6BbIytYV5uC-e5jLMtIErkcUl_PvfSNnhmVFY9Il8uQ,97
7
7
  emu_base/math/brents_root_finding.py,sha256=AVx6L1Il6rpPJWrLJ7cn6oNmJyZOPRgEaaZaubC9lsU,3711
8
8
  emu_base/math/double_krylov.py,sha256=X16dyCbyzdP7fFK-hmKS03Q-DJtC6TZ8sJrGTJ6akIc,3708
9
9
  emu_base/math/krylov_energy_min.py,sha256=iR4hmE0eXptbAg3opikd5d4Zv7dhnDrawH-n_4KG-cc,4009
10
10
  emu_base/math/krylov_exp.py,sha256=mGFddVQ8mEbwypbZtnlRPFpi4Nf8JZT6OKLHloIwCDQ,3934
11
11
  emu_base/math/matmul.py,sha256=lEAnV0b5z_f1xEA-9p-WXxA8bM3QbShiHdXQ3ZkZFcQ,877
12
- emu_base-2.4.2.dist-info/METADATA,sha256=Th95_Wj1Za2kd-t_Dh9O2aBZDeWRysncK0jF_AVTKkc,3604
13
- emu_base-2.4.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
- emu_base-2.4.2.dist-info/RECORD,,
12
+ emu_base-2.4.4.dist-info/METADATA,sha256=e_i4b_tVdN2PTfEs12pUYGZgICeNUbAIzKpNAFBlsfU,3604
13
+ emu_base-2.4.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
+ emu_base-2.4.4.dist-info/RECORD,,