Yes, they should be.
You can check their statevector to confirm that they indeed generate the same state. First, you can generate some arbitrary initial state and use the following two methods to show that they generate the same statevector. For instance:
init_circ = QuantumCircuit(3)
init_circ.ry(2.5,0)
init_circ.ry(1.2, 1)
init_circ.ry(0.5, 2)
print(init_circ)
┌─────────┐
q_0: ┤ RY(2.5) ├
├─────────┤
q_1: ┤ RY(1.2) ├
├─────────┤
q_2: ┤ RY(0.5) ├
└─────────┘
my_circ = QuantumCircuit(3)
my_circ.cx(0,1)
my_circ.rz(np.pi,1)
my_circ.cx(0,1)
my_circ.cx(1,2)
my_circ.rz(np.pi,2)
my_circ.cx(1,2)
print(my_circ)
q_0: ──■─────────────■─────────────────────
┌─┴─┐┌───────┐┌─┴─┐
q_1: ┤ X ├┤ RZ(π) ├┤ X ├──■─────────────■──
└───┘└───────┘└───┘┌─┴─┐┌───────┐┌─┴─┐
q_2: ───────────────────┤ X ├┤ RZ(π) ├┤ X ├
└───┘└───────┘└───┘
xs_gate = my_circ.to_gate()
cxs_gate = xs_gate.control()
circuit = QuantumCircuit(4)
circuit.append(init_circ, [1,2,3])
circuit.append(cxs_gate, [0,1,2,3])
print(circuit)
q_0: ───────────────────────■────────
┌──────────────┐┌──────┴───────┐
q_1: ┤0 ├┤0 ├
│ ││ │
q_2: ┤1 circuit-155 ├┤1 circuit-156 ├
│ ││ │
q_3: ┤2 ├┤2 ├
└──────────────┘└──────────────┘
from qiskit.quantum_info import Statevector
circuit_statevector = Statevector(circuit)
print(circuit_statevector )
Statevector([0.25215633+0.j, 0. +0.j, 0.75888206+0.j,
0. +0.j, 0.17250943+0.j, 0. +0.j,
0.51917915+0.j, 0. +0.j, 0.06438608+0.j,
0. +0.j, 0.1937744 +0.j, 0. +0.j,
0.04404889+0.j, 0. +0.j, 0.1325682 +0.j,
0. +0.j],
dims=(2, 2, 2, 2))
Note: I added a layer of some arbitrary $RY$ rotations at the beginning just so that we don't start at the $|0\rangle$ state.
And for the other circuit you have:
qcz = QuantumCircuit(4)
qcz.ry(2.5,1)
qcz.ry(1.2, 2)
qcz.ry(0.5, 3)
qcz.cx(1,2)
qcz.crz(np.pi,0,2)
qcz.cx(1,2)
qcz.cx(2,3)
qcz.crz(np.pi,0,3)
qcz.cx(2,3)
print(qcz)
q_0: ────────────────────■──────────────────■─────────
┌─────────┐ │ │
q_1: ┤ RY(2.5) ├──■──────┼──────■───────────┼─────────
├─────────┤┌─┴─┐┌───┴───┐┌─┴─┐ │
q_2: ┤ RY(1.2) ├┤ X ├┤ RZ(π) ├┤ X ├──■──────┼──────■──
├─────────┤└───┘└───────┘└───┘┌─┴─┐┌───┴───┐┌─┴─┐
q_3: ┤ RY(0.5) ├───────────────────┤ X ├┤ RZ(π) ├┤ X ├
└─────────┘ └───┘└───────┘└───┘
qcz_statevector = Statevector(qcz)
print(qcz_statevector )
Statevector([0.25215633+0.j, 0. +0.j, 0.75888206+0.j,
0. +0.j, 0.17250943+0.j, 0. +0.j,
0.51917915+0.j, 0. +0.j, 0.06438608+0.j,
0. +0.j, 0.1937744 +0.j, 0. +0.j,
0.04404889+0.j, 0. +0.j, 0.1325682 +0.j,
0. +0.j],
dims=(2, 2, 2, 2))
Notice how the two statevectors are the same. This is because the two circuits are equivalent.
Update:
I didn't think much when I answered this, and knew that the two circuits were equivalent to start so I just tested it out using the method above. Which is kinda convoluted. The other answer used Operator
from quantum_info
to show that the two operators are indeed equivalent is much better as it show they are two equivalent unitary matrix. There is a another method to do this, and I will provide it below:
qcz = QuantumCircuit(4)
qcz.cx(1,2)
qcz.crz(np.pi,0,2)
qcz.cx(1,2)
qcz.cx(2,3)
qcz.crz(np.pi,0,3)
qcz.cx(2,3)
backend = Aer.get_backend('unitary_simulator')
job = execute(qcz, backend)
result = job.result()
qcz_unitary = result.get_unitary(qcz, decimals=3)
my_circ = QuantumCircuit(3)
my_circ.cx(0,1)
my_circ.rz(np.pi,1)
my_circ.cx(0,1)
my_circ.cx(1,2)
my_circ.rz(np.pi,2)
my_circ.cx(1,2)
xs_gate = my_circ.to_gate()
cxs_gate = xs_gate.control()
circuit = QuantumCircuit(4)
circuit.append(cxs_gate, [0,1,2,3])
backend = Aer.get_backend('unitary_simulator')
job = execute(circuit, backend)
result = job.result()
circuit_unitary = result.get_unitary(circuit, decimals=3)
Now you can check that the two operators, qcz_unitary
and circuit_unitary
, represent the two circuits are equivalent.
Also note that these two circuits are equivalent fundamentally as pointed out by DaftWullie in this answer. Here, we are just checking to make sure what being implemented in Qiskit is correct.