# Superdense Coding and Quantum Teleportation

**Harnessing the Power of Entanglement for Communication — Part 3**

Before we delve into quantum communcation, let’s understand Bell states (also known as EPR Pairs). These represent specific quantum states of two qubits that represent the simplest examples of quantum entanglement.

## Bell States

There are four Bell states, each representing a maximally entangled state of two qubits. These states are particularly important because they form a basis for the space of two-qubit states, much like how individual qubits have basis states |0⟩ and |1⟩. The four bell states are listed below:

- |Φ +⟩= (|00⟩ + |11⟩)/√2
- |Φ −⟩= (|00⟩ − |11⟩)/√2
- |Ψ +⟩= (|01⟩ + |10⟩)/√2
- |Ψ −⟩= (|01⟩ − |10⟩)/√2

For quantum communication, it is also important to understand the no-cloning theorem and no-communication theorem. The no-cloning theorem states that it is impossible to create an independent and identical copy of an arbitrary unknown quantum state. The no-communication theorem states that during measurement of an entangled quantum state, it is not possible for one observer, by making a measurement of a subsystem of the total state, to communicate information to another observer, i.e. quantum entanglement alone cannot be used to transmit information faster than the speed of light.

Given the above limitations, you might ask then what is the benefit of quantum computing for communication. While we cannot transmit information using entanglement alone, the theory does not restrict us from transmitting information by physically sending a qubit that is entangled. This is where Superdense coding comes in — it is a quantum communication platform that allows a sender to send two classical bits of information by transmitting just one qubit, under the condition that the two parties share an entangled pair of qubits beforehand.

**Superdense Coding**

**Step 1: **The process starts with a third-party, Charlie, preparing two entangled qubits in a Bell State. Charlie does that by applying a Hadamard gate to the first qubit and then a CNOT gate using the first qubit as the control and the second as the target. Charlie then sends the first qubit to Alice and the second qubit to Bob.

**Step 2: **Alice now wants to send 2 bits of classical information to Bob. Remember that even though a qubit is measured as |0⟩ or |1⟩, the quantum states are described by a set of complex-valued coefficients and therefore Alice can easily encode 2 bits of information into a qubit as long as Bob has a way to decode the qubit to access the 2 bits of information. Alice will now apply the appropriate quantum gates to her qubit depending on the 2 bits of information she wants to send. Depending on the information she wants to send, she can apply the following gates:

These states correspond to each of the four Bell states we discussed earlier.

**Step 3: **Bob receives the qubit from Alice and uses his qubit to decode Alice’s message. He does not need to know the state in order to decode it. All quantum gates are reversible and preserve information that we started out in the Bell state. Bob will therefore apply a CNOT gate using Alice’s qubit using the same control and target as it was applied to prepare the entangled qubit by Charlie. Bob will then apply a Hadamard gate and perform measurement on both qubits to extract Alice’s message.

We can simulate Superdense coding protocol on Qiskit using the code below:

`# Importing required libraries`

from qiskit import QuantumCircuit

from qiskit import IBMQ, Aer, transpile

from qiskit.visualization import plot_histogram

`def create_bell_pair():`

"""

Returns:

QuantumCircuit: Circuit that produces a Bell pair

"""

qc = QuantumCircuit(2)

qc.h(1)

qc.cx(1, 0)

return qc

`def encode_message(qc, qubit, msg):`

"""Encodes a two-bit message on qc using the superdense coding protocol

Args:

qc (QuantumCircuit): Circuit to encode message on

qubit (int): Which qubit to add the gate to

msg (str): Two-bit message to send

Returns:

QuantumCircuit: Circuit that, when decoded, will produce msg

Raises:

ValueError if msg is wrong length or contains invalid characters

"""

if len(msg) != 2 or not set(msg).issubset({"0","1"}):

raise ValueError(f"message '{msg}' is invalid")

if msg[1] == "1":

qc.x(qubit)

if msg[0] == "1":

qc.z(qubit)

return qc

`def decode_message(qc):`

qc.cx(1, 0)

qc.h(1)

return qc

`# Charlie creates the entangled pair between Alice and Bob`

qc = create_bell_pair()

# barrier for visual separation

qc.barrier()

# At this point, qubit 0 goes to Alice and qubit 1 goes to Bob

# Next, Alice encodes her message onto qubit 1.

message = '01'

qc = encode_message(qc, 1, message)

qc.barrier()

# Alice then sends her qubit to Bob.

# After receiving qubit 0, Bob applies the recovery protocol:

qc = decode_message(qc)

# Finally, Bob measures his qubits to read Alice's message

qc.measure_all()

# Draw our output

qc.draw()

The resulting circuit will look like below:

