I have two circuits that I believe are equivalent. When I say 'equivalent' I mean that they have equivalent unitary representations up to a global phase. How can one check this using Qiskit? How I would show equivalence isn't clear to me.
2 Answers
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
-
1$\begingroup$ 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. $\endgroup$ Sep 12, 2020 at 23:21
-
$\begingroup$ 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)
andcirc.rx(numpy.pi, 0)
and this solution fails due to numerical error (there is a $10^{-17}$ somewhere and a phase error) $\endgroup$ Sep 13, 2020 at 0:41 -
$\begingroup$ 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. $\endgroup$– lucianoSep 13, 2020 at 1:40 -
1$\begingroup$ 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. $\endgroup$ Sep 13, 2020 at 6:10
-
1$\begingroup$ 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. $\endgroup$– Gadi ASep 13, 2020 at 6:26
A simpler method is to use equiv
method directly from the Operator
class. Basically convert both the circuits to operators and then use equiv
. You can check out the documentation for the Operator class here.
The basic syntax would be something like,
from qiskit import *
from qiskit.quantum_info import Operator
Op1 = Operator(qc1)
Op2 = Operator(qc2)
Op1.equiv(Op2)
Where qc1 and qc2 are your two quantum circuits.
-
$\begingroup$ simple and straight to the point! good answer. $\endgroup$ May 11, 2022 at 20:42