# Test equivalence of circuits exactly on qiskit

I have two circuits that I believe are equivalent. How can one check this on qiskit? Currently, I am executing both circuits and verifying that the counts are close (which they are) but I would like to be more precise. Here is my code where circ is the quantum circuit.

from qiskit import Aer, QuantumCircuit, execute
.
.
.

backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(circ, backend_sim, shots=1000)
result_sim = job_sim.result()
counts = result_sim.get_counts(circ)


Is there a cleaner way to do this e.g. compare the unitaries of the two circuits, and if yes how? Of course, they are only the same up to a global phase so how to show equivalence isn't clear to me.

As it is point out, depends on your notion of equivalence.

## State vectors

Two circuits are equivalent upto global phase if they represent the same state vector. Consider the following two circuits:

from qiskit import QuantumCircuit
import numpy as np

qc1 = QuantumCircuit(2)
qc1.h(0)
qc1.cx(0,1)

qc2 = QuantumCircuit(2)
qc2.u2(0, np.pi, 0)
qc2.cx(0,1)


It is possible to check if their state vector is the same with the Qiskit qiskit.quantum_info module:

from qiskit.quantum_info import Statevector
Statevector.from_instruction(qc1).equiv(Statevector.from_instruction(qc2)) # True


## Unitary matrices

If you need to consider global phase, in that case you need to compare their unitary matrices via simulation.

In the following case:

qc1 = QuantumCircuit(1)
qc1.x(0)

qc2 = QuantumCircuit(1)
qc2.rx(np.pi, 0)


These circuit has the same state vector, but not the same unitary:

Statevector.from_instruction(qc1).equiv(Statevector.from_instruction(qc2))  # True

backend_sim = Aer.get_backend('unitary_simulator')
job_sim = execute([qc1, qc2], backend_sim)
result_sim = job_sim.result()
unitary1 = result_sim.get_unitary(qc1)
unitary2 = result_sim.get_unitary(qc2)

np.allclose(unitary1, unitary2)  # False



## Counts

If your circuits have measurements, you probably want to consider these to circuits equivalent, since their measured results are equivalent.

qc1 = QuantumCircuit(2,2)
qc1.h(0)
qc1.measure(0,0)
qc1.measure(1,1)

qc2 = QuantumCircuit(2,2)
qc2.h(0)
qc2.swap(0,1)
qc2.measure(0,1)
qc2.measure(1,0)


In this case, you want to compare their result counts, considering some statistical error:

backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute([qc1, qc2], backend_sim, shots=1000)
result_sim = job_sim.result()
counts1 = result_sim.get_counts(qc1)
counts2 = result_sim.get_counts(qc2)
print(counts1, counts2)


## Up to Ancillas

You might want to consider these two circuits equivalent:

qc1 = QuantumCircuit(3)
qc1.x(0)

qc2 = QuantumCircuit(1)
qc2.rx(np.pi, 0)


It was suggested to invert one of them, compose them (wiring the ancillas) and check if it is the identity. For example:

from qiskit.quantum_info import Operator

composed = qc1.compose(qc2.inverse(), qubits=range(len(qc2.qubits)))
Operator(composed).equiv(Operator.from_label('I'*len(qc1.qubits))) # True

• Actually the statevector is not enough. You need to show the unitaries corresponding to the circuits are the same. This check must take into account That there could be a global phase difference that may or may not matter depending on if you are later going to control the circuit. if the circuits are the same up to swap mapping then you need to check for equivalence up to a one sided permutation. If the qubit orderings are different than there is also a row and column permutation to deal with. In the case above one can simply use the definition of unitary to verify equiv up to phase. – Paul Nation Sep 12 '20 at 23:21
• Generally, the statevector is not the same because there is a global phase. For example, I tried using a circuit with only 1 qubit. Let the circuit be obtained through circ.x(0) and circ.rx(numpy.pi, 0) and this solution fails due to numerical error (there is a $10^{-17}$ somewhere and a phase error) – Jason Fring Sep 13 '20 at 0:41
• I updated the answer with unitary matrices and one example considering swap. @JasonFring, if you want to add tolerance for floating point errors when checking for equivalence, equiv allows you to set relative (rtol) and absolute (atol) tolerance values for comparison. – luciano Sep 13 '20 at 1:40
• A couple of comments: 1) You may want to compute the unitary of the first circuit concatenated with the inverse of the second circuit, and check if it's the identity. Simiarly can also be done for the state vector. 2) There is a notion of equivalent circuits with a different number of qubits (for example because of ancilla qubits), which may make this somewhat more complex. – Yael Ben-Haim Sep 13 '20 at 6:10
• Also note that there's a difference between comparing the unitary and comparing the single outcome on the |0> state - the former verifies the circuits produce the same outcome for every input, not just |0>, which is similar to our usual notions of "equivalance"; but if you only want output on |0> unitary is overkill in terms of runtime and you can deduce the phase difference from two nonzero entries in the statevectors. – Gadi A Sep 13 '20 at 6:26