emu-base 1.2.4__py3-none-any.whl → 1.2.6__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
@@ -15,6 +15,7 @@ from .base_classes.default_callbacks import (
15
15
  StateResult,
16
16
  SecondMomentOfEnergy,
17
17
  )
18
+ from .constants import DEVICE_COUNT
18
19
  from .pulser_adapter import PulserData, HamiltonianType
19
20
  from .math.brents_root_finding import find_root_brents
20
21
  from .math.krylov_exp import krylov_exp, DEFAULT_MAX_KRYLOV_DIM
@@ -42,6 +43,7 @@ __all__ = [
42
43
  "krylov_exp",
43
44
  "HamiltonianType",
44
45
  "DEFAULT_MAX_KRYLOV_DIM",
46
+ "DEVICE_COUNT",
45
47
  ]
46
48
 
47
- __version__ = "1.2.4"
49
+ __version__ = "1.2.6"
@@ -4,6 +4,7 @@ import logging
4
4
  import sys
5
5
  import pathlib
6
6
  from typing import TYPE_CHECKING
7
+ import torch
7
8
 
8
9
  if TYPE_CHECKING:
9
10
  from emu_base.base_classes.callback import Callback
@@ -50,14 +51,28 @@ class BackendConfig:
50
51
  self.with_modulation = with_modulation
51
52
  self.noise_model = noise_model
52
53
 
