# Introduction to Circuits and Gates (02/12/2021)

# What is a qubit?

A qubit is a quantum mechanical system consisting of a two-level system, whose state can be written as,

∣Ψ⟩=α∣0⟩+β∣1⟩|\Psi\rangle=\alpha|0\rangle+\beta|1\rangle

where α\alpha​ and β\beta​ are the complex numbers, such that ∣α∣2+∣β∣2=1|\alpha|^2+|\beta|^2=1​.

Here, ∣0⟩=|0\rangle=\left [{\begin{array}{c} 1\\0 \end{array}}\right ]​, and ∣1⟩=|1\rangle=\left [{\begin{array}{c} 0\\1 \end{array}}\right ]​. It can be observed that a qubit can be in superposition of both ∣0⟩|0\rangle​ and ∣1⟩|1\rangle​ states. When a qubit is measured, the probabilities of getting ∣0⟩|0\rangle​ and ∣1⟩|1\rangle​ are ∣α∣2|\alpha|^2​, and ∣β∣2|\beta|^2​ respectively, when added the total probability gives 1.

On a Bloch sphere (a unit sphere with radius = 1), a qubit's state can be properly visualized, where it's state is written as,

∣Ψ⟩=cos(θ/2)∣0⟩+eiϕsin(θ/2)∣1⟩|\Psi\rangle=cos(\theta/2)|0\rangle+e^{i\phi}sin(\theta/2)|1\rangle​​

Here, θ\theta​ and ϕ\phi​ are the polar and azimuthal angles on the Bloch sphere, such that θ\theta​ varies from 0 to π\pi​ and ϕ\phi​ varies from 0 to 2π2\pi​. A unique value of {θ,ϕ}\{\theta,\phi\}​ponds to a particular point on the Bloch sphere, and  each point on the Bloch sphere represents a unique quantum state.

## Measuring a qubit

On the Bloch sphere, there are different axes along which the qubits are measured, they were X, Y and Z axes. Correspndingly, X-basis, Y-basis and Z-basis states are written as {∣+⟩,∣−⟩}\{|+\rangle,|-\rangle\}​, {∣l⟩,∣r⟩}\{|l\rangle,|r\rangle\}​, and {∣0⟩,∣1⟩}\{|0\rangle,|1\rangle\}​ respectively. If the qubits are measured along X-axis, then either ∣+⟩|+\rangle​ or ∣−⟩|-\rangle​ results. If the qubits are measured along Y-axis, then either ∣l⟩|l\rangle​ or ∣r⟩|r\rangle​ results, similarly if the qubits are measured along Z-axis, either ∣0⟩|0\rangle​ or ∣1⟩|1\rangle​ results. It is to be noted that, ∣l⟩=∣0⟩+i∣1⟩2|l\rangle=\frac{|0\rangle+i|1\rangle}{\sqrt{2}}​ and ∣r⟩=∣0⟩−i∣1⟩2|r\rangle=\frac{|0\rangle-i|1\rangle}{\sqrt{2}}​.

Generally, the measurement box used for the measurement of the qubits, is called a Z-basis measurement, i.e., after applying it on a qubit, it will result either ∣0⟩|0\rangle​ or ∣1⟩|1\rangle​ state. For X-basis measurement, we put a Hadamard gate before the Z-basis measurement box, and for Y-basis measurement, we need to put S†S^{\dagger}​ and Hadamard gates consecutively before the Z-basis measurement box. Let us explain the reason for the above operations so as to make them different measurement bases. It can be observed that, X-basis states {∣+⟩,∣−⟩}\{|+\rangle,|-\rangle\}​ map to Z-basis states {∣0⟩,∣1⟩}\{|0\rangle,|1\rangle\}​ by an operation of Hadamard gate, hence if after measurement, we get ∣0⟩|0\rangle​ or ∣1⟩|1\rangle​, that correspond to ∣+⟩|+\rangle​ or ∣−⟩|-\rangle​ states respectively before the Hadamard operation. Similarly, Y-basis states {∣l⟩,∣r⟩}\{|l\rangle,|r\rangle\}​ can be mapped to Z-basis states {∣0⟩,∣1⟩}\{|0\rangle,|1\rangle\}​, by applying S†S^{\dagger}​ and Hadamard gates consecutively.

