cirq-core 1.6.0.dev20250624001344__py3-none-any.whl → 1.6.0.dev20250625011740__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/__init__.py +1 -0
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/transformers/__init__.py +1 -0
- cirq/transformers/merge_single_qubit_gates.py +178 -7
- cirq/transformers/merge_single_qubit_gates_test.py +142 -2
- {cirq_core-1.6.0.dev20250624001344.dist-info → cirq_core-1.6.0.dev20250625011740.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250624001344.dist-info → cirq_core-1.6.0.dev20250625011740.dist-info}/RECORD +11 -11
- {cirq_core-1.6.0.dev20250624001344.dist-info → cirq_core-1.6.0.dev20250625011740.dist-info}/WHEEL +0 -0
- {cirq_core-1.6.0.dev20250624001344.dist-info → cirq_core-1.6.0.dev20250625011740.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250624001344.dist-info → cirq_core-1.6.0.dev20250625011740.dist-info}/top_level.txt +0 -0
cirq/__init__.py
CHANGED
|
@@ -380,6 +380,7 @@ from cirq.transformers import (
|
|
|
380
380
|
merge_operations_to_circuit_op as merge_operations_to_circuit_op,
|
|
381
381
|
merge_single_qubit_gates_to_phased_x_and_z as merge_single_qubit_gates_to_phased_x_and_z,
|
|
382
382
|
merge_single_qubit_gates_to_phxz as merge_single_qubit_gates_to_phxz,
|
|
383
|
+
merge_single_qubit_gates_to_phxz_symbolized as merge_single_qubit_gates_to_phxz_symbolized,
|
|
383
384
|
merge_single_qubit_moments_to_phxz as merge_single_qubit_moments_to_phxz,
|
|
384
385
|
optimize_for_target_gateset as optimize_for_target_gateset,
|
|
385
386
|
parameterized_2q_op_to_sqrt_iswap_operations as parameterized_2q_op_to_sqrt_iswap_operations,
|
cirq/_version.py
CHANGED
cirq/_version_test.py
CHANGED
cirq/transformers/__init__.py
CHANGED
|
@@ -100,6 +100,7 @@ from cirq.transformers.merge_single_qubit_gates import (
|
|
|
100
100
|
merge_single_qubit_gates_to_phased_x_and_z as merge_single_qubit_gates_to_phased_x_and_z,
|
|
101
101
|
merge_single_qubit_gates_to_phxz as merge_single_qubit_gates_to_phxz,
|
|
102
102
|
merge_single_qubit_moments_to_phxz as merge_single_qubit_moments_to_phxz,
|
|
103
|
+
merge_single_qubit_gates_to_phxz_symbolized as merge_single_qubit_gates_to_phxz_symbolized,
|
|
103
104
|
)
|
|
104
105
|
|
|
105
106
|
from cirq.transformers.qubit_management_transformers import (
|
|
@@ -16,13 +16,24 @@
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
-
from typing import TYPE_CHECKING
|
|
19
|
+
from typing import Callable, cast, Hashable, TYPE_CHECKING
|
|
20
20
|
|
|
21
21
|
from cirq import circuits, ops, protocols
|
|
22
|
-
from cirq.
|
|
22
|
+
from cirq.study.resolver import ParamResolver
|
|
23
|
+
from cirq.study.sweeps import dict_to_zip_sweep, ListSweep, ProductOrZipSweepLike, Sweep, Zip
|
|
24
|
+
from cirq.transformers import (
|
|
25
|
+
align,
|
|
26
|
+
merge_k_qubit_gates,
|
|
27
|
+
symbolize,
|
|
28
|
+
tag_transformers,
|
|
29
|
+
transformer_api,
|
|
30
|
+
transformer_primitives,
|
|
31
|
+
)
|
|
23
32
|
from cirq.transformers.analytical_decompositions import single_qubit_decompositions
|
|
24
33
|
|
|
25
34
|
if TYPE_CHECKING:
|
|
35
|
+
import sympy
|
|
36
|
+
|
|
26
37
|
import cirq
|
|
27
38
|
|
|
28
39
|
|
|
@@ -67,6 +78,7 @@ def merge_single_qubit_gates_to_phxz(
|
|
|
67
78
|
circuit: cirq.AbstractCircuit,
|
|
68
79
|
*,
|
|
69
80
|
context: cirq.TransformerContext | None = None,
|
|
81
|
+
merge_tags_fn: Callable[[cirq.CircuitOperation], list[Hashable]] | None = None,
|
|
70
82
|
atol: float = 1e-8,
|
|
71
83
|
) -> cirq.Circuit:
|
|
72
84
|
"""Replaces runs of single qubit rotations with a single optional `cirq.PhasedXZGate`.
|
|
@@ -77,6 +89,7 @@ def merge_single_qubit_gates_to_phxz(
|
|
|
77
89
|
Args:
|
|
78
90
|
circuit: Input circuit to transform. It will not be modified.
|
|
79
91
|
context: `cirq.TransformerContext` storing common configurable options for transformers.
|
|
92
|
+
merge_tags_fn: A callable returns the tags to be added to the merged operation.
|
|
80
93
|
atol: Absolute tolerance to angle error. Larger values allow more negligible gates to be
|
|
81
94
|
dropped, smaller values increase accuracy.
|
|
82
95
|
|
|
@@ -84,12 +97,13 @@ def merge_single_qubit_gates_to_phxz(
|
|
|
84
97
|
Copy of the transformed input circuit.
|
|
85
98
|
"""
|
|
86
99
|
|
|
87
|
-
def rewriter(
|
|
88
|
-
u = protocols.unitary(
|
|
89
|
-
if protocols.num_qubits(
|
|
100
|
+
def rewriter(circuit_op: cirq.CircuitOperation) -> cirq.OP_TREE:
|
|
101
|
+
u = protocols.unitary(circuit_op)
|
|
102
|
+
if protocols.num_qubits(circuit_op) == 0:
|
|
90
103
|
return ops.GlobalPhaseGate(u[0, 0]).on()
|
|
91
|
-
gate = single_qubit_decompositions.single_qubit_matrix_to_phxz(u, atol)
|
|
92
|
-
|
|
104
|
+
gate = single_qubit_decompositions.single_qubit_matrix_to_phxz(u, atol) or ops.I
|
|
105
|
+
phxz_op = gate.on(circuit_op.qubits[0])
|
|
106
|
+
return phxz_op.with_tags(*merge_tags_fn(circuit_op)) if merge_tags_fn else phxz_op
|
|
93
107
|
|
|
94
108
|
return merge_k_qubit_gates.merge_k_qubit_unitaries(
|
|
95
109
|
circuit, k=1, context=context, rewriter=rewriter
|
|
@@ -158,3 +172,160 @@ def merge_single_qubit_moments_to_phxz(
|
|
|
158
172
|
deep=context.deep if context else False,
|
|
159
173
|
tags_to_ignore=tuple(tags_to_ignore),
|
|
160
174
|
).unfreeze(copy=False)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _sweep_on_symbols(sweep: Sweep, symbols: set[sympy.Symbol]) -> Sweep:
|
|
178
|
+
new_resolvers: list[cirq.ParamResolver] = []
|
|
179
|
+
for resolver in sweep:
|
|
180
|
+
param_dict: cirq.ParamMappingType = {s: resolver.value_of(s) for s in symbols}
|
|
181
|
+
new_resolvers.append(ParamResolver(param_dict))
|
|
182
|
+
return ListSweep(new_resolvers)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _calc_phxz_sweeps(
|
|
186
|
+
symbolized_circuit: cirq.Circuit, resolved_circuits: list[cirq.Circuit]
|
|
187
|
+
) -> Sweep:
|
|
188
|
+
"""Return the phxz sweep of the symbolized_circuit on resolved_circuits.
|
|
189
|
+
|
|
190
|
+
Raises:
|
|
191
|
+
ValueError: Structural mismatch: A `resolved_circuit` contains an unexpected gate type.
|
|
192
|
+
Expected a `PhasedXZGate` or `IdentityGate` at a position corresponding to a
|
|
193
|
+
symbolic `PhasedXZGate` in the `symbolized_circuit`.
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
def _extract_axz(op: ops.Operation | None) -> tuple[float, float, float]:
|
|
197
|
+
if not op or not op.gate or not isinstance(op.gate, ops.IdentityGate | ops.PhasedXZGate):
|
|
198
|
+
raise ValueError(f"Expect a PhasedXZGate or IdentityGate on op {op}.")
|
|
199
|
+
if isinstance(op.gate, ops.IdentityGate):
|
|
200
|
+
return 0.0, 0.0, 0.0 # Identity gate's a, x, z in PhasedXZ
|
|
201
|
+
return op.gate.axis_phase_exponent, op.gate.x_exponent, op.gate.z_exponent
|
|
202
|
+
|
|
203
|
+
values_by_params: dict[sympy.Symbol, tuple[float, ...]] = {}
|
|
204
|
+
for mid, moment in enumerate(symbolized_circuit):
|
|
205
|
+
for op in moment.operations:
|
|
206
|
+
if op.gate and isinstance(op.gate, ops.PhasedXZGate) and protocols.is_parameterized(op):
|
|
207
|
+
sa, sx, sz = op.gate.axis_phase_exponent, op.gate.x_exponent, op.gate.z_exponent
|
|
208
|
+
values_by_params[sa], values_by_params[sx], values_by_params[sz] = zip(
|
|
209
|
+
*[_extract_axz(c[mid].operation_at(op.qubits[0])) for c in resolved_circuits]
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
return dict_to_zip_sweep(cast(ProductOrZipSweepLike, values_by_params))
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def merge_single_qubit_gates_to_phxz_symbolized(
|
|
216
|
+
circuit: cirq.AbstractCircuit,
|
|
217
|
+
*,
|
|
218
|
+
context: cirq.TransformerContext | None = None,
|
|
219
|
+
sweep: Sweep,
|
|
220
|
+
atol: float = 1e-8,
|
|
221
|
+
) -> tuple[cirq.Circuit, Sweep]:
|
|
222
|
+
"""Merges consecutive single qubit gates as PhasedXZ Gates. Symbolizes if any of
|
|
223
|
+
the consecutive gates is symbolized.
|
|
224
|
+
|
|
225
|
+
Example:
|
|
226
|
+
>>> q0, q1 = cirq.LineQubit.range(2)
|
|
227
|
+
>>> c = cirq.Circuit(\
|
|
228
|
+
cirq.X(q0),\
|
|
229
|
+
cirq.CZ(q0,q1)**sympy.Symbol("cz_exp"),\
|
|
230
|
+
cirq.Y(q0)**sympy.Symbol("y_exp"),\
|
|
231
|
+
cirq.X(q0))
|
|
232
|
+
>>> print(c)
|
|
233
|
+
0: ───X───@──────────Y^y_exp───X───
|
|
234
|
+
│
|
|
235
|
+
1: ───────@^cz_exp─────────────────
|
|
236
|
+
>>> new_circuit, new_sweep = cirq.merge_single_qubit_gates_to_phxz_symbolized(\
|
|
237
|
+
c, sweep=cirq.Zip(cirq.Points(key="cz_exp", points=[0, 1]),\
|
|
238
|
+
cirq.Points(key="y_exp", points=[0, 1])))
|
|
239
|
+
>>> print(new_circuit)
|
|
240
|
+
0: ───PhXZ(a=-1,x=1,z=0)───@──────────PhXZ(a=a0,x=x0,z=z0)───
|
|
241
|
+
│
|
|
242
|
+
1: ────────────────────────@^cz_exp──────────────────────────
|
|
243
|
+
>>> assert new_sweep[0] == cirq.ParamResolver({'a0': -1, 'x0': 1, 'z0': 0, 'cz_exp': 0})
|
|
244
|
+
>>> assert new_sweep[1] == cirq.ParamResolver({'a0': -0.5, 'x0': 0, 'z0': -1, 'cz_exp': 1})
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
circuit: Input circuit to transform. It will not be modified.
|
|
248
|
+
context: `cirq.TransformerContext` storing common configurable options for transformers.
|
|
249
|
+
sweep: Sweep of the symbols in the input circuit, updated Sweep will be returned
|
|
250
|
+
based on the transformation.
|
|
251
|
+
atol: Absolute tolerance to angle error. Larger values allow more negligible gates to be
|
|
252
|
+
dropped, smaller values increase accuracy.
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
Copy of the transformed input circuit.
|
|
256
|
+
"""
|
|
257
|
+
deep = context.deep if context else False
|
|
258
|
+
|
|
259
|
+
# Tag symbolized single-qubit op.
|
|
260
|
+
symbolized_single_tag = "_tmp_symbolize_tag"
|
|
261
|
+
|
|
262
|
+
circuit_tagged = transformer_primitives.map_operations(
|
|
263
|
+
circuit,
|
|
264
|
+
lambda op, _: (
|
|
265
|
+
op.with_tags(symbolized_single_tag)
|
|
266
|
+
if protocols.is_parameterized(op) and len(op.qubits) == 1
|
|
267
|
+
else op
|
|
268
|
+
),
|
|
269
|
+
deep=deep,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
# Step 0, isolate single qubit symbols and resolve the circuit on them.
|
|
273
|
+
single_qubit_gate_symbols: set[sympy.Symbol] = set().union(
|
|
274
|
+
*[
|
|
275
|
+
protocols.parameter_symbols(op) if symbolized_single_tag in op.tags else set()
|
|
276
|
+
for op in circuit_tagged.all_operations()
|
|
277
|
+
]
|
|
278
|
+
)
|
|
279
|
+
# Remaining symbols, e.g., 2 qubit gates' symbols. Sweep of those symbols keeps unchanged.
|
|
280
|
+
remaining_symbols: set[sympy.Symbol] = set(
|
|
281
|
+
protocols.parameter_symbols(circuit) - single_qubit_gate_symbols
|
|
282
|
+
)
|
|
283
|
+
# If all single qubit gates are not parameterized, call the nonparamerized version of
|
|
284
|
+
# the transformer.
|
|
285
|
+
if not single_qubit_gate_symbols:
|
|
286
|
+
return (merge_single_qubit_gates_to_phxz(circuit, context=context, atol=atol), sweep)
|
|
287
|
+
sweep_of_single: Sweep = _sweep_on_symbols(sweep, single_qubit_gate_symbols)
|
|
288
|
+
# Get all resolved circuits from all sets of resolvers in sweep_of_single.
|
|
289
|
+
resolved_circuits = [
|
|
290
|
+
protocols.resolve_parameters(circuit_tagged, resolver) for resolver in sweep_of_single
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
# Step 1, merge single qubit gates per resolved circuit, preserving
|
|
294
|
+
# the symbolized_single_tag to indicate the operator is a merged one.
|
|
295
|
+
merged_circuits: list[cirq.Circuit] = [
|
|
296
|
+
merge_single_qubit_gates_to_phxz(
|
|
297
|
+
c,
|
|
298
|
+
context=context,
|
|
299
|
+
merge_tags_fn=lambda circuit_op: (
|
|
300
|
+
[symbolized_single_tag]
|
|
301
|
+
if any(
|
|
302
|
+
symbolized_single_tag in set(op.tags)
|
|
303
|
+
for op in circuit_op.circuit.all_operations()
|
|
304
|
+
)
|
|
305
|
+
else []
|
|
306
|
+
),
|
|
307
|
+
atol=atol,
|
|
308
|
+
)
|
|
309
|
+
for c in resolved_circuits
|
|
310
|
+
]
|
|
311
|
+
|
|
312
|
+
# Step 2, get the new symbolized circuit by symbolizing on indexed symbolized_single_tag.
|
|
313
|
+
new_circuit = tag_transformers.remove_tags( # remove the temp tags used to track merges
|
|
314
|
+
symbolize.symbolize_single_qubit_gates_by_indexed_tags(
|
|
315
|
+
tag_transformers.index_tags( # index all 1-qubit-ops merged from ops with symbols
|
|
316
|
+
merged_circuits[0],
|
|
317
|
+
context=transformer_api.TransformerContext(deep=deep),
|
|
318
|
+
target_tags={symbolized_single_tag},
|
|
319
|
+
),
|
|
320
|
+
symbolize_tag=symbolize.SymbolizeTag(prefix=symbolized_single_tag),
|
|
321
|
+
),
|
|
322
|
+
remove_if=lambda tag: str(tag).startswith(symbolized_single_tag),
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
# Step 3, get N sets of parameterizations as new_sweep.
|
|
326
|
+
new_sweep = Zip(
|
|
327
|
+
_calc_phxz_sweeps(new_circuit, merged_circuits), # phxz sweeps
|
|
328
|
+
_sweep_on_symbols(sweep, remaining_symbols), # remaining sweeps
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
return align.align_right(new_circuit), new_sweep
|
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from unittest import TestCase
|
|
16
|
+
from unittest.mock import Mock, patch
|
|
17
|
+
|
|
18
|
+
import pytest
|
|
19
|
+
import sympy
|
|
16
20
|
|
|
17
21
|
import cirq
|
|
18
22
|
|
|
@@ -81,7 +85,7 @@ def test_merge_single_qubit_gates_to_phased_x_and_z_deep():
|
|
|
81
85
|
cirq.testing.assert_same_circuits(c_new, c_expected)
|
|
82
86
|
|
|
83
87
|
|
|
84
|
-
def _phxz(a: float, x: float, z: float):
|
|
88
|
+
def _phxz(a: float | sympy.Symbol, x: float | sympy.Symbol, z: float | sympy.Symbol):
|
|
85
89
|
return cirq.PhasedXZGate(axis_phase_exponent=a, x_exponent=x, z_exponent=z)
|
|
86
90
|
|
|
87
91
|
|
|
@@ -233,6 +237,142 @@ def test_merge_single_qubit_gates_to_phased_x_and_z_global_phase():
|
|
|
233
237
|
assert c == c2
|
|
234
238
|
|
|
235
239
|
|
|
240
|
+
class TestMergeSingleQubitGatesSymbolized(TestCase):
|
|
241
|
+
"""Test suite for merge_single_qubit_gates_to_phxz_symbolized."""
|
|
242
|
+
|
|
243
|
+
def test_case1(self):
|
|
244
|
+
"""Test case diagram.
|
|
245
|
+
Input circuit:
|
|
246
|
+
0: ───X─────────@────────H[ignore]─H──X──PhXZ(a=a0,x=x0,z=z0)──X──PhXZ(a=a1,x=x1,z=z1)───
|
|
247
|
+
│
|
|
248
|
+
1: ───H^h_exp───@^cz_exp─────────────────────────────────────────────────────────────────
|
|
249
|
+
Expected output:
|
|
250
|
+
0: ───PhXZ(a=-1,x=1,z=0)─────@──────────H[ignore]───PhXZ(a=a1,x=x1,z=z1)───
|
|
251
|
+
│
|
|
252
|
+
1: ───PhXZ(a=a0,x=x0,z=z0)───@^cz_exp──────────────────────────────────────
|
|
253
|
+
"""
|
|
254
|
+
a, b = cirq.LineQubit.range(2)
|
|
255
|
+
sa0, sa1 = [sympy.Symbol(a) for a in ["a0", "a1"]]
|
|
256
|
+
sx0, sx1 = [sympy.Symbol(x) for x in ["x0", "x1"]]
|
|
257
|
+
sz0, sz1 = [sympy.Symbol(z) for z in ["z0", "z1"]]
|
|
258
|
+
input_circuit = cirq.Circuit(
|
|
259
|
+
cirq.Moment(cirq.X(a), cirq.H(b) ** sympy.Symbol("h_exp")),
|
|
260
|
+
cirq.Moment(cirq.CZ(a, b) ** sympy.Symbol("cz_exp")),
|
|
261
|
+
cirq.Moment(cirq.H(a).with_tags("ignore")),
|
|
262
|
+
cirq.Moment(cirq.H(a)),
|
|
263
|
+
cirq.Moment(cirq.X(a)),
|
|
264
|
+
cirq.Moment(_phxz(sa0, sx0, sz0).on(a)),
|
|
265
|
+
cirq.Moment(cirq.X(a)),
|
|
266
|
+
cirq.Moment(_phxz(sa1, sx1, sz1).on(a)),
|
|
267
|
+
)
|
|
268
|
+
context = cirq.TransformerContext(tags_to_ignore=["ignore"])
|
|
269
|
+
sweep = cirq.Zip(
|
|
270
|
+
cirq.Points(key="h_exp", points=[0, 1]),
|
|
271
|
+
cirq.Points(key="cz_exp", points=[0, 1]),
|
|
272
|
+
cirq.Points(key="a0", points=[0, 1]),
|
|
273
|
+
cirq.Points(key="x0", points=[0, 1]),
|
|
274
|
+
cirq.Points(key="z0", points=[0, 1]),
|
|
275
|
+
cirq.Points(key="a1", points=[0, 1]),
|
|
276
|
+
cirq.Points(key="x1", points=[0, 1]),
|
|
277
|
+
cirq.Points(key="z1", points=[0, 1]),
|
|
278
|
+
)
|
|
279
|
+
output_circuit, new_sweep = cirq.merge_single_qubit_gates_to_phxz_symbolized(
|
|
280
|
+
input_circuit, context=context, sweep=sweep
|
|
281
|
+
)
|
|
282
|
+
expected = cirq.Circuit(
|
|
283
|
+
cirq.Moment(_phxz(-1, 1, 0).on(a), _phxz(sa0, sx0, sz0).on(b)),
|
|
284
|
+
cirq.Moment(cirq.CZ(a, b) ** sympy.Symbol("cz_exp")),
|
|
285
|
+
cirq.Moment(cirq.H(a).with_tags("ignore")),
|
|
286
|
+
cirq.Moment(_phxz(sa1, sx1, sz1).on(a)),
|
|
287
|
+
)
|
|
288
|
+
assert_optimizes(output_circuit, expected)
|
|
289
|
+
|
|
290
|
+
# Check the unitaries are preserved for each set of sweep paramerization.
|
|
291
|
+
for old_resolver, new_resolver in zip(sweep, new_sweep):
|
|
292
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
293
|
+
cirq.resolve_parameters(input_circuit, old_resolver),
|
|
294
|
+
cirq.resolve_parameters(output_circuit, new_resolver),
|
|
295
|
+
{q: q for q in input_circuit.all_qubits()},
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
def test_with_gauge_compiling_as_sweep_success(self):
|
|
299
|
+
qubits = cirq.LineQubit.range(7)
|
|
300
|
+
c = cirq.Circuit(
|
|
301
|
+
cirq.Moment(cirq.H(qubits[0]), cirq.H(qubits[3])),
|
|
302
|
+
cirq.Moment(cirq.CZ(qubits[0], qubits[2]), cirq.CZ(qubits[3], qubits[5])),
|
|
303
|
+
cirq.Moment(cirq.CZ(qubits[0], qubits[1]), cirq.CZ(qubits[3], qubits[4])),
|
|
304
|
+
cirq.Moment(cirq.CZ(qubits[1], qubits[3]), cirq.CZ(qubits[4], qubits[6])),
|
|
305
|
+
cirq.Moment(cirq.M(*qubits, key='m')),
|
|
306
|
+
)
|
|
307
|
+
old_circuit, old_sweep = cirq.transformers.gauge_compiling.CZGaugeTransformer.as_sweep(
|
|
308
|
+
c, N=50
|
|
309
|
+
)
|
|
310
|
+
new_circuit, new_sweep = cirq.merge_single_qubit_gates_to_phxz_symbolized(
|
|
311
|
+
old_circuit, sweep=old_sweep
|
|
312
|
+
)
|
|
313
|
+
# Check the unitaries are preserved for each set of sweep paramerization.
|
|
314
|
+
for old_resolver, new_resolver in zip(old_sweep, new_sweep):
|
|
315
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
316
|
+
cirq.resolve_parameters(old_circuit[0:-1], old_resolver),
|
|
317
|
+
cirq.resolve_parameters(new_circuit[0:-1], new_resolver),
|
|
318
|
+
{q: q for q in qubits},
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
def test_case_non_parameterized_singles(self):
|
|
322
|
+
"""Test merge_single_qubit_gates_to_phxz_symbolized when all single qubit gates are not
|
|
323
|
+
parameterized."""
|
|
324
|
+
|
|
325
|
+
a, b = cirq.LineQubit.range(2)
|
|
326
|
+
input_circuit = cirq.Circuit(cirq.H(a), cirq.H(a), cirq.CZ(a, b) ** sympy.Symbol("exp"))
|
|
327
|
+
expected_circuit = cirq.merge_single_qubit_gates_to_phxz(input_circuit)
|
|
328
|
+
output_circuit, _ = cirq.merge_single_qubit_gates_to_phxz_symbolized(
|
|
329
|
+
input_circuit, sweep=cirq.Points(key="exp", points=[0.1, 0.2, 0.5])
|
|
330
|
+
)
|
|
331
|
+
assert_optimizes(output_circuit, expected_circuit)
|
|
332
|
+
|
|
333
|
+
def test_fail_different_structures_error(self):
|
|
334
|
+
"""Tests that the function raises a ValueError if merged structures of the circuit differ
|
|
335
|
+
for different parameterizations."""
|
|
336
|
+
q0, q1 = cirq.LineQubit.range(2)
|
|
337
|
+
circuit = cirq.Circuit(cirq.H(q0) ** sympy.Symbol("exp"))
|
|
338
|
+
sweep = cirq.Points(key="exp", points=[0.1, 0.2])
|
|
339
|
+
|
|
340
|
+
with patch(
|
|
341
|
+
"cirq.protocols.resolve_parameters",
|
|
342
|
+
side_effect=[ # Mock the return values of resolve_parameters
|
|
343
|
+
cirq.Circuit(cirq.I(q0).with_tags("_tmp_symbolize_tag")),
|
|
344
|
+
cirq.Circuit(cirq.CZ(q0, q1)),
|
|
345
|
+
],
|
|
346
|
+
):
|
|
347
|
+
with pytest.raises(ValueError, match="Expect a PhasedXZGate or IdentityGate.*"):
|
|
348
|
+
cirq.merge_single_qubit_gates_to_phxz_symbolized(circuit, sweep=sweep)
|
|
349
|
+
|
|
350
|
+
def test_fail_unexpected_gate_error(self):
|
|
351
|
+
"""Tests that the function raises a RuntimeError of unexpected gate."""
|
|
352
|
+
a, b = cirq.LineQubit.range(2)
|
|
353
|
+
circuit = cirq.Circuit(
|
|
354
|
+
cirq.H(a) ** sympy.Symbol("exp1"),
|
|
355
|
+
cirq.X(a),
|
|
356
|
+
cirq.CZ(a, b),
|
|
357
|
+
cirq.Y(a),
|
|
358
|
+
cirq.H(a) ** sympy.Symbol("exp2"),
|
|
359
|
+
)
|
|
360
|
+
sweep = cirq.Points(key="exp1", points=[0.1, 0.2]) * cirq.Points(
|
|
361
|
+
key="exp2", points=[0.1, 0.2]
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
mock_iter = Mock()
|
|
365
|
+
mock_iter.__next__ = Mock(return_value=2)
|
|
366
|
+
|
|
367
|
+
with patch(
|
|
368
|
+
"cirq.transformers.analytical_decompositions"
|
|
369
|
+
".single_qubit_decompositions.single_qubit_matrix_to_phxz",
|
|
370
|
+
return_value=cirq.H,
|
|
371
|
+
):
|
|
372
|
+
with pytest.raises(ValueError, match="Expect a PhasedXZGate or IdentityGate.*"):
|
|
373
|
+
cirq.merge_single_qubit_gates_to_phxz_symbolized(circuit, sweep=sweep)
|
|
374
|
+
|
|
375
|
+
|
|
236
376
|
def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_first_moment():
|
|
237
377
|
q0 = cirq.LineQubit(0)
|
|
238
378
|
c_orig = cirq.Circuit(
|
{cirq_core-1.6.0.dev20250624001344.dist-info → cirq_core-1.6.0.dev20250625011740.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cirq-core
|
|
3
|
-
Version: 1.6.0.
|
|
3
|
+
Version: 1.6.0.dev20250625011740
|
|
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.6.0.dev20250624001344.dist-info → cirq_core-1.6.0.dev20250625011740.dist-info}/RECORD
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
cirq/__init__.py,sha256=
|
|
1
|
+
cirq/__init__.py,sha256=n670ZaGq1Yuj88GYz87JeuXoFH91-FZLH7RbJ2-vAho,28315
|
|
2
2
|
cirq/_compat.py,sha256=BCAAJx19-5UXHv3HpCzewinx-b9eDs_C1GHPXPfKLIY,29478
|
|
3
3
|
cirq/_compat_test.py,sha256=emXpdD5ZvwLRlFAoQB8YatmZyU3b4e9jg6FppMTUhkU,33900
|
|
4
4
|
cirq/_doc.py,sha256=BrnoABo1hk5RgB3Cgww4zLHUfiyFny0F1V-tOMCbdaU,2909
|
|
5
5
|
cirq/_import.py,sha256=ixBu4EyGl46Ram2cP3p5eZVEFDW5L2DS-VyTjz4N9iw,8429
|
|
6
6
|
cirq/_import_test.py,sha256=oF4izzOVZLc7NZ0aZHFcGv-r01eiFFt_JORx_x7_D4s,1089
|
|
7
|
-
cirq/_version.py,sha256=
|
|
8
|
-
cirq/_version_test.py,sha256=
|
|
7
|
+
cirq/_version.py,sha256=IH_yywLC2DP2aoKRwaMc-SSgj8xtbawI_twNVETqkKo,1206
|
|
8
|
+
cirq/_version_test.py,sha256=U7bVhNAYqNObqaCFrE56cK-cTnxPKD87NR_9rSy22eY,155
|
|
9
9
|
cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
|
|
10
10
|
cirq/json_resolver_cache.py,sha256=hYyG53VJeV61X0oukK5ndZYega8lkL2FyaL1m0j6h5M,13556
|
|
11
11
|
cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
|
|
@@ -1050,7 +1050,7 @@ cirq/testing/test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
|
1050
1050
|
cirq/testing/test_data/test_module_missing_json_test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1051
1051
|
cirq/testing/test_data/test_module_missing_testspec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1052
1052
|
cirq/testing/test_data/test_module_missing_testspec/json_test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1053
|
-
cirq/transformers/__init__.py,sha256=
|
|
1053
|
+
cirq/transformers/__init__.py,sha256=B4ijV7PR4bN_QBswNqpAehIWTjXuaRMeyccrWz4Gw4w,7285
|
|
1054
1054
|
cirq/transformers/align.py,sha256=2uLjN5B4wNC661IGbwG5NKb-GSAW93pFCtPxuJkc6fs,3339
|
|
1055
1055
|
cirq/transformers/align_test.py,sha256=X4ysJuemqqOeKix2rO9SlwF4CBQzEYbgiqgZmlMxbsQ,7722
|
|
1056
1056
|
cirq/transformers/drop_empty_moments.py,sha256=uZJG9FpUNyA1Mi0xLDuVuhj_siZhPZ1_s08Ry9xQ-1M,1535
|
|
@@ -1071,8 +1071,8 @@ cirq/transformers/measurement_transformers.py,sha256=crAYKGK90drr_3GEh5t8-Z87eSE
|
|
|
1071
1071
|
cirq/transformers/measurement_transformers_test.py,sha256=mJKYFqqMwZnD8KXVM1tmF2kcIZXkkZKlfOU9XbGxYpQ,29019
|
|
1072
1072
|
cirq/transformers/merge_k_qubit_gates.py,sha256=v9vY3f52S9QR7D_Om4APSZ65rwJH6Z7g6Gf3pD_9H3I,4380
|
|
1073
1073
|
cirq/transformers/merge_k_qubit_gates_test.py,sha256=523FmfCC7mGX_zecGaQ2tgdqBvMGiMinwJMIfKBgG8E,14016
|
|
1074
|
-
cirq/transformers/merge_single_qubit_gates.py,sha256=
|
|
1075
|
-
cirq/transformers/merge_single_qubit_gates_test.py,sha256=
|
|
1074
|
+
cirq/transformers/merge_single_qubit_gates.py,sha256=jQsO2mTagm4nmLoD0rk-FP4un80D3RJtxBBgAVTyQYg,13664
|
|
1075
|
+
cirq/transformers/merge_single_qubit_gates_test.py,sha256=48U_X4fWZ3BZiFI14kZL6T9TPaHSwfVIPrQWnnTABl0,18076
|
|
1076
1076
|
cirq/transformers/noise_adding.py,sha256=ZBS-015Kc-BnoO-lMXfEGpCXbPu4whVgTXIB-E16ApQ,4476
|
|
1077
1077
|
cirq/transformers/noise_adding_test.py,sha256=nHOoKUPBBOkWF6A_JhIO6-G0AuFkLKBCxH7e2BOem9M,2171
|
|
1078
1078
|
cirq/transformers/optimize_for_target_gateset.py,sha256=QThizLtkzvZpUK-LG77ixuZXghDyWGNn6yHkNrzYR3o,7206
|
|
@@ -1220,8 +1220,8 @@ cirq/work/sampler.py,sha256=rxbMWvrhu3gfNSBjZKozw28lLKVvBAS_1EGyPdYe8Xg,19041
|
|
|
1220
1220
|
cirq/work/sampler_test.py,sha256=SsMrRvLDYELyOAWLKISjkdEfrBwLYWRsT6D8WrsLM3Q,13533
|
|
1221
1221
|
cirq/work/zeros_sampler.py,sha256=Fs2JWwq0n9zv7_G5Rm-9vPeHUag7uctcMOHg0JTkZpc,2371
|
|
1222
1222
|
cirq/work/zeros_sampler_test.py,sha256=lQLgQDGBLtfImryys2HzQ2jOSGxHgc7-koVBUhv8qYk,3345
|
|
1223
|
-
cirq_core-1.6.0.
|
|
1224
|
-
cirq_core-1.6.0.
|
|
1225
|
-
cirq_core-1.6.0.
|
|
1226
|
-
cirq_core-1.6.0.
|
|
1227
|
-
cirq_core-1.6.0.
|
|
1223
|
+
cirq_core-1.6.0.dev20250625011740.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
|
1224
|
+
cirq_core-1.6.0.dev20250625011740.dist-info/METADATA,sha256=_q1W3S0aAsqVZyyOY0-P7nQH4q_XAWi4lBx0luZmBqs,4857
|
|
1225
|
+
cirq_core-1.6.0.dev20250625011740.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
1226
|
+
cirq_core-1.6.0.dev20250625011740.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
|
|
1227
|
+
cirq_core-1.6.0.dev20250625011740.dist-info/RECORD,,
|
{cirq_core-1.6.0.dev20250624001344.dist-info → cirq_core-1.6.0.dev20250625011740.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|