53
- if interaction_matrix is not None and (
54
- not isinstance(interaction_matrix, list)
55
- or not isinstance(interaction_matrix[0], list)
54
+ if interaction_matrix is not None and not (
55
+ isinstance(interaction_matrix, list)
56
+ and isinstance(interaction_matrix[0], list)
57
+ and isinstance(interaction_matrix[0][0], float)
56
58
  ):
57
59
  raise ValueError(
58
60
  "Interaction matrix must be provided as a Python list of lists of floats"
59
61
  )
60
62
 
63
+ if interaction_matrix is not None:
64
+ int_mat = torch.tensor(interaction_matrix)
65
+ tol = 1e-10
66
+ if not (
67
+ int_mat.numel() != 0
68
+ and torch.all(torch.isreal(int_mat))
69
+ and int_mat.dim() == 2
70
+ and int_mat.shape[0] == int_mat.shape[1]
71
+ and torch.allclose(int_mat, int_mat.T, atol=tol)
72
+ and torch.norm(torch.diag(int_mat)) < tol
73
+ ):
74
+ raise ValueError("Interaction matrix is not symmetric and zero diag")
75
+
61
76
  self.interaction_matrix = interaction_matrix
62
77
  self.interaction_cutoff = interaction_cutoff
63
78
  self.logger = logging.getLogger("global_logger")
emu_base/constants.py ADDED
@@ -0,0 +1,4 @@
1
+ import torch
2
+
3
+
4
+ DEVICE_COUNT = torch.cuda.device_count()
@@ -158,17 +158,47 @@ def _extract_omega_delta_phi(
158
158
  global_times |= set(i for i in range(slot.ti, slot.tf))
159
159
 
160
160
  step = 0
161
- t = int((step + 1 / 2) * dt)
161
+ t = (step + 1 / 2) * dt
162
+ omega_1 = torch.zeros_like(omega[0])
163
+ omega_2 = torch.zeros_like(omega[0])
162
164
 
163
165
  while t < max_duration:
164
- for q_pos, q_id in enumerate(sequence.register.qubit_ids):
165
- omega[step, q_pos] = locals_a_d_p[q_id]["amp"][t]
166
- delta[step, q_pos] = locals_a_d_p[q_id]["det"][t]
167
- phi[step, q_pos] = locals_a_d_p[q_id]["phase"][t]
168
- if t in global_times:
169
- omega[step] *= waist_factors
166
+ # The sampled values correspond to the start of each interval
167
+ # To maximize the order of the solver, we need the values in the middle
168
+ if math.ceil(t) < max_duration:
169
+ # If we're not the final step, approximate this using linear interpolation
170
+ # Note that for dt even, t1=t2
171
+ for q_pos, q_id in enumerate(sequence.register.qubit_ids):
172
+ t1 = math.floor(t)
173
+ t2 = math.ceil(t)
174
+ omega_1[q_pos] = locals_a_d_p[q_id]["amp"][t1]
175
+ omega_2[q_pos] = locals_a_d_p[q_id]["amp"][t2]
176
+ delta[step, q_pos] = (
177
+ locals_a_d_p[q_id]["det"][t1] + locals_a_d_p[q_id]["det"][t2]
178
+ ) / 2.0
179
+ phi[step, q_pos] = (
180
+ locals_a_d_p[q_id]["phase"][t1] + locals_a_d_p[q_id]["phase"][t2]
181
+ ) / 2.0
182
+ # omegas at different times need to have the laser waist applied independently
183
+ if t1 in global_times:
184
+ omega_1 *= waist_factors
185
+ if t2 in global_times:
186
+ omega_2 *= waist_factors
187
+ omega[step] = 0.5 * (omega_1 + omega_2)
188
+ else:
189
+ # We're in the final step and dt=1, approximate this using linear extrapolation
190
+ # we can reuse omega_1 and omega_2 from before
191
+ for q_pos, q_id in enumerate(sequence.register.qubit_ids):
192
+ delta[step, q_pos] = (
193
+ 3.0 * locals_a_d_p[q_id]["det"][t2] - locals_a_d_p[q_id]["det"][t1]
194
+ ) / 2.0
195
+ phi[step, q_pos] = (
196
+ 3.0 * locals_a_d_p[q_id]["phase"][t2]
197
+ - locals_a_d_p[q_id]["phase"][t1]
198
+ ) / 2.0
199
+ omega[step] = torch.clamp(0.5 * (3 * omega_2 - omega_1).real, min=0.0)
170
200
  step += 1
171
- t = int((step + 1 / 2) * dt)
201
+ t = (step + 1 / 2) * dt
172
202
 
173
203
  return omega, delta, phi
174
204
 
@@ -241,11 +271,12 @@ class PulserData:
241
271
  ] = 0.0
242
272
  self.masked_interaction_matrix = self.full_interaction_matrix.clone()
243
273
 
244
- slm_targets = sequence._slm_mask_targets
245
274
  self.slm_end_time = (
246
275
  sequence._slm_mask_time[1] if len(sequence._slm_mask_time) > 1 else 0.0
247
276
  )
248
277
 
249
- for target in slm_targets:
278
+ # disable interaction for SLM masked qubits
279
+ slm_targets = list(sequence._slm_mask_targets)
280
+ for target in sequence.register.find_indices(slm_targets):
250
281
  self.masked_interaction_matrix[target] = 0.0
251
282
  self.masked_interaction_matrix[:, target] = 0.0
@@ -1,7 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: emu-base
3
- Version: 1.2.4
3
+ Version: 1.2.6
4
4
  Summary: Pasqal base classes for emulators
5
+ Project-URL: Documentation, https://pasqal-io.github.io/emulators/
6
+ Project-URL: Repository, https://github.com/pasqal-io/emulators
7
+ Project-URL: Issues, https://github.com/pasqal-io/emulators/issues
5
8
  Author-email: Anton Quelle <anton.quelle@pasqal.com>, Mauro Mendizabal <mauro.mendizabal-pico@pasqal.com>, Stefano Grava <stefano.grava@pasqal.com>, Pablo Le Henaff <pablo.le-henaff@pasqal.com>
6
9
  License: PASQAL OPEN-SOURCE SOFTWARE LICENSE AGREEMENT (MIT-derived)
7
10
 
@@ -22,79 +25,14 @@ Classifier: Programming Language :: Python :: 3.10
22
25
  Classifier: Programming Language :: Python :: Implementation :: CPython
23
26
  Classifier: Programming Language :: Python :: Implementation :: PyPy
24
27
  Requires-Python: >=3.10
25
- Requires-Dist: pulser-core==1.1.*
28
+ Requires-Dist: pulser-core==1.3.*
26
29
  Requires-Dist: torch==2.5.0
27
30
  Description-Content-Type: text/markdown
28
31
 
29
32
  <div align="center">
30
33
  <img src="docs/logos/LogoTaglineSoftGreen.svg">
31
-
32
- # Emu-MPS
33
34
  </div>
34
35
 
35
- **Emu-mps** is a backend for the [Pulser low-level Quantum Programming toolkit](https://pulser.readthedocs.io) that lets you run Quantum Algorithms on a simulated device, using GPU acceleration if available. More in depth, emu-mps is designed to **emu**late the dynamics of programmable arrays of neutral atoms, with matrix product states (**mps**). While benchmarking is incomplete as of this writing, early results suggest that this design makes emu-mps faster and more memory-efficient than previous generations of quantum emulators at running simulations with large numbers of qubits.
36
-
37
- ## Installation
38
-
39
- **Warning:** installing emu-mps will update pulser-core
40
-
41
- ### Using `hatch`, `uv` or any pyproject-compatible Python manager
42
-
43
- To add `emu-mps` to your project, edit your `pyproject.toml` to add the line
44
-
45
- ```toml
46
- "emu-mps"
47
- ```
48
-
49
- to the list of `dependencies`.
50
-
51
-
52
- ### Using `pip` or `pipx`
53
- To install the `pipy` package using `pip` or `pipx`
54
-
55
- 1. Create a `venv` if that's not done yet
56
-
57
- ```sh
58
- $ python -m venv venv
59
-
60
- ```
61
-
62
- 2. Enter the venv
63
-
64
- If you're running Unix:
65
-
66
- ```sh
67
- $ . venv/bin/activate
68
- ```
69
-
70
- If you're running Windows:
71
-
72
- ```sh
73
- C:\> /path/to/new/virtual/environment/Scripts/activate
74
- ```
75
-
76
- 3. Install the package
77
-
78
- ```sh
79
- $ pip install emu-mps
80
- # or
81
- $ pipx install emu-mps
82
- ```
83
-
84
-
85
- Join us on [Slack](https://pasqalworkspace.slack.com/archives/C07MUV5K7EU) or by [e-mail](mailto:emulation@pasqal.com) to give us feedback about how you plan to use Emu-MPS or if you require specific feature-upgrades.
86
-
87
- ## Usage
88
-
89
- For the time being, the easiest way to learn how to use this package is to look
90
- at the [examples](examples/emu_mps_examples) and [notebooks](https://pasqal-io.github.io/emulators/latest/).
91
-
92
- See also the [full documentation](https://github.com/pasqal-io/emulators/blob/main/docs/index.md) for
93
- the API, information about contributing, benchmarks, etc.
94
-
95
-
96
- ## Getting in touch
36
+ # Welcome to the Pasqal analog emulators
97
37
 
98
- - [Pasqal Community Portal](https://community.pasqal.com/) (forums, chat, tutorials, examples, code library).
99
- - [GitHub Repository](https://github.com/pasqal-io/quantum-evolution-kernel) (source code, issue tracker).
100
- - [Professional Support](https://www.pasqal.com/contact-us/) (if you need tech support, custom licenses, a variant of this library optimized for your workload, your own QPU, remote access to a QPU, ...)
38
+ Welcome, and please see the [GitHub pages](https://pasqal-io.github.io/emulators/) for a landing page to this repo.
@@ -1,12 +1,13 @@
1
- emu_base/__init__.py,sha256=7xlIJ_5eU7fEVG-RQnIdSnCrRk2fw5NwqjYmwmUwKC8,1130
1
+ emu_base/__init__.py,sha256=YDB_UjuJJoFfzL3gG_z09ieMTU7RvE5UAGn7POqiYbE,1186
2
+ emu_base/constants.py,sha256=41LYkKLUCz-oxPbd-j7nUDZuhIbUrnez6prT0uR0jcE,56
2
3
  emu_base/lindblad_operators.py,sha256=eXkXsLt_fV7jhF31EkxzYFU04rOJV3uWXsl6t1aTAqs,1562
3
- emu_base/pulser_adapter.py,sha256=aFq4Q7INUTyhfqALSrLpZZRnKf1QZ0SyUyt1Cdiolz0,8802
4
+ emu_base/pulser_adapter.py,sha256=Doi24xNQp09UhyrvNkS_ydXiRV4XNinoziALo6Gil2U,10456
4
5
  emu_base/utils.py,sha256=RM8O0qfPAJfcdqqAojwEEKV7I3ZfVDklnTisTGhUg5k,233
5
6
  emu_base/base_classes/__init__.py,sha256=Su6fHtjCyg0fw-7y7e7nbMfDASppNRQs8iGaAOkO3c4,570
6
7
  emu_base/base_classes/aggregators.py,sha256=bcvoGfZCkPKv-CI29gTma6HBphGh7bjBq2Ome77eRJM,1840
7
8
  emu_base/base_classes/backend.py,sha256=7tnwb9MnRbwRN1_JTqliYftjqExuOE-Rrwz9AU2Pc4c,1645
8
9
  emu_base/base_classes/callback.py,sha256=JXah_ZDNM8iyPWy7IOwW481qRFyqVvlSM-0OkjBzV0A,3055
9
- emu_base/base_classes/config.py,sha256=Iz5bO6WRcjiz3ORGscyM7ELQZ4IocuJLJjJLyc-Odpg,3474
10
+ emu_base/base_classes/config.py,sha256=Dg2CwC9sc5HYwszQAJSVjkSd3wuQrv6aEZGYBRnFl48,4098
10
11
  emu_base/base_classes/default_callbacks.py,sha256=F44kkuwWdVcvMGZ9vJ2q7ug-_P8IQyJv-SVxSVWHW_w,9940
11
12
  emu_base/base_classes/operator.py,sha256=MJjuDUTwJLbaSJzSNCKDWGvmGCGAEIEWISLoPSSzNsU,3501
12
13
  emu_base/base_classes/results.py,sha256=7-Mz3jmFy19hd3PIA5idK610mC3b5jOf3EKBmV14Jv4,5569
@@ -14,6 +15,6 @@ emu_base/base_classes/state.py,sha256=7iIyZmBqqJ6G4SyYZ3kyylWjAqiYIx0aW5B0T74EPZ
14
15
  emu_base/math/__init__.py,sha256=6BbIytYV5uC-e5jLMtIErkcUl_PvfSNnhmVFY9Il8uQ,97
15
16
  emu_base/math/brents_root_finding.py,sha256=AVx6L1Il6rpPJWrLJ7cn6oNmJyZOPRgEaaZaubC9lsU,3711
16
17
  emu_base/math/krylov_exp.py,sha256=UCFNeq-j2ukgBsOPC9_Jiv1aqpy88SrslDLiCxIGBwk,3840
17
- emu_base-1.2.4.dist-info/METADATA,sha256=uNaPv60Dih8BsidRdd1bEEfBTJGstIC-BuxjkbUWaqQ,5482
18
- emu_base-1.2.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
19
- emu_base-1.2.4.dist-info/RECORD,,
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,,