Representing multiqubit states with matrices. A cheat sheet Loosely uses Mathematica syntax. version 1.0 polprog.net The Bloch sphere of qubit states looks like this: |0> |-> z^ / | / |/ y |-i> --------/------> |i> /| x./ | '' | |+> |1> A single qubit is represented by a 2 element vector |a> = a0 * |0> + a1 * |1> where |0> = {1, 0} and |1> = {0, 1} Representing two- and more-qubit states is more complicated. We have a 2n element vector representing all possible states. Representing 2-qubit states in |0>,|1> basis |aa> = a00*|00> + a01*|01> + a10*|10> + a11*|11> = {a00, a01, a10, a11} So, state |00> = {1, 0, 0, 0} |01> = {0, 1, 0, 0} |10> = {0, 0, 1, 0} |11> = {0, 0, 0, 1} state with a 1/2 probability of |00> and |10> = 1/Sqrt[2] * {1, 0, 1, 0} The hadamard gate converts between 0/1 and +/- basis. State |+> = 1/Sqrt[2] * {1, 1} |-> = 1/Sqrt[2] * {1, -1} A single qubit gate is represented by a 2x2 matrix. Copy-paste for Mathematica notebooks: II = IdentityMatrix[2]; X = PauliMatrix[1]; Y = PauliMatrix[2]; Z = PauliMatrix[3]; H = 1/Sqrt[2] * {{1, 1}, {1, -1}}; CNOT = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}, {0, 0, 1, 0}}; CPHASE = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, -1}}; SWAP = {{1, 0, 0, 0}, {0, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}}; (Mathematica already defines I as the imaginary number j, so the identity matrix is II) Here's a 1-qubit circuit with a Hadamard gate ---[H]--- We can simulate it by feeding it one state. This is simply done by the dot product {0, 1}.H = 1/Sqrt[2] * {1, 1} == |+> {1, 0}.H = 1/Sqrt[2] * {1, -1} == |-> We fed the states |0> and |1> to the Hadamard gate and got the |+> and |-> states as a result. .-----------------------------------------------. Representing multiqubit circuits with matrices '-----------------------------------------------' Multiqubit circuits are represented by the Kronecker product of the gate matrices. Lack of a gate is equivalent to the identity matrix ---[X]--- --------- This circuit applies a pauli-X to the top qubit. We can express it as KroneckerProduct[X, IdentityMatrix[2]] This will flip the value of the top qubit in the 0/1 basis. So for |00> we get |10> and so on. |11> = {0, 0, 0, 1} {0, 0, 0, 1}.KroneckerProduct[X, IdentityMatrix[2]] = {0, 1, 0, 0} The state {0, 1, 0, 0} is |01>. It flipped the top qubit. .---------------------------. The +/- basis (the X basis) '---------------------------' |aa> = a00*|++> + a01*|+-> + a10*|-+> + a11*|--> We can get the +/- basis states from 0/1 basis states by applying a Hadamard on both qubits. ---[H]--- ---[H]--- This operation is represented by a 4x4 matrix of KroneckerProduct[H, H] The +/- states in 0/1 basis are as follows. 1/2 constant is for normalization |++> = 1/2 * { 1, 1, 1, 1} |+-> = 1/2 * { 1, -1, 1, -1} |-+> = 1/2 * { 1, 1, -1, -1} |--> = 1/2 * { 1, -1, -1, 1} Let's make an example with this circuit which will flip the top bit's state, so for |++> i want a |-+>. The gate which flips the states in +/- basis is the pauli-Y gate. The circuit looks like this ---[Y]--- --------- 1/2 * {1, 1, 1, 1}.KroneckerProduct[Y, I] = {i/2, i/2, -i/2, -i/2} Which, ignoring the phase, is the same as 1/2 * {1, 1, -1, -1} = |-+>. The circuit indeed flipped the top qubit. More complicated circuits are simply represented by subsequent matrices. Suppose we want to make a CNOT gate with the top qubit as the target That gate would flip the top state only if the bottom state is 1. In Out -------- |00> |00> |01> |11> |10> |10> |11> |01> It can be implemented like this ---[H]---#---[H]--- -#- represents a CNOT with the bottom qubit | where | as the target and the top as the control ---[H]---+---[H]--- -+- qubit The matrix representation of this circuit is KroneckerProduct[H, H].CNOT.KroneckerProduct[H, H] where CNOT = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}, {0, 0, 1, 0}} Let's try the |00> state. It should not change it {1, 0, 0, 0}.KroneckerProduct[H, H].CNOT.KroneckerProduct[H, H] = {1, 0, 0, 0} While the |01> state should become |11> {0, 1, 0, 0}.KroneckerProduct[H, H].CNOT.KroneckerProduct[H, H] = {0, 0, 0, 1} This circuit respects the phase {0, I, 0, 0}.KroneckerProduct[H, H].CNOT.KroneckerProduct[H, H] = {0, 0, 0, I} A three qubit circuit can be represented by giving more matrices to KroneckerProduct, which can take more than 2 arguments. ---[X]--- ----#---- | ----O---- This circuit flips the top qubit and does a CNOT on the bottom two with the middle as the control For example state |010> will become |111> {0, 0, 1, 0, 0, 0, 0, 0}.KroneckerProduct[X, CNOT] = {0, 0, 0, 0, 0, 0, 0, 1} == |111> If you give KroneckerProduct a 2x2 matrix (X) and a 4x4 matrix (CNOT), it will work just like you expect. So a circuit which performs a pauli-X on the middle qubit, --------- ---[X]--- --------- Would be KroneckerProduct[II, X, II]. Let's put |010> in: {0, 0, 1, 0, 0, 0, 0, 0}.KroneckerProduct[II, X, II] = {1, 0, 0, 0, 0, 0, 0, 0} == |000> .-----------------. Distant CNOT gate '-----------------' We want to make a CNOT on a 3-qubit circuit which will have the top qubit as a control and the bottom as target, and leave the middle one unaltered. We know how a regular CNOT is represented in a matrix, and how SWAP works. Essentially we can SWAP the top two qubits, do a CNOT on the bottom two and SWAP the top two again, like this --X-----X-- ---#--- | | | --X--#--X-- == ------- | | -----O----- ---O--- How does that look like as a matrix? circ2 = KroneckerProduct[SWAP, IdentityMatrix[2]].KroneckerProduct[IdentityMatrix[2], CNOT].KroneckerProduct[SWAP, IdentityMatrix[2]] Enter state |100>, we want |101>: {0, 0, 0, 0, 1, 0, 0, 0}.circ2 = {0, 0, 0, 0, 0, 1, 0, 0} == |101> as we expected. Enter state |011>, we want |011>: {0, 0, 0, 1, 0, 0, 0, 0}.circ2 = {0, 0, 0, 1, 0, 0, 0, 0} No change. It works. And here's the matrix: circ2 // MatrixForm 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 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 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0