emu-mps 2.4.3__py3-none-any.whl → 2.5.0__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 +1 -1
- emu_mps/mps.py +4 -2
- emu_mps/mps_backend.py +3 -3
- emu_mps/mps_backend_impl.py +5 -1
- emu_mps/mps_config.py +10 -35
- emu_mps/solver_utils.py +9 -4
- {emu_mps-2.4.3.dist-info → emu_mps-2.5.0.dist-info}/METADATA +2 -2
- {emu_mps-2.4.3.dist-info → emu_mps-2.5.0.dist-info}/RECORD +9 -9
- {emu_mps-2.4.3.dist-info → emu_mps-2.5.0.dist-info}/WHEEL +0 -0
emu_mps/__init__.py
CHANGED
emu_mps/mps.py
CHANGED
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
import math
|
|
3
3
|
from collections import Counter
|
|
4
4
|
from typing import List, Optional, Sequence, TypeVar, Mapping
|
|
5
|
-
|
|
5
|
+
import logging
|
|
6
6
|
import torch
|
|
7
7
|
|
|
8
8
|
from pulser.backend.state import State, Eigenstate
|
|
@@ -481,7 +481,9 @@ class MPS(State[complex, torch.Tensor]):
|
|
|
481
481
|
accum_mps += amplitude * MPS(factors, eigenstates=eigenstates)
|
|
482
482
|
norm = accum_mps.norm()
|
|
483
483
|
if not math.isclose(1.0, norm, rel_tol=1e-5, abs_tol=0.0):
|
|
484
|
-
|
|
484
|
+
logging.getLogger("emulators").warning(
|
|
485
|
+
"\nThe state is not normalized, normalizing it for you."
|
|
486
|
+
)
|
|
485
487
|
accum_mps *= 1 / norm
|
|
486
488
|
|
|
487
489
|
return accum_mps, amplitudes
|
emu_mps/mps_backend.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from pulser.backend import EmulatorBackend, Results
|
|
2
2
|
from emu_mps.mps_config import MPSConfig
|
|
3
|
+
from emu_base import init_logging
|
|
3
4
|
from emu_mps.mps_backend_impl import create_impl, MPSBackendImpl
|
|
4
5
|
import pickle
|
|
5
6
|
import os
|
|
6
7
|
import time
|
|
7
|
-
import logging
|
|
8
8
|
import pathlib
|
|
9
9
|
|
|
10
10
|
|
|
@@ -34,9 +34,9 @@ class MPSBackend(EmulatorBackend):
|
|
|
34
34
|
|
|
35
35
|
impl.autosave_file = autosave_file
|
|
36
36
|
impl.last_save_time = time.time()
|
|
37
|
-
impl.config.
|
|
37
|
+
init_logging(impl.config.log_level, impl.config.log_file)
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
impl.config.logger.warning(
|
|
40
40
|
f"Resuming simulation from file {autosave_file}\n"
|
|
41
41
|
f"Saving simulation state every {impl.config.autosave_dt} seconds"
|
|
42
42
|
)
|
emu_mps/mps_backend_impl.py
CHANGED
|
@@ -119,6 +119,7 @@ class MPSBackendImpl:
|
|
|
119
119
|
self.phi = pulser_data.phi
|
|
120
120
|
self.timestep_count: int = self.omega.shape[0]
|
|
121
121
|
self.has_lindblad_noise = pulser_data.has_lindblad_noise
|
|
122
|
+
self.eigenstates = pulser_data.eigenstates
|
|
122
123
|
self.dim = pulser_data.dim
|
|
123
124
|
self.lindblad_noise = torch.zeros(self.dim, self.dim, dtype=dtype)
|
|
124
125
|
self.qubit_permutation = (
|
|
@@ -220,6 +221,7 @@ class MPSBackendImpl:
|
|
|
220
221
|
precision=self.config.precision,
|
|
221
222
|
max_bond_dim=self.config.max_bond_dim,
|
|
222
223
|
num_gpus_to_use=self.resolved_num_gpus,
|
|
224
|
+
eigenstates=self.eigenstates,
|
|
223
225
|
)
|
|
224
226
|
return
|
|
225
227
|
|
|
@@ -268,6 +270,7 @@ class MPSBackendImpl:
|
|
|
268
270
|
),
|
|
269
271
|
hamiltonian_type=self.hamiltonian_type,
|
|
270
272
|
num_gpus_to_use=self.resolved_num_gpus,
|
|
273
|
+
dim=self.dim,
|
|
271
274
|
)
|
|
272
275
|
|
|
273
276
|
update_H(
|
|
@@ -342,6 +345,7 @@ class MPSBackendImpl:
|
|
|
342
345
|
config=self.config,
|
|
343
346
|
orth_center_right=orth_center_right,
|
|
344
347
|
is_hermitian=not self.has_lindblad_noise,
|
|
348
|
+
dim=self.dim,
|
|
345
349
|
)
|
|
346
350
|
|
|
347
351
|
self.state.orthogonality_center = r if orth_center_right else l
|
|
@@ -616,7 +620,7 @@ class NoisyMPSBackendImpl(MPSBackendImpl):
|
|
|
616
620
|
# The below is used for batch computation of noise collapse weights.
|
|
617
621
|
self.aggregated_lindblad_ops = stacked.conj().transpose(1, 2) @ stacked
|
|
618
622
|
|
|
619
|
-
self.lindblad_noise = compute_noise_from_lindbladians(self.lindblad_ops)
|
|
623
|
+
self.lindblad_noise = compute_noise_from_lindbladians(self.lindblad_ops, self.dim)
|
|
620
624
|
|
|
621
625
|
def set_jump_threshold(self, bound: float) -> None:
|
|
622
626
|
self.jump_threshold = random.uniform(0.0, bound)
|
emu_mps/mps_config.py
CHANGED
|
@@ -3,6 +3,7 @@ from types import MethodType
|
|
|
3
3
|
|
|
4
4
|
import copy
|
|
5
5
|
|
|
6
|
+
from emu_base import init_logging
|
|
6
7
|
from emu_mps.mps import MPS, DEFAULT_MAX_BOND_DIM, DEFAULT_PRECISION
|
|
7
8
|
from emu_mps.mpo import MPO
|
|
8
9
|
from emu_mps.solver import Solver
|
|
@@ -24,7 +25,6 @@ from pulser.backend import (
|
|
|
24
25
|
)
|
|
25
26
|
import logging
|
|
26
27
|
import pathlib
|
|
27
|
-
import sys
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class MPSConfig(EmulationConfig):
|
|
@@ -90,7 +90,7 @@ class MPSConfig(EmulationConfig):
|
|
|
90
90
|
max_krylov_dim: int = 100,
|
|
91
91
|
extra_krylov_tolerance: float = 1e-3,
|
|
92
92
|
num_gpus_to_use: int | None = None,
|
|
93
|
-
optimize_qubit_ordering: bool =
|
|
93
|
+
optimize_qubit_ordering: bool = True,
|
|
94
94
|
interaction_cutoff: float = 0.0,
|
|
95
95
|
log_level: int = logging.INFO,
|
|
96
96
|
log_file: pathlib.Path | None = None,
|
|
@@ -116,8 +116,6 @@ class MPSConfig(EmulationConfig):
|
|
|
116
116
|
solver=solver,
|
|
117
117
|
**kwargs,
|
|
118
118
|
)
|
|
119
|
-
if self.optimize_qubit_ordering:
|
|
120
|
-
self.check_permutable_observables()
|
|
121
119
|
|
|
122
120
|
MIN_AUTOSAVE_DT = 10
|
|
123
121
|
assert (
|
|
@@ -125,20 +123,8 @@ class MPSConfig(EmulationConfig):
|
|
|
125
123
|
), f"autosave_dt must be larger than {MIN_AUTOSAVE_DT} seconds"
|
|
126
124
|
|
|
127
125
|
self.monkeypatch_observables()
|
|
126
|
+
self.logger = init_logging(log_level, log_file)
|
|
128
127
|
|
|
129
|
-
self.logger = logging.getLogger("global_logger")
|
|
130
|
-
if log_file is None:
|
|
131
|
-
logging.basicConfig(
|
|
132
|
-
level=log_level, format="%(message)s", stream=sys.stdout, force=True
|
|
133
|
-
) # default to stream = sys.stderr
|
|
134
|
-
else:
|
|
135
|
-
logging.basicConfig(
|
|
136
|
-
level=log_level,
|
|
137
|
-
format="%(message)s",
|
|
138
|
-
filename=str(log_file),
|
|
139
|
-
filemode="w",
|
|
140
|
-
force=True,
|
|
141
|
-
)
|
|
142
128
|
if (self.noise_model.runs != 1 and self.noise_model.runs is not None) or (
|
|
143
129
|
self.noise_model.samples_per_run != 1
|
|
144
130
|
and self.noise_model.samples_per_run is not None
|
|
@@ -146,6 +132,9 @@ class MPSConfig(EmulationConfig):
|
|
|
146
132
|
self.logger.warning(
|
|
147
133
|
"Warning: The runs and samples_per_run values of the NoiseModel are ignored!"
|
|
148
134
|
)
|
|
135
|
+
self._backend_options[
|
|
136
|
+
"optimize_qubit_ordering"
|
|
137
|
+
] &= self.check_permutable_observables()
|
|
149
138
|
|
|
150
139
|
def _expected_kwargs(self) -> set[str]:
|
|
151
140
|
return super()._expected_kwargs() | {
|
|
@@ -191,21 +180,7 @@ class MPSConfig(EmulationConfig):
|
|
|
191
180
|
obs_list.append(obs_copy)
|
|
192
181
|
self.observables = tuple(obs_list)
|
|
193
182
|
|
|
194
|
-
def
|
|
195
|
-
if self.log_file is None:
|
|
196
|
-
logging.basicConfig(
|
|
197
|
-
level=self.log_level, format="%(message)s", stream=sys.stdout, force=True
|
|
198
|
-
) # default to stream = sys.stderr
|
|
199
|
-
else:
|
|
200
|
-
logging.basicConfig(
|
|
201
|
-
level=self.log_level,
|
|
202
|
-
format="%(message)s",
|
|
203
|
-
filename=str(self.log_file),
|
|
204
|
-
filemode="w",
|
|
205
|
-
force=True,
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
def check_permutable_observables(self) -> None:
|
|
183
|
+
def check_permutable_observables(self) -> bool:
|
|
209
184
|
allowed_permutable_obs = set(
|
|
210
185
|
[
|
|
211
186
|
"bitstrings",
|
|
@@ -221,10 +196,10 @@ class MPSConfig(EmulationConfig):
|
|
|
221
196
|
actual_obs = set([obs._base_tag for obs in self.observables])
|
|
222
197
|
not_allowed = actual_obs.difference(allowed_permutable_obs)
|
|
223
198
|
if not_allowed:
|
|
224
|
-
|
|
199
|
+
self.logger.warning(
|
|
225
200
|
f"emu-mps allows only {allowed_permutable_obs} observables with"
|
|
226
201
|
" `optimize_qubit_ordering = True`."
|
|
227
202
|
f" you provided unsupported {not_allowed}"
|
|
228
|
-
"
|
|
229
|
-
" `optimize_qubit_ordering = False` in `MPSConfig()`."
|
|
203
|
+
" using `optimize_qubit_ordering = False` instead."
|
|
230
204
|
)
|
|
205
|
+
return not_allowed == set()
|
emu_mps/solver_utils.py
CHANGED
|
@@ -14,6 +14,7 @@ def make_op(
|
|
|
14
14
|
state_factors: Sequence[torch.Tensor],
|
|
15
15
|
baths: tuple[torch.Tensor, torch.Tensor],
|
|
16
16
|
ham_factors: Sequence[torch.Tensor],
|
|
17
|
+
dim: int = 2,
|
|
17
18
|
) -> tuple[torch.Tensor, torch.device, Callable[[torch.Tensor], torch.Tensor]]:
|
|
18
19
|
assert len(state_factors) == 2
|
|
19
20
|
assert len(baths) == 2
|
|
@@ -35,7 +36,7 @@ def make_op(
|
|
|
35
36
|
|
|
36
37
|
combined_state_factors = torch.tensordot(
|
|
37
38
|
left_state_factor, right_state_factor, dims=1
|
|
38
|
-
).reshape(left_bond_dim,
|
|
39
|
+
).reshape(left_bond_dim, dim**2, right_bond_dim)
|
|
39
40
|
|
|
40
41
|
deallocate_tensor(left_state_factor)
|
|
41
42
|
deallocate_tensor(right_state_factor)
|
|
@@ -48,7 +49,7 @@ def make_op(
|
|
|
48
49
|
torch.tensordot(left_ham_factor, right_ham_factor, dims=1)
|
|
49
50
|
.transpose(2, 3)
|
|
50
51
|
.contiguous()
|
|
51
|
-
.view(left_ham_factor.shape[0],
|
|
52
|
+
.view(left_ham_factor.shape[0], dim**2, dim**2, -1)
|
|
52
53
|
)
|
|
53
54
|
|
|
54
55
|
def op(x: torch.Tensor) -> torch.Tensor:
|
|
@@ -151,6 +152,7 @@ def evolve_pair(
|
|
|
151
152
|
orth_center_right: bool,
|
|
152
153
|
is_hermitian: bool,
|
|
153
154
|
config: MPSConfig,
|
|
155
|
+
dim: int = 2,
|
|
154
156
|
) -> tuple[torch.Tensor, torch.Tensor]:
|
|
155
157
|
"""
|
|
156
158
|
Time evolution of a pair of tensors of a tensor train using baths and truncated SVD.
|
|
@@ -165,6 +167,7 @@ def evolve_pair(
|
|
|
165
167
|
state_factors=state_factors,
|
|
166
168
|
baths=baths,
|
|
167
169
|
ham_factors=ham_factors,
|
|
170
|
+
dim=dim,
|
|
168
171
|
)
|
|
169
172
|
left_bond_dim = combined_state_factors.shape[0]
|
|
170
173
|
right_bond_dim = combined_state_factors.shape[-1]
|
|
@@ -176,7 +179,7 @@ def evolve_pair(
|
|
|
176
179
|
norm_tolerance=config.precision * config.extra_krylov_tolerance,
|
|
177
180
|
max_krylov_dim=config.max_krylov_dim,
|
|
178
181
|
is_hermitian=is_hermitian,
|
|
179
|
-
).view(left_bond_dim *
|
|
182
|
+
).view(left_bond_dim * dim, dim * right_bond_dim)
|
|
180
183
|
|
|
181
184
|
l, r = split_matrix(
|
|
182
185
|
evol,
|
|
@@ -186,7 +189,9 @@ def evolve_pair(
|
|
|
186
189
|
preserve_norm=not is_hermitian, # only relevant for computing jump times
|
|
187
190
|
)
|
|
188
191
|
|
|
189
|
-
return l.view(left_bond_dim,
|
|
192
|
+
return l.view(left_bond_dim, dim, -1), r.view(-1, dim, right_bond_dim).to(
|
|
193
|
+
right_device
|
|
194
|
+
)
|
|
190
195
|
|
|
191
196
|
|
|
192
197
|
def evolve_single(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: emu-mps
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
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.
|
|
28
|
+
Requires-Dist: emu-base==2.5.0
|
|
29
29
|
Description-Content-Type: text/markdown
|
|
30
30
|
|
|
31
31
|
<div align="center">
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
emu_mps/__init__.py,sha256=
|
|
1
|
+
emu_mps/__init__.py,sha256=att-gSzRc9t4OvllrmSVf_vPjP2WlmqT_sBJ020sv0c,708
|
|
2
2
|
emu_mps/algebra.py,sha256=VZ5uaX5PYWGqDCpRKKr819BLMMtT0pKDxc2HrlLCdgU,5423
|
|
3
3
|
emu_mps/custom_callback_implementations.py,sha256=WeczmO6qkvBIipvXLqX45i3D7M4ovOrepusIGs6d2Ts,2420
|
|
4
4
|
emu_mps/hamiltonian.py,sha256=OM0bPNZV7J5Egk6aTUwt4GaWqiUOP68ujZBTuqlBY1k,16289
|
|
5
5
|
emu_mps/mpo.py,sha256=WmGDGkCMhlODmydd0b09YcSRlsk6Bg5xYQ4rXSNJvnY,9703
|
|
6
|
-
emu_mps/mps.py,sha256=
|
|
7
|
-
emu_mps/mps_backend.py,sha256=
|
|
8
|
-
emu_mps/mps_backend_impl.py,sha256=
|
|
9
|
-
emu_mps/mps_config.py,sha256=
|
|
6
|
+
emu_mps/mps.py,sha256=9LcneNCGMLYQJfiTQrDzBKz-YQmcL76P9l-A-3_bXOI,21707
|
|
7
|
+
emu_mps/mps_backend.py,sha256=dXcW5Fa2AAL_WlHUgr30WS2l3qiDJgBVebiVpyYWpPM,2064
|
|
8
|
+
emu_mps/mps_backend_impl.py,sha256=WyB1PpC61rzrnr_c3epVZOhDtXLOdhQLsMgUtZQWCYg,30851
|
|
9
|
+
emu_mps/mps_config.py,sha256=btlygf6VDFna9TQus-zOmUqB6pfe_aoQmNoivfvxABk,8251
|
|
10
10
|
emu_mps/observables.py,sha256=4C_ewkd3YkJP0xghTrGUTgXUGvJRCQcetb8cU0SjMl0,1900
|
|
11
11
|
emu_mps/solver.py,sha256=M9xkHhlEouTBvoPw2UYVu6kij7CO4Z1FXw_SiGFtdgo,85
|
|
12
|
-
emu_mps/solver_utils.py,sha256=
|
|
12
|
+
emu_mps/solver_utils.py,sha256=Q1SY8E3Kipe_RfKE8lAMRfD4mSG2VkkkPmk-fU7eAgY,8852
|
|
13
13
|
emu_mps/utils.py,sha256=rL75H55hB5lDMjy8a_O2PpJq51iZKjSx91X4euxB3mY,7293
|
|
14
14
|
emu_mps/optimatrix/__init__.py,sha256=fBXQ7-rgDro4hcaBijCGhx3J69W96qcw5_3mWc7tND4,364
|
|
15
15
|
emu_mps/optimatrix/optimiser.py,sha256=k9suYmKLKlaZ7ozFuIqvXHyCBoCtGgkX1mpen9GOdOo,6977
|
|
16
16
|
emu_mps/optimatrix/permutations.py,sha256=9DDMZtrGGZ01b9F3GkzHR3paX4qNtZiPoI7Z_Kia3Lc,3727
|
|
17
|
-
emu_mps-2.
|
|
18
|
-
emu_mps-2.
|
|
19
|
-
emu_mps-2.
|
|
17
|
+
emu_mps-2.5.0.dist-info/METADATA,sha256=La-IngskVDu8pMUaqmyqS_4Fe1qPAnOKfErnPsVpAiQ,3587
|
|
18
|
+
emu_mps-2.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
19
|
+
emu_mps-2.5.0.dist-info/RECORD,,
|
|
File without changes
|