emu-base 1.2.6__py3-none-any.whl → 1.2.7__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
@@ -46,4 +46,4 @@ __all__ = [
46
46
  "DEVICE_COUNT",
47
47
  ]
48
48
 
49
- __version__ = "1.2.6"
49
+ __version__ = "1.2.7"
@@ -9,9 +9,14 @@ _NUMERIC_TYPES = {int, float, complex}
9
9
 
10
10
  def mean_aggregator(
11
11
  values: list[Any],
12
- ) -> complex | float | list[complex] | list[float] | list[list[complex]] | list[
13
- list[float]
14
- ]: # FIXME: support tuples?
12
+ ) -> (
13
+ complex
14
+ | float
15
+ | list[complex]
16
+ | list[float]
17
+ | list[list[complex]]
18
+ | list[list[float]]
19
+ ): # FIXME: support tuples?
15
20
  if values == []:
16
21
  raise ValueError("Cannot average 0 samples")
17
22
 
@@ -37,7 +37,7 @@ class BackendConfig:
37
37
  *,
38
38
  observables: list[Callback] | None = None,
39
39
  with_modulation: bool = False,
40
- noise_model: NoiseModel = None,
40
+ noise_model: NoiseModel | None = None,
41
41
  interaction_matrix: list[list[float]] | None = None,
42
42
  interaction_cutoff: float = 0.0,
43
43
  log_level: int = logging.INFO,
@@ -3,11 +3,19 @@ from typing import Any, Callable, Optional
3
3
  from pathlib import Path
4
4
  import json
5
5
  import logging
6
+ import torch
6
7
 
7
8
  from emu_base.base_classes.callback import Callback, AggregationType
8
9
  from emu_base.base_classes.aggregators import aggregation_types_definitions
9
10
 
10
11
 
12
+ class ResultsEncoder(json.JSONEncoder):
13
+ def default(self, obj: Any) -> Any:
14
+ if isinstance(obj, torch.Tensor):
15
+ return obj.tolist()
16
+ return super().default(obj)
17
+
18
+
11
19
  @dataclass
12
20
  class Results:
13
21
  """
@@ -171,4 +179,5 @@ class Results:
171
179
  "statistics": self.statistics,
172
180
  },
173
181
  file_handle,
182
+ cls=ResultsEncoder,
174
183
  )
@@ -32,7 +32,10 @@ def get_lindblad_operators(
32
32
  ]
33
33
 
34
34
  if noise_type == "eff_noise":
35
- if not all(op.shape == (2, 2) for op in noise_model.eff_noise_opers):
35
+ if not all(
36
+ isinstance(op, torch.Tensor) and op.shape == (2, 2)
37
+ for op in noise_model.eff_noise_opers
38
+ ):
36
39
  raise ValueError("Only 2 * 2 effective noise operator matrices are supported")
37
40
 
38
41
  return [
@@ -5,6 +5,8 @@ import math
5
5
  from pulser.noise_model import NoiseModel
6
6
  from enum import Enum
7
7
 
8
+ from pulser.register.base_register import BaseRegister
9
+
8
10
  from emu_base.base_classes.config import BackendConfig
9
11
  from emu_base.lindblad_operators import get_lindblad_operators
10
12
  from emu_base.utils import dist2, dist3
@@ -16,7 +18,7 @@ class HamiltonianType(Enum):
16
18
 
17
19
 
18
20
  def _get_qubit_positions(
19
- register: pulser.Register,
21
+ register: BaseRegister,
20
22
  ) -> list[torch.Tensor]:
21
23
  """Conversion from pulser Register to emu-mps register (torch type).
22
24
  Each element will be given as [Rx,Ry,Rz]"""
@@ -31,7 +33,7 @@ def _get_qubit_positions(
31
33
  def _rydberg_interaction(sequence: pulser.Sequence) -> torch.Tensor:
32
34
  """
33
35
  Computes the Ising interaction matrix from the qubit positions.
