-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Describe the issue
The [map_clean_and_borrowable_qubits] transformer in [qubit_management_transformers.py] does not support recursive mapping for nested CircuitOperations.
As documented in the code (line 81):
Since this is not implemented using the cirq transformers infrastructure, we currently do not support recursive mapping within sub-circuits and that is left as a future TODO.
While the transformer attaches a [qubit_map] to the outer CircuitOperation, it does not traverse into the underlying FrozenCircuit to replace CleanQubit or BorrowableQubit instances. This results in the inner circuit retaining abstract placeholder qubits, which can cause failures in downstream operations that expect physical qubits.
Expected behavior: The transformer should recursively process nested CircuitOperations and replace all CleanQubit/BorrowableQubit placeholders with actual qubits.
Actual behavior: The inner FrozenCircuit retains its original placeholder qubits; only a [qubit_map] is applied to the outer CircuitOperation.
Explain how to reproduce the bug or problem
import cirq
from cirq.transformers.qubit_management_transformers import map_clean_and_borrowable_qubits
# Create a sub-circuit containing a CleanQubit placeholder
clean_qubit = cirq.ops.CleanQubit(0)
sub_circuit = cirq.Circuit(cirq.X(clean_qubit))
# Wrap in a CircuitOperation (nested circuit)
main_circuit = cirq.Circuit(cirq.CircuitOperation(sub_circuit.freeze()))
print("Original circuit:")
print(main_circuit)
# Apply the transformer
result = map_clean_and_borrowable_qubits(main_circuit)
print("Transformed circuit:")
print(result)
# Verify: check if placeholder was replaced in the inner circuit
circuit_op = list(result.all_operations())[0]
inner_qubit = list(circuit_op.circuit.all_operations())[0].qubits[0]
print(f"Inner qubit: {inner_qubit!r}")
print(f"Inner qubit type: {type(inner_qubit).__name__}")Output:
Original circuit:
_c(0): ───[ _c(0): ───X─── ]───
Transformed circuit:
ancilla_0: ───[ _c(0): ───X─── ](qubit_map={_c(0): ancilla_0})───
Inner qubit: cirq.ops.CleanQubit(0)
Inner qubit type: CleanQubit
Tell us the version of Cirq where this happens
1.7.0.dev0