## Quantum circuit for different measurement bases

For Z-basis measurement:

from qiskit import QuantumCircuit, execute
from strangeworks.qiskit import get_backend

#taking one classical c and one quantum q register
qc = QuantumCircuit(1, 1)

#measuring the q qubit in Z-basis and storing the results in c bit
qc.measure(, )

# get a Strangeworks backend
backend = get_backend("qasm_simulator")

# execute circuit
execute(qc, backend, shots=100)

After running the codes, ∣0⟩|0\rangle​ results with 100% probability, as initially the qubit was in∣0⟩|0\rangle​ state, and it was measured in Z-basis state.

For X-basis measurement:

from qiskit import QuantumCircuit, execute
from strangeworks.qiskit import get_backend

#taking one classical c and one quantum q register
qc = QuantumCircuit(1, 1)

#measuring the q qubit in X-basis and storing the results in c bit
qc.h(0)
qc.measure(, )

# get a Strangeworks backend
backend = get_backend("qasm_simulator")

# execute circuit
execute(qc, backend, shots=100)


Initially, the qubit was in ∣0⟩|0\rangle​ state, after measuring it in X-basis, ∣0⟩|0\rangle​ and ∣1⟩|1\rangle​ results with equal probability. As ∣0⟩|0\rangle​ and ∣1⟩|1\rangle​ correspond to ∣+⟩|+\rangle​ and ∣−⟩|-\rangle​ states respectively, that means the state before the Hadamard operation was in equal superposition of ∣+⟩|+\rangle​ and ∣−⟩|-\rangle​ states. This can be understood, as ∣0⟩|0\rangle​ can be written as equal superposition of ∣+⟩|+\rangle​ and ∣−⟩|-\rangle​ states, ∣0⟩=∣+⟩+∣−⟩2|0\rangle=\frac{|+\rangle+|-\rangle}{\sqrt{2}}​.

For Y-basis measurement:

from qiskit import QuantumCircuit, execute
from strangeworks.qiskit import get_backend

#taking one classical c and one quantum q register
qc = QuantumCircuit(1, 1)

#measuring the q qubit in Y-basis and storing the results in c bit
qc.sdg(0)
qc.h(0)
qc.measure(, )

# get a Strangeworks backend
backend = get_backend("qasm_simulator")

# execute circuit
execute(qc, backend, shots=100)

In a similar way, in Y-basis measurement, ∣0⟩|0\rangle​ and ∣1⟩|1\rangle​ result with equal probabilites, meaning that, ∣l⟩|l\rangle​ and ∣r⟩|r\rangle​ states were there before the Y-basis measurement. As it can be seen that ∣0⟩|0\rangle​ can be written as equal superposition of ∣l⟩|l\rangle​ and ∣r⟩|r\rangle​ states, i.e., ∣0⟩=∣l⟩+∣r⟩2|0\rangle=\frac{|l\rangle+|r\rangle}{\sqrt{2}}

# Basic single-qubit gates

Basic single-qubit gates are Hadamard (HH​), XX​, YY​, ZZ​, SS​, S†S^{\dagger}​, TT​, T†T^{\dagger}​, U1(ϕ)U_1(\phi)​, U3(θ,ϕ,λ)U_3(\theta,\phi,\lambda)​. The matrix form of the above are given in the following.