34
- Hᵢⱼ=C₆/Rᵢⱼ⁶ (nᵢ⊗ nⱼ)
36
+ Hᵢⱼ=C₆/R⁶ᵢⱼ (nᵢ⊗ nⱼ)
35
37
  """
36
38
 
37
39
  num_qubits = len(sequence.register.qubit_ids)
@@ -88,7 +90,7 @@ def _xy_interaction(sequence: pulser.Sequence) -> torch.Tensor:
88
90
  def _extract_omega_delta_phi(
89
91
  *,
90
92
  sequence: pulser.Sequence,
91
- dt: int,
93
+ target_times: list[int],
92
94
  with_modulation: bool,
93
95
  laser_waist: float | None,
94
96
  ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
@@ -125,7 +127,7 @@ def _extract_omega_delta_phi(
125
127
 
126
128
  max_duration = sequence.get_duration(include_fall_time=with_modulation)
127
129
 
128
- nsamples = math.ceil(max_duration / dt - 1 / 2)
130
+ nsamples = len(target_times) - 1
129
131
  omega = torch.zeros(
130
132
  nsamples,
131
133
  len(sequence.register.qubit_ids),
@@ -157,12 +159,11 @@ def _extract_omega_delta_phi(
157
159
  for slot in ch_samples.slots:
158
160
  global_times |= set(i for i in range(slot.ti, slot.tf))
159
161
 
160
- step = 0
161
- t = (step + 1 / 2) * dt
162
162
  omega_1 = torch.zeros_like(omega[0])
163
163
  omega_2 = torch.zeros_like(omega[0])
164
164
 
165
- while t < max_duration:
165
+ for i in range(nsamples):
166
+ t = (target_times[i] + target_times[i + 1]) / 2
166
167
  # The sampled values correspond to the start of each interval
167
168
  # To maximize the order of the solver, we need the values in the middle
168
169
  if math.ceil(t) < max_duration:
@@ -173,10 +174,10 @@ def _extract_omega_delta_phi(
173
174
  t2 = math.ceil(t)
174
175
  omega_1[q_pos] = locals_a_d_p[q_id]["amp"][t1]
175
176
  omega_2[q_pos] = locals_a_d_p[q_id]["amp"][t2]
176
- delta[step, q_pos] = (
177
+ delta[i, q_pos] = (
177
178
  locals_a_d_p[q_id]["det"][t1] + locals_a_d_p[q_id]["det"][t2]
178
179
  ) / 2.0
179
- phi[step, q_pos] = (
180
+ phi[i, q_pos] = (
180
181
  locals_a_d_p[q_id]["phase"][t1] + locals_a_d_p[q_id]["phase"][t2]
181
182
  ) / 2.0
182
183
  # omegas at different times need to have the laser waist applied independently
@@ -184,21 +185,19 @@ def _extract_omega_delta_phi(
184
185
  omega_1 *= waist_factors
185
186
  if t2 in global_times:
186
187
  omega_2 *= waist_factors
187
- omega[step] = 0.5 * (omega_1 + omega_2)
188
+ omega[i] = 0.5 * (omega_1 + omega_2)
188
189
  else:
189
190
  # We're in the final step and dt=1, approximate this using linear extrapolation
190
191
  # we can reuse omega_1 and omega_2 from before
191
192
  for q_pos, q_id in enumerate(sequence.register.qubit_ids):
192
- delta[step, q_pos] = (
193
+ delta[i, q_pos] = (
193
194
  3.0 * locals_a_d_p[q_id]["det"][t2] - locals_a_d_p[q_id]["det"][t1]
194
195
  ) / 2.0
195
- phi[step, q_pos] = (
196
+ phi[i, q_pos] = (
196
197
  3.0 * locals_a_d_p[q_id]["phase"][t2]
197
198
  - locals_a_d_p[q_id]["phase"][t1]
198
199
  ) / 2.0
199
- omega[step] = torch.clamp(0.5 * (3 * omega_2 - omega_1).real, min=0.0)
200
- step += 1
201
- t = (step + 1 / 2) * dt
200
+ omega[i] = torch.clamp(0.5 * (3 * omega_2 - omega_1).real, min=0.0)
202
201
 
203
202
  return omega, delta, phi
204
203
 
@@ -221,7 +220,7 @@ def _get_all_lindblad_noise_operators(
221
220
 
222
221
 
223
222
  class PulserData:
224
- slm_end_time: int
223
+ slm_end_time: float
225
224
  full_interaction_matrix: torch.Tensor
226
225
  masked_interaction_matrix: torch.Tensor
227
226
  omega: torch.Tensor
@@ -233,12 +232,20 @@ class PulserData:
233
232
  def __init__(self, *, sequence: pulser.Sequence, config: BackendConfig, dt: int):
234
233
  self.qubit_count = len(sequence.register.qubit_ids)
235
234
 
235
+ # the end value is exclusive, so add +1
236
+ observable_times = set(torch.arange(0, sequence.get_duration() + 1, dt).tolist())
237
+ observable_times.add(sequence.get_duration())
238
+ for obs in config.callbacks:
239
+ observable_times |= set(obs.evaluation_times)
240
+ self.target_times = list(observable_times)
241
+ self.target_times.sort()
242
+
236
243
  laser_waist = (
237
244
  config.noise_model.laser_waist if config.noise_model is not None else None
238
245
  )
239
246
  self.omega, self.delta, self.phi = _extract_omega_delta_phi(
240
247
  sequence=sequence,
241
- dt=dt,
248
+ target_times=self.target_times,
242
249
  with_modulation=config.with_modulation,
243
250
  laser_waist=laser_waist,
244
251
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: emu-base
3
- Version: 1.2.6
3
+ Version: 1.2.7
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,20 +1,20 @@
1
- emu_base/__init__.py,sha256=YDB_UjuJJoFfzL3gG_z09ieMTU7RvE5UAGn7POqiYbE,1186
1
+ emu_base/__init__.py,sha256=i2Gv8rIusAD2hXepDFdFTfC5FQOOpNXtB0F1xoSd6QQ,1186
2
2
  emu_base/constants.py,sha256=41LYkKLUCz-oxPbd-j7nUDZuhIbUrnez6prT0uR0jcE,56
3
- emu_base/lindblad_operators.py,sha256=eXkXsLt_fV7jhF31EkxzYFU04rOJV3uWXsl6t1aTAqs,1562
4
- emu_base/pulser_adapter.py,sha256=Doi24xNQp09UhyrvNkS_ydXiRV4XNinoziALo6Gil2U,10456
3
+ emu_base/lindblad_operators.py,sha256=Nsl1YrWb8IDM9Z50ucy2Ed44p_IRETnlbr6qaqAgV50,1629
4
+ emu_base/pulser_adapter.py,sha256=SIkw3Mrob4RPTt4QNYzC8CUJ0tj-sTj-t-fEKEyRTtU,10858
5
5
  emu_base/utils.py,sha256=RM8O0qfPAJfcdqqAojwEEKV7I3ZfVDklnTisTGhUg5k,233
6
6
  emu_base/base_classes/__init__.py,sha256=Su6fHtjCyg0fw-7y7e7nbMfDASppNRQs8iGaAOkO3c4,570
7
- emu_base/base_classes/aggregators.py,sha256=bcvoGfZCkPKv-CI29gTma6HBphGh7bjBq2Ome77eRJM,1840
7
+ emu_base/base_classes/aggregators.py,sha256=BDzFq12q36p12TXp2qv3g7a9cHnXbT1hhMZJLVojkDU,1862
8
8
  emu_base/base_classes/backend.py,sha256=7tnwb9MnRbwRN1_JTqliYftjqExuOE-Rrwz9AU2Pc4c,1645
9
9
  emu_base/base_classes/callback.py,sha256=JXah_ZDNM8iyPWy7IOwW481qRFyqVvlSM-0OkjBzV0A,3055
10
- emu_base/base_classes/config.py,sha256=Dg2CwC9sc5HYwszQAJSVjkSd3wuQrv6aEZGYBRnFl48,4098
10
+ emu_base/base_classes/config.py,sha256=oLS2jwmxqwMbLKIPdqohK-KPIcXdtpG3sRr_Y12poNQ,4105
11
11
  emu_base/base_classes/default_callbacks.py,sha256=F44kkuwWdVcvMGZ9vJ2q7ug-_P8IQyJv-SVxSVWHW_w,9940
12
12
  emu_base/base_classes/operator.py,sha256=MJjuDUTwJLbaSJzSNCKDWGvmGCGAEIEWISLoPSSzNsU,3501
13
- emu_base/base_classes/results.py,sha256=7-Mz3jmFy19hd3PIA5idK610mC3b5jOf3EKBmV14Jv4,5569
13
+ emu_base/base_classes/results.py,sha256=w4js7gThb49sNjEEDfEf0tYRwK004GrafWPeEOvyeCg,5810
14
14
  emu_base/base_classes/state.py,sha256=7iIyZmBqqJ6G4SyYZ3kyylWjAqiYIx0aW5B0T74EPZI,2707
15
15
  emu_base/math/__init__.py,sha256=6BbIytYV5uC-e5jLMtIErkcUl_PvfSNnhmVFY9Il8uQ,97
16
16
  emu_base/math/brents_root_finding.py,sha256=AVx6L1Il6rpPJWrLJ7cn6oNmJyZOPRgEaaZaubC9lsU,3711
17
17
  emu_base/math/krylov_exp.py,sha256=UCFNeq-j2ukgBsOPC9_Jiv1aqpy88SrslDLiCxIGBwk,3840
18
- emu_base-1.2.6.dist-info/METADATA,sha256=AKKbxP9g8y0vjIYHix98y-DxKOlAufhKRW8YQy74h_Q,3522
19
- emu_base-1.2.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
- emu_base-1.2.6.dist-info/RECORD,,
18
+ emu_base-1.2.7.dist-info/METADATA,sha256=JpfSGDOQtIu2hwwoHXgBNgf8ZmIkUh0MUDiwJYPZL_Q,3522
19
+ emu_base-1.2.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
+ emu_base-1.2.7.dist-info/RECORD,,