Skip to content

Commit 11ae0bd

Browse files
author
Shef
authored
Make RouteCQC errorout on intermediate measurements on 3+ qubits (#6307)
1 parent aa312bc commit 11ae0bd

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

Diff for: cirq-core/cirq/transformers/routing/route_circuit_cqc.py

+16-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"""Heuristic qubit routing algorithm based on arxiv:1902.08091."""
1616

1717
from typing import Any, Dict, List, Optional, Set, Sequence, Tuple, TYPE_CHECKING
18-
from itertools import combinations
18+
import itertools
1919
import networkx as nx
2020

2121
from cirq import circuits, ops, protocols
@@ -48,7 +48,9 @@ def _disjoint_nc2_combinations(
4848
Returns:
4949
All 2-combinations between qubit pairs that are disjoint.
5050
"""
51-
return [pair for pair in combinations(qubit_pairs, 2) if set(pair[0]).isdisjoint(pair[1])]
51+
return [
52+
pair for pair in itertools.combinations(qubit_pairs, 2) if set(pair[0]).isdisjoint(pair[1])
53+
]
5254

5355

5456
@transformer_api.transformer
@@ -245,17 +247,28 @@ def _get_one_and_two_qubit_ops_as_timesteps(
245247
The i'th entry in the nested two-qubit and single-qubit ops correspond to the two-qubit
246248
gates and single-qubit gates of the i'th timesteps respectively. When constructing the
247249
output routed circuit, single-qubit operations are inserted before two-qubit operations.
250+
251+
Raises:
252+
ValueError: if circuit has intermediate measurement op's that act on 3 or more qubits.
248253
"""
249254
two_qubit_circuit = circuits.Circuit()
250255
single_qubit_ops: List[List[cirq.Operation]] = []
256+
257+
if any(
258+
protocols.num_qubits(op) > 2 and protocols.is_measurement(op)
259+
for op in itertools.chain(*circuit.moments[:-1])
260+
):
261+
# There is at least one non-terminal measurement on 3+ qubits
262+
raise ValueError('Non-terminal measurements on three or more qubits are not supported')
263+
251264
for moment in circuit:
252265
for op in moment:
253266
timestep = two_qubit_circuit.earliest_available_moment(op)
254267
single_qubit_ops.extend([] for _ in range(timestep + 1 - len(single_qubit_ops)))
255268
two_qubit_circuit.append(
256269
circuits.Moment() for _ in range(timestep + 1 - len(two_qubit_circuit))
257270
)
258-
if protocols.num_qubits(op) == 2 and not protocols.is_measurement(op):
271+
if protocols.num_qubits(op) == 2:
259272
two_qubit_circuit[timestep] = two_qubit_circuit[timestep].with_operation(op)
260273
else:
261274
single_qubit_ops[timestep].append(op)

Diff for: cirq-core/cirq/transformers/routing/route_circuit_cqc_test.py

+32
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,38 @@ def test_circuit_with_measurement_gates():
107107
cirq.testing.assert_same_circuits(routed_circuit, circuit)
108108

109109

110+
def test_circuit_with_valid_intermediate_multi_qubit_measurement_gates():
111+
device = cirq.testing.construct_ring_device(3)
112+
device_graph = device.metadata.nx_graph
113+
router = cirq.RouteCQC(device_graph)
114+
q = cirq.LineQubit.range(2)
115+
hard_coded_mapper = cirq.HardCodedInitialMapper({q[i]: q[i] for i in range(2)})
116+
117+
valid_circuit = cirq.Circuit(cirq.measure_each(*q), cirq.H.on_each(q))
118+
119+
c_routed = router(
120+
valid_circuit, initial_mapper=hard_coded_mapper, context=cirq.TransformerContext(deep=True)
121+
)
122+
device.validate_circuit(c_routed)
123+
124+
125+
def test_circuit_with_invalid_intermediate_multi_qubit_measurement_gates():
126+
device = cirq.testing.construct_ring_device(3)
127+
device_graph = device.metadata.nx_graph
128+
router = cirq.RouteCQC(device_graph)
129+
q = cirq.LineQubit.range(3)
130+
hard_coded_mapper = cirq.HardCodedInitialMapper({q[i]: q[i] for i in range(3)})
131+
132+
invalid_circuit = cirq.Circuit(cirq.MeasurementGate(3).on(*q), cirq.H.on_each(*q))
133+
134+
with pytest.raises(ValueError):
135+
_ = router(
136+
invalid_circuit,
137+
initial_mapper=hard_coded_mapper,
138+
context=cirq.TransformerContext(deep=True),
139+
)
140+
141+
110142
def test_circuit_with_non_unitary_and_global_phase():
111143
device = cirq.testing.construct_ring_device(4)
112144
device_graph = device.metadata.nx_graph

0 commit comments

Comments
 (0)