H=12[111−1]H=\frac{1}{\sqrt{2}}\left [{\begin{array}{cc} 1 &1 \\ 1& -1 \end{array}}\right ]​, X=X=\left [{\begin{array}{cc} 0 &1 \\ 1& 0 \end{array}}\right ]​, Y=[0−ii0]Y=\left [{\begin{array}{cc} 0 &-i \\ i& 0 \end{array}}\right ]​, Z=[101−1]Z=\left [{\begin{array}{cc} 1 &0 \\ 1& -1 \end{array}}\right ]​, S=[100i]S=\left [{\begin{array}{cc} 1 &0 \\ 0& i \end{array}}\right ]​, S†=[100−i]S^{\dagger}=\left [{\begin{array}{cc} 1 &0 \\ 0& -i \end{array}}\right ]​, T=[100eiπ/4]T=\left [{\begin{array}{cc} 1 &0 \\ 0& e^{i\pi/4} \end{array}}\right ]​, T†=[100e−iπ/4]T^{\dagger}=\left [{\begin{array}{cc} 1 &0 \\ 0& e^{-i\pi/4} \end{array}}\right ]​, U1(ϕ)=[100eiϕ]U_1(\phi)=\left [{\begin{array}{cc} 1 &0 \\ 0& e^{i\phi} \end{array}}\right ]​, U3(θ,ϕ,λ)=[cos(θ/2)−eiλsin(θ/2)eiϕsin(θ/2)ei(ϕ+λ)cos(θ/2)]U_3(\theta,\phi,\lambda)=\left [{\begin{array}{cc} cos(\theta/2) &-e^{i\lambda}sin(\theta/2) \\ e^{i\phi}sin(\theta/2) & e^{i(\phi+\lambda)}cos(\theta/2) \end{array}}\right ]​​

It can be noted that U3U_3​ gate is the general form, i.e., any single-qubit gates, can be written in terms of U3U3U3U_3​ gate by choosing proper values, of θ\theta​, ϕ\phi and λ\lambda​. U1U_1​ gate in general called as phase gate, i.e., any value of phase gate can be achieved with this gate.

Let us some of single-qubit gate operations on the quatum states,

A Hadamard gate acting on computational basis states, {∣0⟩,∣1⟩}\{|0\rangle,|1\rangle\}​ gives the following X-basis states,

H∣0⟩→∣+⟩H|0\rangle\rightarrow|+\rangle​​

H∣1⟩→∣−⟩H|1\rangle\rightarrow|-\rangle​​

Again, applying Hadamard gate on {∣+⟩,∣−⟩}\{|+\rangle,|-\rangle\}​ gives computational basis states {∣0⟩,∣1⟩}\{|0\rangle,|1\rangle\}​​

H∣+⟩→∣0⟩H|+\rangle\rightarrow|0\rangle​​

H∣−⟩→∣1⟩H|-\rangle\rightarrow|1\rangle​​

Similarly, Pauli {X,Y,Z}\{X,Y,Z\}​ operations can be given as,

X∣0⟩→∣1⟩X|0\rangle\rightarrow|1\rangle​​

X∣1⟩→∣0⟩X|1\rangle\rightarrow|0\rangle​​

Y∣0⟩→i∣1⟩Y|0\rangle\rightarrow i|1\rangle​​

Y∣1⟩→−i∣1⟩Y|1\rangle\rightarrow-i|1\rangle​​

Z∣0⟩→∣0⟩Z|0\rangle\rightarrow|0\rangle​​

Z∣1⟩→−∣1⟩Z|1\rangle\rightarrow-|1\rangle​​

Application of phase gates and general unitary operations can be given as,

U1(ϕ)∣0⟩→∣0⟩U_1(\phi)|0\rangle\rightarrow|0\rangle​​

U1(ϕ)∣1⟩→eiϕ∣1⟩U_1(\phi)|1\rangle\rightarrow e^{i\phi}|1\rangle​​

U3(θ,ϕ,λ)∣0⟩→cos(θ/2)∣0⟩+eiϕsin(θ/2)∣1⟩U_3(\theta,\phi,\lambda)|0\rangle\rightarrow cos(\theta/2)|0\rangle+e^{i\phi}sin(\theta/2)|1\rangle​​

