# Qiskit - order of swap gates

It seems I don't understand what swap gates actually do. The following code:

import qiskit
import numpy as np
from qiskit.quantum_info.operators import Operator

circuit = qiskit.QuantumCircuit(3)
circuit.swap(0, 1)
circuit.swap(1, 2)
display(circuit.draw(output='mpl'))
display(Operator(circuit).data)
print({x: y for (x, y) in zip(*np.nonzero(Operator(circuit).data))})


outputs ... {0: 0, 1: 2, 2: 4, 3: 6, 4: 1, 5: 3, 6: 5, 7: 7}, meaning that the circuit maps 0 to 0, 1 to 2, 2 to 4, etc.

Some of these outputs are not what I expect. For example, I expected 1=001 ----swap(0,1)---> 010 ---swap(1,2)---> 100 = 4, not 2.

What do I misunderstand? Some of my experiments seem to indicate that the swaps happen in the reverse order. Another crazy explanation I have is that swap swaps not the values on the wires, but the wires themselves. But there is nothing like this in the documentation.

Each gate independently (i.e. only swap(0, 1) or only swap(1, 2)) behaves as I expect, so there is no chance that I confused the order of bits (i.e. big-endian vs little-endian).

Is my usage of Operator wrong? Again, don't see anything about it in documentation.

I'm starting to question my sanity, so any help is appreciated.

• It depends which qubit is zero. The leftmost or the rightmost? Your expectation means that zero qubit is the rightmost, while the results correspond to zero qubit to be the leftmost. So, this is problem of big-endian vs little-endian. Commented Apr 25, 2023 at 6:22

You're correct in your expectations: qiskit's little-endian will indeed send $$|001\rangle$$ to $$|100\rangle$$ with your circuit. In fact, this is shown when you display Operator(circuit).data, which gives the following matrix: $$\begin{pmatrix} 1&0&0&0&0&0&0&0\\ 0&0&1&0&0&0&0&0\\ 0&0&0&0&1&0&0&0\\ 0&0&0&0&0&0&1&0\\ 0&1&0&0&0&0&0&0\\ 0&0&0&1&0&0&0&0\\ 0&0&0&0&0&1&0&0\\ 0&0&0&0&0&0&0&1 \end{pmatrix}$$ The output you get when inputting $$|001\rangle$$ into this circuit is given by reading the second column of this matrix, which gives $$|100\rangle$$. However, np.nonzero will return (x, y) couples such that the x-th row and y-th column has a non-zero coefficient. Thus, you're essentially reading the transpose of your circuit by doing this. If you replace your last line by:

print({y: x for (x, y) in zip(*np.nonzero(Operator(circuit).data))})


You obtain {0: 0, 2: 1, 4: 2, 6: 3, 1: 4, 3: 5, 5: 6, 7: 7}, which was what you expected to get. You can also do this if you want the output to be sorted according to the keys:

print(dict(sorted({y: x for (x, y) in zip(*np.nonzero(Operator(circuit).data))}.items())))


Using which you will obtain {0: 0, 1: 4, 2: 1, 3: 5, 4: 2, 5: 6, 6: 3, 7: 7}.

• Thanks, looks like I forgot linear algebra. Commented Apr 25, 2023 at 12:55