cirq-core 1.5.0.dev20240722144600__py3-none-any.whl → 1.5.0.dev20240723233926__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.
Potentially problematic release.
This version of cirq-core might be problematic. Click here for more details.
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/transformers/randomized_measurements.py +105 -44
- cirq/transformers/randomized_measurements_test.py +23 -11
- {cirq_core-1.5.0.dev20240722144600.dist-info → cirq_core-1.5.0.dev20240723233926.dist-info}/METADATA +1 -1
- {cirq_core-1.5.0.dev20240722144600.dist-info → cirq_core-1.5.0.dev20240723233926.dist-info}/RECORD +9 -9
- {cirq_core-1.5.0.dev20240722144600.dist-info → cirq_core-1.5.0.dev20240723233926.dist-info}/LICENSE +0 -0
- {cirq_core-1.5.0.dev20240722144600.dist-info → cirq_core-1.5.0.dev20240723233926.dist-info}/WHEEL +0 -0
- {cirq_core-1.5.0.dev20240722144600.dist-info → cirq_core-1.5.0.dev20240723233926.dist-info}/top_level.txt +0 -0
cirq/_version.py
CHANGED
cirq/_version_test.py
CHANGED
|
@@ -13,17 +13,18 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from collections.abc import Sequence
|
|
16
|
-
from typing import Any
|
|
16
|
+
from typing import Any
|
|
17
17
|
|
|
18
18
|
import cirq
|
|
19
19
|
import numpy as np
|
|
20
|
+
from cirq.ops import SingleQubitCliffordGate
|
|
20
21
|
from cirq.transformers import transformer_api
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
@transformer_api.transformer
|
|
24
25
|
class RandomizedMeasurements:
|
|
25
|
-
"""A transformer that appends a moment of random rotations
|
|
26
|
-
|
|
26
|
+
"""A transformer that appends a moment of random rotations from a given unitary ensemble (pauli,
|
|
27
|
+
clifford, cue)"""
|
|
27
28
|
|
|
28
29
|
def __init__(self, subsystem: Sequence[int] | None = None):
|
|
29
30
|
"""Class structure for performing and analyzing a general randomized measurement protocol.
|
|
@@ -31,79 +32,139 @@ class RandomizedMeasurements:
|
|
|
31
32
|
|
|
32
33
|
Args:
|
|
33
34
|
subsystem: The specific subsystem (e.g qubit index) to measure in random basis
|
|
35
|
+
rest of the qubits are measured in the computational basis
|
|
34
36
|
"""
|
|
35
37
|
self.subsystem = subsystem
|
|
36
38
|
|
|
37
39
|
def __call__(
|
|
38
40
|
self,
|
|
39
|
-
circuit:
|
|
41
|
+
circuit: "cirq.AbstractCircuit",
|
|
42
|
+
unitary_ensemble: str = "pauli",
|
|
40
43
|
rng: np.random.Generator | None = None,
|
|
41
44
|
*,
|
|
42
45
|
context: transformer_api.TransformerContext | None = None,
|
|
43
|
-
):
|
|
46
|
+
) -> "cirq.Circuit":
|
|
44
47
|
"""Apply the transformer to the given circuit. Given an input circuit returns
|
|
45
|
-
a
|
|
46
|
-
|
|
48
|
+
a new circuit with the pre-measurement unitaries and measurements gates added.
|
|
49
|
+
to the qubits in the subsystem provided.If no subsystem is specified in the
|
|
50
|
+
construction of this class it defaults to measuring all the qubits in the
|
|
51
|
+
randomized bases.
|
|
47
52
|
|
|
48
53
|
Args:
|
|
49
54
|
circuit: The circuit to add randomized measurements to.
|
|
50
|
-
|
|
55
|
+
unitary_ensemble: Choice of unitary ensemble (pauli/clifford/cue(circular
|
|
56
|
+
unitary ensemble))
|
|
51
57
|
context: Not used; to satisfy transformer API.
|
|
58
|
+
rng: Random number generator.
|
|
52
59
|
|
|
53
60
|
Returns:
|
|
54
|
-
|
|
61
|
+
A circuit with pre-measurement unitaries and measurements added
|
|
55
62
|
"""
|
|
63
|
+
|
|
64
|
+
all_qubits = sorted(circuit.all_qubits())
|
|
65
|
+
if self.subsystem is None:
|
|
66
|
+
subsystem_qubits = all_qubits
|
|
67
|
+
else:
|
|
68
|
+
subsystem_qubits = [all_qubits[s] for s in self.subsystem]
|
|
56
69
|
if rng is None:
|
|
57
70
|
rng = np.random.default_rng()
|
|
58
71
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
pre_measurement_unitaries_list = self._generate_unitaries_list(rng, num_qubits)
|
|
63
|
-
pre_measurement_moment = self.unitaries_to_moment(pre_measurement_unitaries_list, qubits)
|
|
72
|
+
pre_measurement_moment = self.random_single_qubit_unitary_moment(
|
|
73
|
+
unitary_ensemble, subsystem_qubits, rng
|
|
74
|
+
)
|
|
64
75
|
|
|
65
76
|
return cirq.Circuit.from_moments(
|
|
66
|
-
*circuit.moments, pre_measurement_moment, cirq.M(*
|
|
77
|
+
*circuit.moments, pre_measurement_moment, cirq.M(*subsystem_qubits, key="m")
|
|
67
78
|
)
|
|
68
79
|
|
|
69
|
-
def
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
pauli_strings = rng.choice(["X", "Y", "Z"], size=num_qubits)
|
|
73
|
-
|
|
74
|
-
if self.subsystem is not None:
|
|
75
|
-
for i in range(pauli_strings.shape[0]):
|
|
76
|
-
if i not in self.subsystem:
|
|
77
|
-
pauli_strings[i] = np.array("Z")
|
|
78
|
-
|
|
79
|
-
return pauli_strings.tolist()
|
|
80
|
-
|
|
81
|
-
def unitaries_to_moment(
|
|
82
|
-
self, unitaries: Sequence[Literal["X", "Y", "Z"]], qubits: Sequence[Any]
|
|
83
|
-
) -> 'cirq.Moment':
|
|
80
|
+
def random_single_qubit_unitary_moment(
|
|
81
|
+
self, unitary_ensemble: str, qubits: Sequence[Any], rng: np.random.Generator
|
|
82
|
+
) -> "cirq.Moment":
|
|
84
83
|
"""Outputs the cirq moment associated with the pre-measurement rotations.
|
|
84
|
+
|
|
85
85
|
Args:
|
|
86
|
-
|
|
86
|
+
unitary_ensemble: clifford, pauli, cue
|
|
87
87
|
qubits: List of qubits
|
|
88
|
+
rng: Random number generator to be used in sampling.
|
|
88
89
|
|
|
89
|
-
Returns:
|
|
90
|
+
Returns:
|
|
91
|
+
The cirq moment associated with the pre-measurement rotations
|
|
92
|
+
|
|
93
|
+
Raises:
|
|
94
|
+
ValueError: When unitary_ensemble is not one of "cue", "pauli" or "clifford"
|
|
90
95
|
"""
|
|
96
|
+
|
|
97
|
+
if unitary_ensemble.lower() == "pauli":
|
|
98
|
+
unitaries = [_pauli_basis_rotation(rng) for _ in range(len(qubits))]
|
|
99
|
+
|
|
100
|
+
elif unitary_ensemble.lower() == "clifford":
|
|
101
|
+
unitaries = [_single_qubit_clifford(rng) for _ in range(len(qubits))]
|
|
102
|
+
|
|
103
|
+
elif unitary_ensemble.lower() == "cue":
|
|
104
|
+
unitaries = [_single_qubit_cue(rng) for _ in range(len(qubits))]
|
|
105
|
+
|
|
106
|
+
else:
|
|
107
|
+
raise ValueError("Only pauli, clifford and cue unitaries are available")
|
|
108
|
+
|
|
91
109
|
op_list: list[cirq.Operation] = []
|
|
92
|
-
|
|
93
|
-
|
|
110
|
+
|
|
111
|
+
for idx, unitary in enumerate(unitaries):
|
|
112
|
+
op_list.append(unitary.on(qubits[idx]))
|
|
94
113
|
|
|
95
114
|
return cirq.Moment.from_ops(*op_list)
|
|
96
115
|
|
|
97
116
|
|
|
98
|
-
def _pauli_basis_rotation(
|
|
99
|
-
"""
|
|
117
|
+
def _pauli_basis_rotation(rng: np.random.Generator) -> "cirq.Gate":
|
|
118
|
+
"""Randomly generate a Pauli basis rotation.
|
|
119
|
+
|
|
100
120
|
Args:
|
|
101
|
-
|
|
102
|
-
|
|
121
|
+
rng: Random number generator
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
cirq gate
|
|
125
|
+
"""
|
|
126
|
+
basis_idx = rng.choice(np.arange(3))
|
|
127
|
+
|
|
128
|
+
if basis_idx == 0:
|
|
129
|
+
gate: "cirq.Gate" = cirq.Ry(rads=-np.pi / 2)
|
|
130
|
+
elif basis_idx == 1:
|
|
131
|
+
gate = cirq.Rx(rads=np.pi / 2)
|
|
132
|
+
else:
|
|
133
|
+
gate = cirq.I
|
|
134
|
+
return gate
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _single_qubit_clifford(rng: np.random.Generator) -> "cirq.Gate":
|
|
138
|
+
"""Randomly generate a single-qubit Clifford rotation.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
rng: Random number generator
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
cirq gate
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
# there are 24 distinct single-qubit Clifford gates
|
|
148
|
+
clifford_idx = rng.choice(np.arange(24))
|
|
149
|
+
|
|
150
|
+
return SingleQubitCliffordGate.to_phased_xz_gate(
|
|
151
|
+
SingleQubitCliffordGate.all_single_qubit_cliffords[clifford_idx]
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _single_qubit_cue(rng: np.random.Generator) -> "cirq.Gate":
|
|
156
|
+
"""Randomly generate a CUE gate.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
rng: Random number generator
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
cirq gate
|
|
103
163
|
"""
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
164
|
+
|
|
165
|
+
# phasedxz parameters are distinct between -1 and +1
|
|
166
|
+
x_exponent, z_exponent, axis_phase_exponent = 1 - 2 * rng.random(size=3)
|
|
167
|
+
|
|
168
|
+
return cirq.PhasedXZGate(
|
|
169
|
+
x_exponent=x_exponent, z_exponent=z_exponent, axis_phase_exponent=axis_phase_exponent
|
|
170
|
+
)
|
|
@@ -14,19 +14,23 @@
|
|
|
14
14
|
|
|
15
15
|
import cirq
|
|
16
16
|
import cirq.transformers.randomized_measurements as rand_meas
|
|
17
|
+
import pytest
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
def test_randomized_measurements_appends_two_moments_on_returned_circuit():
|
|
20
21
|
# Create a 4-qubit circuit
|
|
21
22
|
q0, q1, q2, q3 = cirq.LineQubit.range(4)
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
circuit_pre = cirq.Circuit(
|
|
24
|
+
[cirq.H(q0), cirq.CNOT(q0, q1), cirq.CNOT(q1, q2), cirq.CNOT(q2, q3)]
|
|
25
|
+
)
|
|
26
|
+
num_moments_pre = len(circuit_pre.moments)
|
|
24
27
|
|
|
25
28
|
# Append randomized measurements to subsystem
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
unitary_ensembles = ['pauli', 'clifford', 'cue']
|
|
30
|
+
for u in unitary_ensembles:
|
|
31
|
+
circuit_post = rand_meas.RandomizedMeasurements()(circuit_pre, unitary_ensemble=u)
|
|
32
|
+
num_moments_post = len(circuit_post.moments)
|
|
33
|
+
assert num_moments_post == num_moments_pre + 2
|
|
30
34
|
|
|
31
35
|
|
|
32
36
|
def test_append_randomized_measurements_leaves_qubits_not_in_specified_subsystem_unchanged():
|
|
@@ -36,10 +40,9 @@ def test_append_randomized_measurements_leaves_qubits_not_in_specified_subsystem
|
|
|
36
40
|
|
|
37
41
|
# Append randomized measurements to subsystem
|
|
38
42
|
circuit = rand_meas.RandomizedMeasurements(subsystem=(0, 1))(circuit)
|
|
39
|
-
|
|
40
43
|
# assert latter subsystems were not changed.
|
|
41
|
-
assert circuit.operation_at(q2, 4)
|
|
42
|
-
assert circuit.operation_at(q3, 4)
|
|
44
|
+
assert circuit.operation_at(q2, 4) is None
|
|
45
|
+
assert circuit.operation_at(q3, 4) is None
|
|
43
46
|
|
|
44
47
|
|
|
45
48
|
def test_append_randomized_measurements_leaves_qubits_not_in_noncontinuous_subsystem_unchanged():
|
|
@@ -51,5 +54,14 @@ def test_append_randomized_measurements_leaves_qubits_not_in_noncontinuous_subsy
|
|
|
51
54
|
circuit = rand_meas.RandomizedMeasurements(subsystem=(0, 2))(circuit)
|
|
52
55
|
|
|
53
56
|
# assert latter subsystems were not changed.
|
|
54
|
-
assert circuit.operation_at(q1, 4)
|
|
55
|
-
assert circuit.operation_at(q3, 4)
|
|
57
|
+
assert circuit.operation_at(q1, 4) is None
|
|
58
|
+
assert circuit.operation_at(q3, 4) is None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_exception():
|
|
62
|
+
q0, q1, q2, q3 = cirq.LineQubit.range(4)
|
|
63
|
+
circuit = cirq.Circuit([cirq.H(q0), cirq.CNOT(q0, q1), cirq.CNOT(q1, q2), cirq.CNOT(q2, q3)])
|
|
64
|
+
|
|
65
|
+
# Append randomized measurements to subsystem
|
|
66
|
+
with pytest.raises(ValueError):
|
|
67
|
+
rand_meas.RandomizedMeasurements()(circuit, unitary_ensemble="coe")
|
{cirq_core-1.5.0.dev20240722144600.dist-info → cirq_core-1.5.0.dev20240723233926.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cirq-core
|
|
3
|
-
Version: 1.5.0.
|
|
3
|
+
Version: 1.5.0.dev20240723233926
|
|
4
4
|
Summary: A framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
|
|
5
5
|
Home-page: http://github.com/quantumlib/cirq
|
|
6
6
|
Author: The Cirq Developers
|
{cirq_core-1.5.0.dev20240722144600.dist-info → cirq_core-1.5.0.dev20240723233926.dist-info}/RECORD
RENAMED
|
@@ -4,8 +4,8 @@ cirq/_compat_test.py,sha256=Qq3ZcfgD-Nb81cEppQdJqhAyrVqXKtfXZYGXT0p-Wh0,34718
|
|
|
4
4
|
cirq/_doc.py,sha256=yDyWUD_2JDS0gShfGRb-rdqRt9-WeL7DhkqX7np0Nko,2879
|
|
5
5
|
cirq/_import.py,sha256=p9gMHJscbtDDkfHOaulvd3Aer0pwUF5AXpL89XR8dNw,8402
|
|
6
6
|
cirq/_import_test.py,sha256=6K_v0riZJXOXUphHNkGA8MY-JcmGlezFaGmvrNhm3OQ,1015
|
|
7
|
-
cirq/_version.py,sha256=
|
|
8
|
-
cirq/_version_test.py,sha256=
|
|
7
|
+
cirq/_version.py,sha256=vqNxUekJB6OW8tq4V5O46uke_u4hHGYkb1-RErSMfNk,1206
|
|
8
|
+
cirq/_version_test.py,sha256=FXvASQTfU_0AoGcYal5mjjne-oPGZ2BnUUKSKyadLGs,147
|
|
9
9
|
cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
|
|
10
10
|
cirq/json_resolver_cache.py,sha256=ytePZtNZgKjOF2NiVpUTuotB-JKZmQNOFIFdvXqsxHw,13271
|
|
11
11
|
cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
|
|
@@ -1046,8 +1046,8 @@ cirq/transformers/optimize_for_target_gateset.py,sha256=MxhFsCm2XgW3gdpNW4NGVmz1
|
|
|
1046
1046
|
cirq/transformers/optimize_for_target_gateset_test.py,sha256=MgAHjsPbVtd0fl2ytRz2R-LQuhSqImtrFK5F45QXkA8,19523
|
|
1047
1047
|
cirq/transformers/qubit_management_transformers.py,sha256=A7Mweu9ElLSCsy_atmgFbYlzOFXKhct5gQ5YNTjjaVU,9430
|
|
1048
1048
|
cirq/transformers/qubit_management_transformers_test.py,sha256=GGuZ4uxtFI59t9diW67_J17XQdBu9NFZjOHeMAHmm8Y,13991
|
|
1049
|
-
cirq/transformers/randomized_measurements.py,sha256=
|
|
1050
|
-
cirq/transformers/randomized_measurements_test.py,sha256=
|
|
1049
|
+
cirq/transformers/randomized_measurements.py,sha256=E1VG4sKWcZ-OZINpFT7F2n0I3kZpButkjNbHz95YaVw,5686
|
|
1050
|
+
cirq/transformers/randomized_measurements_test.py,sha256=z3K3YiGFiOrxw0dVjKUxRwbRHKspVvisyM1tpSKozl0,2736
|
|
1051
1051
|
cirq/transformers/stratify.py,sha256=EEcXD6PEdHTZAoaAfaHnsw3Hf1SftbIl19hZOU_ZnXE,10469
|
|
1052
1052
|
cirq/transformers/stratify_test.py,sha256=17ic2VAUPEGuPG2o5j98yDxQ2j2J_PN3EsPsfh5xwUk,15220
|
|
1053
1053
|
cirq/transformers/synchronize_terminal_measurements.py,sha256=p061MYYglY6HhWYYkFzIny0CtaY9LUygPg4UbGewZhQ,3842
|
|
@@ -1181,8 +1181,8 @@ cirq/work/sampler.py,sha256=JEAeQQRF3bqlO9AkOf4XbrTATDI5f5JgyM_FAUCNxao,19751
|
|
|
1181
1181
|
cirq/work/sampler_test.py,sha256=B2ZsuqGT854gQtBIAh8k0LiG9Vj5wSzcGvkxOUoTcW4,13217
|
|
1182
1182
|
cirq/work/zeros_sampler.py,sha256=x1C7cup66a43n-3tm8QjhiqJa07qcJW10FxNp9jJ59Q,2356
|
|
1183
1183
|
cirq/work/zeros_sampler_test.py,sha256=JIkpBBFPJe5Ba4142vzogyWyboG1Q1ZAm0UVGgOoZn8,3279
|
|
1184
|
-
cirq_core-1.5.0.
|
|
1185
|
-
cirq_core-1.5.0.
|
|
1186
|
-
cirq_core-1.5.0.
|
|
1187
|
-
cirq_core-1.5.0.
|
|
1188
|
-
cirq_core-1.5.0.
|
|
1184
|
+
cirq_core-1.5.0.dev20240723233926.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
|
1185
|
+
cirq_core-1.5.0.dev20240723233926.dist-info/METADATA,sha256=reaHCvMFs4BM9GguxY_5tcT4_A8Qua34H-QGz2D7EUQ,2007
|
|
1186
|
+
cirq_core-1.5.0.dev20240723233926.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
1187
|
+
cirq_core-1.5.0.dev20240723233926.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
|
|
1188
|
+
cirq_core-1.5.0.dev20240723233926.dist-info/RECORD,,
|
{cirq_core-1.5.0.dev20240722144600.dist-info → cirq_core-1.5.0.dev20240723233926.dist-info}/LICENSE
RENAMED
|
File without changes
|
{cirq_core-1.5.0.dev20240722144600.dist-info → cirq_core-1.5.0.dev20240723233926.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|