U3(θ,ϕ,λ)∣1⟩→−eiλsin(θ/2)∣0⟩+ei((ϕ+λ)cos(θ)∣1⟩U_3(\theta,\phi,\lambda)|1\rangle\rightarrow -e^{i\lambda}sin(\theta/2)|0\rangle+e^{i((\phi+\lambda)}cos(\theta)|1\rangle​​

# Basic two-qubit gates

Controlled-Not gate (CNOT) is a two-qubit gate, also called as an entangling gate, is used for creating entanglement between two or more than two qubits. CNOT acts on two qubits, where one is control and the other qubit is the target qubit. In a CNOT operation, Not gate is applied on the target qubit when the control qubit is in ∣1⟩|1\rangle​ state. The matrix form of CNOT operation can be given as,

CNOT=CNOT=\left [{\begin{array}{cccc} 1 &0&0&0 \\ 0 & 1&0&0 \\ 0&0&0&1 \\0&0&1&0 \end{array}}\right ]​. There are other two-qubit basic gates such as controlled-U3U_3​ gate, and cotrolled-U1U_1​ gates, whose forms can be given as follows,

Controlled−U3(θ,ϕ,λ)=[1000010000cos(θ/2)−eiλsin(θ/2)00eiϕsin(θ/2)ei(ϕ+λ)cos(θ/2)]\rm{Controlled-}U_3(\theta,\phi,\lambda)=\left [{\begin{array}{cccc} 1 &0&0&0 \\ 0 & 1&0&0 \\ 0&0&cos(\theta/2)&-e^{i\lambda}sin(\theta/2) \\0&0&e^{i\phi}sin(\theta/2)&e^{i(\phi+\lambda)}cos(\theta/2) \end{array}}\right ]​,

Controlled−U1(ϕ)=[100001000010000eiϕ]\rm{Controlled-}U_1(\phi)=\left [{\begin{array}{cccc} 1 &0&0&0 \\ 0 & 1&0&0 \\ 0&0&1&0 \\0&0&0&e^{i\phi} \end{array}}\right ]​,

It can be noted that any two-qubit controlled-U operator can be designed using Controlled-U3U_3​ gate, after choosing appropriate parameters.

Application of CNOT operation on the computational basis states can be shown as,

CNOT∣00⟩→∣00⟩CNOT|00\rangle\rightarrow|00\rangle​​

CNOT∣01⟩→∣01⟩CNOT|01\rangle\rightarrow|01\rangle​​

CNOT∣10⟩→∣11⟩CNOT|10\rangle\rightarrow|11\rangle​​

CNOT∣11⟩→∣10⟩CNOT|11\rangle\rightarrow|10\rangle​​

It can be observed that, in the last two cases, when the first qubits are in ∣1⟩|1\rangle​ state, then not gates are applied on the corresponding target qubits.

A control-U3 operation also can be shown as,

Controlled−U3(θ,ϕ,λ)∣00⟩→∣00⟩\rm{Controlled-}U_3(\theta,\phi,\lambda)|00\rangle\rightarrow|00\rangle​​

C−U3(θ,ϕ,λ)∣01⟩→∣01⟩C-U3(\theta,\phi,\lambda)|01\rangle\rightarrow|01\rangle​​

C−U3(θ,ϕ,λ)∣10⟩→∣1⟩(cos(θ/2)∣0⟩+eiϕsin(θ/2)∣1⟩)C-U3(\theta,\phi,\lambda)|10\rangle\rightarrow|1\rangle (cos(\theta/2)|0\rangle+e^{i\phi}sin(\theta/2)|1\rangle)​​

C−U3(θ,ϕ,λ)∣11⟩→∣1⟩(−eiλsin(θ/2)∣0⟩+ei(ϕ+λ)cos(θ/2)∣1⟩)C-U3(\theta,\phi,\lambda)|11\rangle\rightarrow|1\rangle (-e^{i\lambda}sin(\theta/2)|0\rangle+e^{i(\phi+\lambda)}cos(\theta/2)|1\rangle)​​

# Other two-qubit and multiple qubit gates

Swap gate is another two-qubit important gate which just swaps the qubit states. The matrix form of the swap gate is given as,

Swap=Swap=\left [{\begin{array}{cccc} 1 &0&0&0 \\ 0 & 0&1&0 \\ 0&1&0&0 \\0&0&0&1 \end{array}}\right ]​​

This can be designed using three CNOT gates, such as Swap01=CNOT01CNOT10CNOT01Swap_{01}=CNOT_{01}CNOT_{10}CNOT_{01}​, where Swap01Swap_{01}​​

denotes Swap gate is applied on the qubits qq​ and qq​, and CNOTijCNOT_{ij}​ denotes the CNOT gate is applied on ithi^{th}​ and jthj^{th}​ qubits, where q[i]q[i]​ acts as the control qubit and q[j]q[j]​ acts as the target qubit.

Demonstration of Swap gate:

from qiskit import QuantumCircuit, execute
from strangeworks.qiskit import get_backend

#taking two classical c[0,1] and two quantum q[0,1] registers
qc = QuantumCircuit(2, 2)

#preparing 10 state
qc.x(0)

#applying Swap operation on q and q qubits

qc.cx(0,1)
qc.cx(1,0)
qc.cx(0,1)

#now after the swap operation the state becomes 01
qc.measure([0,1], [0,1])

# get a Strangeworks backend
backend = get_backend("qasm_simulator")

# execute circuit
execute(qc, backend, shots=100)

It can be observed that, initially the qubits were in ∣10⟩|10\rangle​ state, after the swap operation, it was converted to ∣01⟩|01\rangle​ state. Similarly, for other two-qubit states, it can be checked.

There is another two-qubit anti-controlled operation, which acts on two qubits, among which one is anti-control qubit, and the other is target qubit. In an anti-control-U operation, U is operated on the target qubit, when the control qubit is in ∣0⟩|0\rangle​ state.

Let us take an example of anit-control Not operation.

from qiskit import QuantumCircuit, execute
from strangeworks.qiskit import get_backend

#taking two classical c[0,1] and two quantum q[0,1] registers
qc = QuantumCircuit(2, 2)

#preparing 01 state
qc.x(1)

#applying anti-control Not operation on q and q qubits, where q is the control qubit and q is the target qubit
qc.x(0)
qc.cx(0,1)
qc.x(0)

#now after the anti-control Not operation the state becomes 00
qc.measure([0,1], [0,1])

# get a Strangeworks backend
backend = get_backend("qasm_simulator")

# execute circuit
execute(qc, backend, shots=100)

As can be seen from the above measurement, initiallly the qubits were in ∣01⟩|01\rangle​ state, after the application of anti-control Not operation, the state becomes ∣00⟩|00\rangle state.

Let us now discuss a three-qubit gate named Toffoli gate, which is also known as control-control-Not gate. Toffoli gate is applied on  a three-qubit system, where the first two qubits act as the control qubit and the third qubit acts as the target qubit. When the control qubits are in ∣1⟩|1\rangle​ state, then Not gate is applied on the target qubit.

A circuit demonstration for one of the examples is given here,

from qiskit import QuantumCircuit, execute
from strangeworks.qiskit import get_backend

#taking two classical c[0,1,2] and two quantum q[0,1,2] registers
qc = QuantumCircuit(3, 3)

#preparing 110 state
qc.x(0)
qc.x(1)

#applying Toffoli operation on q, q and q qubits
qc.ccx(0,1,2)

#now after the Toffoli operation the state becomes 111
qc.measure([0,1,2], [0,1,2])

# get a Strangeworks backend
backend = get_backend("qasm_simulator")

# execute circuit
execute(qc, backend, shots=100)

It can be observed that, applying Toffoli operation on ∣110⟩|110\rangle​ state, it converts to ∣111⟩|111\rangle​. Similarly, for other cases, it can be checked by applying Toffoli gate onto different states.