We can simulate the result of our circuit below:

`aer_sim = Aer.get_backend('aer_simulator')`

result = aer_sim.run(qc).result()

counts = result.get_counts(qc)

print(counts)

plot_histogram(counts)

**Teleportation**

This time Alice wants to send some quantum information to Bob. As we discussed previously, that the laws of the universe does not allow us to copy an arbitrary quantum state (no-cloning theorem), therefore Alice will need to “teleport” an arbitrary qubit state in her possession to Bob, without sending him any qubits.

Quantum teleportation is a process by which the state of a qubit can be transmitted from one location to another, with the help of classical communication and quantum entanglement.

This protocol will require three qubits. Similar to Superdense coding, we will assume a third-party Charlie or Telemon prepares the two entangled qubits and send one to Alice and one to Bob.

- The qubit to be teleported (q0)
- One half of an entangled pair of qubit (bell0 — Alice’s qubit)
- The other half of the entangled pair (bell1 — Bob’s qubit)

We will take the following steps:

**Step 1: **Create an entangled pair of qubits (Bell pair) shared between Alice and Bob.

**Step 2: **Alice performs a Bell basis measurement on her two qubits.

**Step 3: **Alice sends the classical results of her measurement to Bob using classical communication mode.

**Step 4: **Bob applies appropriate quantum gates based on Alice’s measurement results to obtain the teleported state.

Let’s implement it in qiskit, using the lab from Qiskit Summer School 2023:

Import required libraries:

`from qiskit.circuit import ClassicalRegister, QuantumRegister`

Prepare the qubit to be teleported:

`theta = Parameter('θ')`

qr = QuantumRegister(1, 'q')

qc = QuantumCircuit(qr)

qc.ry(theta, 0)

qc.draw('mpl')

Setup the remaining circuit:

`tele_qc = qc.copy()`

bell = QuantumRegister(2, 'Bell')

alice = ClassicalRegister(2, 'Alice')

bob = ClassicalRegister(1, 'Bob')

tele_qc.add_register(bell, alice, bob)

tele_qc.draw('mpl')

Create bell state with other two qubits:

`# create Bell state with other two qubits`

tele_qc.barrier()

tele_qc.h(1)

tele_qc.cx(1, 2)

tele_qc.barrier()

tele_qc.draw('mpl')

Next, Alice will perform a CNOT controlled by 1 on Bell0, which maps information about the state on it. She then applies Hadamard gate on q:

`# alice operates on her qubits`

tele_qc.cx(0, 1)

tele_qc.h(0)

tele_qc.barrier()

tele_qc.draw('mpl')

Alice will then measure her qubits and save the results to her register:

`tele_qc.measure([qr[0], bell[0]], alice)`

tele_qc.draw('mpl')

Bob’s qubit now has the information from Alice’s qubit q encoded in Bell1. However, Bob does not know how to extract that information. Alice shares information with Bob over a classical communication channel and instructs Bob to perform an X gate on his qubit if her measurement of Bell0 yields a 1 outcome, followed by a Z gate if her measurement of q yeilds a 1:

`graded_qc = tele_qc.copy()`

with graded_qc.if_test((alice[1],1)):

graded_qc.x(bell[1])

with graded_qc.if_test((alice[0],1)):

graded_qc.z(bell[1])

graded_qc.draw('mpl')

Finally Bob measures his qubit:

`graded_qc.barrier()`

graded_qc.measure(bell[1], bob)

graded_qc.draw('mpl')

We will now run both the circuts on a simulator using an angle of 5π/7, which will yield a 1 result about 80% of the time and 0 result about 20% of the time. If all went well then we should see similar results from both the circuits:

`from qiskit_aer.primitives import Sampler`

angle = 5*np.pi/7

sampler = Sampler()

qc.measure_all()

job_static = sampler.run(qc.bind_parameters({theta: angle}))

job_dynamic = sampler.run(graded_qc.bind_parameters({theta: angle}))

print(f"Original Dists: {job_static.result().quasi_dists[0].binary_probabilities()}")

print(f"Teleported Dists: {job_dynamic.result().quasi_dists[0].binary_probabilities()}")

# marginalizing counts

from qiskit.result import marginal_counts

tele_counts = marginal_counts(job_result_bp, [2]) # marginalize counts

# plotting histogram

legend = ['Original State', 'Teleported State']

plot_histogram([job_static.result().quasi_dists[0].binary_probabilities(), tele_counts], legend=legend)

As we can see that the quasi-distributions from Alice’s measurement and Bob’s measurement are nearly identical, demonstrating that teleportation was successful.

This is Part 3 in a series of articles on quantum computing. The links to all the parts are below: