Skip to content

Commit 7cf4cff

Browse files
babacryBichengYing
authored andcommitted
Update dd with faster circuit construction (quantumlib#7431)
Context: Constructing circuit using Circuit.from_moment instead of passing all the moments to Circuit() can improve the construction performance of Circuit as being suggested by NoureldinYosri@. Also did some minor improvements of imports.
1 parent 73de90e commit 7cf4cff

File tree

1 file changed

+15
-20
lines changed

1 file changed

+15
-20
lines changed

cirq-core/cirq/transformers/dynamical_decoupling.py

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323
import numpy as np
2424

25-
from cirq import circuits, ops, protocols
25+
from cirq import ops, protocols
26+
from cirq.circuits import Circuit, FrozenCircuit, Moment
2627
from cirq.protocols import unitary_protocol
2728
from cirq.protocols.has_stabilizer_effect_protocol import has_stabilizer_effect
2829
from cirq.protocols.has_unitary_protocol import has_unitary
@@ -113,17 +114,15 @@ def _is_single_qubit_operation(operation: ops.Operation) -> bool:
113114
return len(operation.qubits) == 1
114115

115116

116-
def _is_single_qubit_gate_moment(moment: circuits.Moment) -> bool:
117+
def _is_single_qubit_gate_moment(moment: Moment) -> bool:
117118
return all(_is_single_qubit_operation(op) for op in moment)
118119

119120

120121
def _is_clifford_op(op: ops.Operation) -> bool:
121122
return has_unitary(op) and has_stabilizer_effect(op)
122123

123124

124-
def _calc_busy_moment_range_of_each_qubit(
125-
circuit: circuits.FrozenCircuit,
126-
) -> dict[ops.Qid, list[int]]:
125+
def _calc_busy_moment_range_of_each_qubit(circuit: FrozenCircuit) -> dict[ops.Qid, list[int]]:
127126
busy_moment_range_by_qubit: dict[ops.Qid, list[int]] = {
128127
q: [len(circuit), -1] for q in circuit.all_qubits()
129128
}
@@ -134,7 +133,7 @@ def _calc_busy_moment_range_of_each_qubit(
134133
return busy_moment_range_by_qubit
135134

136135

137-
def _is_insertable_moment(moment: circuits.Moment, single_qubit_gate_moments_only: bool) -> bool:
136+
def _is_insertable_moment(moment: Moment, single_qubit_gate_moments_only: bool) -> bool:
138137
return not single_qubit_gate_moments_only or _is_single_qubit_gate_moment(moment)
139138

140139

@@ -150,9 +149,7 @@ def _merge_single_qubit_ops_to_phxz(
150149
return gate.on(q)
151150

152151

153-
def _try_merge_single_qubit_ops_of_two_moments(
154-
m1: circuits.Moment, m2: circuits.Moment
155-
) -> tuple[circuits.Moment, ...]:
152+
def _try_merge_single_qubit_ops_of_two_moments(m1: Moment, m2: Moment) -> tuple[Moment, ...]:
156153
"""Merge single qubit ops of 2 moments if possible, returns 2 moments otherwise."""
157154
for q in m1.qubits & m2.qubits:
158155
op1 = m1.operation_at(q)
@@ -169,12 +166,10 @@ def _try_merge_single_qubit_ops_of_two_moments(
169166
# ops_on_q may contain 1 op or 2 ops.
170167
ops_on_q = [op for op in [m.operation_at(q) for m in [m1, m2]] if op is not None]
171168
merged_ops.add(_merge_single_qubit_ops_to_phxz(q, tuple(ops_on_q)))
172-
return (circuits.Moment(merged_ops),)
169+
return (Moment(merged_ops),)
173170

174171

175-
def _calc_pulled_through(
176-
moment: circuits.Moment, input_pauli_ops: ops.PauliString
177-
) -> ops.PauliString:
172+
def _calc_pulled_through(moment: Moment, input_pauli_ops: ops.PauliString) -> ops.PauliString:
178173
"""Calculates the pulled_through such that circuit(input_pauli_ops, moment.clifford_ops) is
179174
equivalent to circuit(moment.clifford_ops, pulled_through).
180175
"""
@@ -184,7 +179,7 @@ def _calc_pulled_through(
184179
return input_pauli_ops.after(clifford_ops_in_moment)
185180

186181

187-
def _get_stop_qubits(moment: circuits.Moment) -> set[ops.Qid]:
182+
def _get_stop_qubits(moment: Moment) -> set[ops.Qid]:
188183
stop_pulling_through_qubits: set[ops.Qid] = set()
189184
for op in moment:
190185
if (not _is_clifford_op(op) and not _is_single_qubit_operation(op)) or not has_unitary(
@@ -233,7 +228,7 @@ def add_dynamical_decoupling(
233228
busy_moment_range_by_qubit = _calc_busy_moment_range_of_each_qubit(orig_circuit)
234229

235230
# Stores all the moments of the output circuit chronologically.
236-
transformed_moments: list[circuits.Moment] = []
231+
transformed_moments: list[Moment] = []
237232
# A PauliString stores the result of 'pulling' Pauli gates past each operations
238233
# right before the current moment.
239234
pulled_through: ops.PauliString = ops.PauliString()
@@ -277,7 +272,7 @@ def _update_pulled_through(q: ops.Qid, insert_gate: ops.Gate) -> ops.Operation:
277272
# Need to insert a new moment before current moment
278273
if new_moment_ops:
279274
moments_to_be_appended = _try_merge_single_qubit_ops_of_two_moments(
280-
transformed_moments[-1], circuits.Moment(new_moment_ops)
275+
transformed_moments[-1], Moment(new_moment_ops)
281276
)
282277
if len(moments_to_be_appended) == 1:
283278
transformed_moments.pop()
@@ -291,7 +286,7 @@ def _update_pulled_through(q: ops.Qid, insert_gate: ops.Gate) -> ops.Operation:
291286
):
292287
new_moment_ops.append(_update_pulled_through(q, next(dd_iter_by_qubits[q])))
293288
moments_to_be_appended = _try_merge_single_qubit_ops_of_two_moments(
294-
transformed_moments.pop(), circuits.Moment(new_moment_ops)
289+
transformed_moments.pop(), Moment(new_moment_ops)
295290
)
296291
transformed_moments.extend(moments_to_be_appended)
297292

@@ -325,7 +320,7 @@ def _update_pulled_through(q: ops.Qid, insert_gate: ops.Gate) -> ops.Operation:
325320
updated_moment_ops.add(updated_op)
326321

327322
if updated_moment_ops:
328-
updated_moment = circuits.Moment(updated_moment_ops)
323+
updated_moment = Moment(updated_moment_ops)
329324
transformed_moments.append(updated_moment)
330325

331326
# Step 3, update pulled through.
@@ -339,8 +334,8 @@ def _update_pulled_through(q: ops.Qid, insert_gate: ops.Gate) -> ops.Operation:
339334
if ending_moment_ops:
340335
transformed_moments.extend(
341336
_try_merge_single_qubit_ops_of_two_moments(
342-
transformed_moments.pop(), circuits.Moment(ending_moment_ops)
337+
transformed_moments.pop(), Moment(ending_moment_ops)
343338
)
344339
)
345340

346-
return circuits.Circuit(transformed_moments)
341+
return Circuit.from_moments(*transformed_moments)

0 commit comments

Comments
 (0)