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 CHANGED
@@ -28,4 +28,4 @@ if sys.version_info < (3, 10, 0): # pragma: no cover
28
28
  'of cirq (e.g. "python -m pip install cirq==1.1.*")'
29
29
  )
30
30
 
31
- __version__ = "1.5.0.dev20240722144600"
31
+ __version__ = "1.5.0.dev20240723233926"
cirq/_version_test.py CHANGED
@@ -3,4 +3,4 @@ import cirq
3
3
 
4
4
 
5
5
  def test_version():
6
- assert cirq.__version__ == "1.5.0.dev20240722144600"
6
+ assert cirq.__version__ == "1.5.0.dev20240723233926"
@@ -13,17 +13,18 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from collections.abc import Sequence
16
- from typing import Any, Literal
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 to map qubits to
26
- random pauli bases."""
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: 'cirq.AbstractCircuit',
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 list of circuits with the pre-measurement unitaries. If no arguments are specified,
46
- it will default to computing the entropy of the entire circuit.
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
- rng: Random number generator.
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
- List of circuits with pre-measurement unitaries and measurements added
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
- qubits = sorted(circuit.all_qubits())
60
- num_qubits = len(qubits)
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(*qubits, key='m')
77
+ *circuit.moments, pre_measurement_moment, cirq.M(*subsystem_qubits, key="m")
67
78
  )
68
79
 
69
- def _generate_unitaries_list(self, rng: np.random.Generator, num_qubits: int) -> Sequence[Any]:
70
- """Generates a list of pre-measurement unitaries."""
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
- unitaries: List of pre-measurement unitaries
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: The cirq moment associated with the pre-measurement rotations
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
- for idx, pauli in enumerate(unitaries):
93
- op_list.append(_pauli_basis_rotation(pauli).on(qubits[idx]))
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(basis: Literal["X", "Y", "Z"]) -> 'cirq.Gate':
99
- """Given a measurement basis returns the associated rotation.
117
+ def _pauli_basis_rotation(rng: np.random.Generator) -> "cirq.Gate":
118
+ """Randomly generate a Pauli basis rotation.
119
+
100
120
  Args:
101
- basis: Measurement basis
102
- Returns: The cirq gate for associated with measurement basis
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
- if basis == "X":
105
- return cirq.Ry(rads=-np.pi / 2)
106
- elif basis == "Y":
107
- return cirq.Rx(rads=np.pi / 2)
108
- elif basis == "Z":
109
- return cirq.I
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
- circuit = cirq.Circuit([cirq.H(q0), cirq.CNOT(q0, q1), cirq.CNOT(q1, q2), cirq.CNOT(q2, q3)])
23
- num_moments_pre = len(circuit.moments)
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
- circuit = rand_meas.RandomizedMeasurements()(circuit)
27
-
28
- num_moments_post = len(circuit.moments)
29
- assert num_moments_post == num_moments_pre + 2
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) == cirq.I(q2)
42
- assert circuit.operation_at(q3, 4) == cirq.I(q3)
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) == cirq.I(q1)
55
- assert circuit.operation_at(q3, 4) == cirq.I(q3)
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")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cirq-core
3
- Version: 1.5.0.dev20240722144600
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
@@ -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=uQ2OPDBBSCYg-g44pLd6AcUQaaI_lBysU-q2bzHBdvc,1206
8
- cirq/_version_test.py,sha256=lxJ-EcPcJ7r1KMcxpsSNXP55oet4YsgQNK1HAHIdKlM,147
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=GfHI2dtx6MmHbp0akXACi44GD7CoDNB_wdmFZPyaETc,4049
1050
- cirq/transformers/randomized_measurements_test.py,sha256=gvlXALIe1pm-fgNth0usSePnj0Gdx3kc40rKSbaAFHI,2265
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.dev20240722144600.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1185
- cirq_core-1.5.0.dev20240722144600.dist-info/METADATA,sha256=PHLo6VtKVya5vWnrtyHsAreaAdVeBmz6g0zfCQEtDLI,2007
1186
- cirq_core-1.5.0.dev20240722144600.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
1187
- cirq_core-1.5.0.dev20240722144600.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1188
- cirq_core-1.5.0.dev20240722144600.dist-info/RECORD,,
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,,