Skip to content

Commit 419233b

Browse files
Allow measurements and resets into Gemini noise model.
1 parent 58a91e2 commit 419233b

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

src/bloqade/cirq_utils/noise/model.py

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def validate_moments(moments: Iterable[cirq.Moment]):
106106
continue
107107

108108
gate = operation.gate
109-
for allowed_family in allowed_target_gates:
109+
for allowed_family in set(allowed_target_gates).union({cirq.GateFamily(gate=cirq.ops.common_channels.ResetChannel, ignore_global_phase=True)}):
110110
if gate in allowed_family:
111111
break
112112
else:
@@ -246,14 +246,18 @@ def noisy_moment(self, moment, system_qubits):
246246
original_moment = moment
247247

248248
# Check if the moment is empty
249-
if len(moment.operations) == 0:
249+
if len(moment.operations) == 0 or cirq.is_measurement(moment.operations[0]):
250250
move_noise_ops = []
251251
gate_noise_ops = []
252252
# Check if the moment contains 1-qubit gates or 2-qubit gates
253253
elif len(moment.operations[0].qubits) == 1:
254-
gate_noise_ops, move_noise_ops = self._single_qubit_moment_noise_ops(
255-
moment, system_qubits
256-
)
254+
if (isinstance(moment.operations[0].gate, cirq.ResetChannel)) or (cirq.is_measurement(moment.operations[0])):
255+
move_noise_ops = []
256+
gate_noise_ops = []
257+
else:
258+
gate_noise_ops, move_noise_ops = self._single_qubit_moment_noise_ops(
259+
moment, system_qubits
260+
)
257261
elif len(moment.operations[0].qubits) == 2:
258262
control_qubits = [op.qubits[0] for op in moment.operations]
259263
target_qubits = [op.qubits[1] for op in moment.operations]
@@ -319,20 +323,26 @@ def noisy_moments(
319323

320324
# Split into moments with only 1Q and 2Q gates
321325
moments_1q = [
322-
cirq.Moment([op for op in moment.operations if len(op.qubits) == 1])
326+
cirq.Moment([op for op in moment.operations if (len(op.qubits) == 1) and (not cirq.is_measurement(op)) and (not isinstance(op.gate, cirq.ResetChannel))])
323327
for moment in moments
324328
]
325329
moments_2q = [
326-
cirq.Moment([op for op in moment.operations if len(op.qubits) == 2])
330+
cirq.Moment([op for op in moment.operations if (len(op.qubits) == 2) and (not cirq.is_measurement(op))])
327331
for moment in moments
328332
]
329333

330-
assert len(moments_1q) == len(moments_2q)
334+
moments_measurement = [
335+
cirq.Moment([op for op in moment.operations if (cirq.is_measurement(op)) or (isinstance(op.gate, cirq.ResetChannel))])
336+
for moment in moments
337+
]
338+
339+
assert len(moments_1q) == len(moments_2q) == len(moments_measurement)
331340

332341
interleaved_moments = []
333342
for idx, moment in enumerate(moments_1q):
334343
interleaved_moments.append(moment)
335344
interleaved_moments.append(moments_2q[idx])
345+
interleaved_moments.append(moments_measurement[idx])
336346

337347
interleaved_circuit = cirq.Circuit.from_moments(*interleaved_moments)
338348

@@ -368,14 +378,17 @@ def noisy_moment(self, moment, system_qubits):
368378
"all qubits in the circuit must be defined as cirq.GridQubit objects."
369379
)
370380
# Check if the moment is empty
371-
if len(moment.operations) == 0:
381+
if len(moment.operations) == 0 or cirq.is_measurement(moment.operations[0]):
372382
move_moments = []
373383
gate_noise_ops = []
374384
# Check if the moment contains 1-qubit gates or 2-qubit gates
375385
elif len(moment.operations[0].qubits) == 1:
376-
gate_noise_ops, _ = self._single_qubit_moment_noise_ops(
377-
moment, system_qubits
378-
)
386+
if (isinstance(moment.operations[0].gate, cirq.ResetChannel)) or (cirq.is_measurement(moment.operations[0])):
387+
gate_noise_ops = []
388+
else:
389+
gate_noise_ops, _ = self._single_qubit_moment_noise_ops(
390+
moment, system_qubits
391+
)
379392
move_moments = []
380393
elif len(moment.operations[0].qubits) == 2:
381394
cg = OneZoneConflictGraph(moment)

0 commit comments

Comments
 (0)