Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass to remove diagonal gates before measurement #2208

Merged
merged 25 commits into from
Apr 27, 2019

Conversation

1ucian0
Copy link
Member

@1ucian0 1ucian0 commented Apr 26, 2019

This pass removes gates RZ and Z before measurement.

@jaygambetta
Copy link
Member

why not T, S Tdg, Sdg, U1 etc. Can we make this remove diagonal gates.

@1ucian0 1ucian0 changed the title Pass to remove RZ and Z before measurement Pass to remove diagonal gates before measurement Apr 26, 2019
@1ucian0
Copy link
Member Author

1ucian0 commented Apr 26, 2019

T, S Tdg, Sdg and U1 added (and pass renamed). Is there any other diagonal gate?

@jaygambetta
Copy link
Member

We could also remove control Z if the measurement is on both the qubits.

@1ucian0
Copy link
Member Author

1ucian0 commented Apr 26, 2019

Updated to include CzGate. Are CrzGate and Cu1Gate animals of the same species?

@chriseclectic
Copy link
Member

Yes, and also RZZGate.

@1ucian0
Copy link
Member Author

1ucian0 commented Apr 26, 2019

CrzGate, Cu1Gate, and RZZGate added!

jaygambetta
jaygambetta previously approved these changes Apr 26, 2019
@ajavadia
Copy link
Member

Consider this example:

from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister
from qiskit.transpiler import PassManager, transpile
from qiskit.transpiler.passes import RemoveDiagonalGatesBeforeMeasure, DAGFixedPoint

qr = QuantumRegister(2, 'qr')
cr = ClassicalRegister(1, 'cr')
circuit = QuantumCircuit(qr, cr)
circuit.rz(0.1, qr[1]).c_if(cr, 1)
circuit.barrier()
circuit.h(qr[0])
circuit.measure(qr[0], cr[0])

pm = PassManager()
pm.append(RemoveDiagonalGatesBeforeMeasure())
new_circuit = pm.run(circuit)

Here, this circuit:

                     ░ ┌───┐┌─┐
qr_0: |0>────────────░─┤ H ├┤M├
         ┌─────────┐ ░ └───┘└╥┘
qr_1: |0>┤ Rz(0.1) ├─░───────╫─
         └─┬──┴──┬─┘ ░       ║ 
 cr_0: 0 ══╡ = 1 ╞═══════════╩═
           └─────┘             

gets transformed into:

          ░ ┌───┐┌─┐
qr_0: |0>─░─┤ H ├┤M├
          ░ └───┘└╥┘
qr_1: |0>─░───────╫─
          ░       ║ 
 cr_0: 0 ═════════╩═
                    

which is incorrect. The reason, as I explained above, is that the crz gate is a predecessor of the measure, so it gets picked up by your algorithm. However, it is not a qubit predecessor, thus it should be ignored.

@1ucian0
Copy link
Member Author

1ucian0 commented Apr 27, 2019

good catch about the classical predecessor situation!

@ajavadia
Copy link
Member

ajavadia commented Apr 27, 2019

Similarly when you check successors, you should only care about qubits. Consider this example:

from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister
from qiskit.transpiler import PassManager, transpile
from qiskit.transpiler.passes import RemoveDiagonalGatesBeforeMeasure, DAGFixedPoint

qr = QuantumRegister(3, 'qr')
cr = ClassicalRegister(2, 'cr')
circuit = QuantumCircuit(qr, cr)
circuit.crz(0.1, qr[0], qr[1]).c_if(cr, 1)
circuit.h(qr[2]).c_if(cr, 3)
circuit.measure(qr[0], cr[0])
circuit.measure(qr[1], cr[1])

pm = PassManager()
pm.append(RemoveDiagonalGatesBeforeMeasure())
new_circuit = pm.run(circuit)

This circuit:
image
Remains unchanged.

Note that the CRz gate can legitimately be removed, because it is followed immediately by measures.

The reason why it fails here is that the check for successors is showing the Ch gate as a successor -- but this is only due to the clbits.

@ajavadia
Copy link
Member

In general I think going with DAG.nodes_on_wire() might be a better option here to only check the qubit wires.

@1ucian0
Copy link
Member Author

1ucian0 commented Apr 27, 2019

Your second example can also be addressed with quantum_predecessors. I think is cleaner. Thoughts?

Copy link
Member

@ajavadia ajavadia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good now! the quantum predecessors do the trick.

@1ucian0 1ucian0 merged commit a85c741 into Qiskit:master Apr 27, 2019
@1ucian0 1ucian0 deleted the rz_and_z_optimization branch April 27, 2019 03:17
lia-approves pushed a commit to edasgupta/qiskit-terra that referenced this pull request Jul 30, 2019
* rz_and_z_optimization

* bug fixing and more testing

* changelog

* lint

* RemoveRZandZbeforeMeasure -> RemoveDiagonalGatesBeforeMeasure

* changelog

* invalid-name

* test

* diagonal_control_gates

* CrzGate, Cu1Gate, RZZGate

* lint

* from qiskit.compiler import transpile

* remove_diagonal_gates_before_measurere

* diagonal_control_gates -> diagonal_2q_gates

* quantum_predecessors

* use quantum_predecessors

* test_optimize_1rzz_2measure docstring

* lint
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants