# How do I get the Unitary matrix of this circuit without using 'unitary_simulator'? [duplicate]

I am using jupyter notebook and qiskit. I have a simple quantum circuit and I want to know how to get the unitary matrix of the circuit without using 'get_unitary' from the Aer unitary_simulator. i.e.: By just using matrix manipulation, how do I get the unitary matrix of the circuit below by just using numpy and normal matrix properties? I have figured out how to get the unitary matrix of the circuit below: By using this code:

import numpy as np

swapcnot = np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]])
cnot = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])

layer1 = np.kron(np.eye(2),swapcnot)

layer2 = np.kron(swapcnot, np.eye(2))

print(layer2@layer1)


However when I try to add another qubit and another cnot gate, I do not get the correct result

# The result I should be getting: The 4 qubit case goes as follows:

swapcnot = np.array([[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0]])
id = np.eye(2)
op1 = np.kron(np.kron(swapcnot, id), id)
op2 = np.kron(np.kron(id, swapcnot), id)
op3 = np.kron(np.kron(id, id), swapcnot)
op1@op2@op3
# output:
array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])


I guess you will figure out the general case base on the above snippet. Just keep in mind that Kronecker product (or more generally tensor product) is associative, thus the place where you put np.kron does not matter.

First, realized that your circuit can be divided into 3 stages as follow: The first state, $$U1$$, can be written in term of tensor product as $$U1 = CNOT \otimes I \otimes I$$

The second state, $$U2$$, can be written as $$U2 = I \otimes CNOT \otimes I$$

The third state, $$U3$$, can be written as $$U3 = I \otimes I \otimes CNOT$$

Your entire circuit then can be represented as a Unitary matrix $$U$$ where $$U = U3 \cdot U2 \cdot U1$$.