## Introduction

The purpose of this notebook article is to demonstrate using quantum operations to achieve computing objectives. The term *quantum operation* refers to a higher level method that may be implemented with one or many low-level quantum gates. More generally, the goal is to demonstrate the notion that quantum algorithms use quantum operations to implement constraints that coerce qubits from representing any possible outcomes to representing the outcomes that satisfy the constraints.

Using John Preskill's terminology, we now have "noisy intermediate scale quantum" (NISQ) computers that can obtain a desired outcome with high probablility, i.e. where the desired outcome rises well above the noise that can occur within the current early-stage quantum computing devices. In this notebook article, we will implement a classical computing algorithm in order to see how differently it is done in quantum computing, and we will see that the desired outcome occurs by far the most frequently. However, note that the emphasis is on understanding how the quantum operations achieve an easily understood result, and so there is no quantum computing speedup in this case.

In this noteboook article, we will create a **quantum circuit** that uses quantum operations to perform **addition** of two single bit numbers. This problem reduces to developing quantum operation sequences that perform a classical 'XOR' operation to calculate the least significant bit and a classical 'AND' operation to calculate the most significant bit of the answer. This can be seen in the two columns of the expected answers below:

0+0=00 0+1=01 1+0=01 1+1=10

## Qiskit Installation and Import

The Quantum Information Science development kit, or Qiskit, is a library and framework for either connecting to and running quantum computing programs on a real IBM Q quantum computer or simulating them on the user's classical computing environment. The first cell below contains code to run once to get Qiskit installed. The second cell below should be run any time the notebook starts to import the parts of Qiskit relevant to this notebook's operations.

```
[1] !pip install --user qiskit
[2] from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import execute, IBMQ, Aer, QISKitError
from qiskit.backends.ibmq import least_busy
```

## The Memory Model for the Quantum Circuit

This notebook uses qubits *q _{0}* and

*q*for the inputs. Qubit

_{1}*q*will be used for the least significant bit of the answer, and qubit

_{2}*q*will be for the most significant bit.

_{3}```
[3] num_qubits = 4
q = QuantumRegister(num_qubits)
c = ClassicalRegister(num_qubits)
```

## Quantum Circuit Initialization and Input

The following cell creates the quantum circuit with the quantum and classical registers. Then, it assigns the input to qubits *q _{0}* and

*q*.

_{1}The ground state |0> is the default, so an X gate is used on qubits that must start in the excited state |1>. The X gate performs a *pi* radian rotation about the X-axis, which rotates |0> (a.k.a. |+z>) through the Y-axis to |1> (a.k.a. |-z>). The X gate is sometimes called a NOT gate, but note that it performs a *pi* radian rotation that happens to perform a classical NOT, or bit flip, only when the qubit is in |0> or |1> state. **To change the input**, comment out the X gate operation on any qubits that should be |0> and ensure the X gate is not commented on any qubits that should be initialized to |1>.

```
[4] qc = QuantumCircuit(q, c)
qc.x(q[0])
qc.x(q[1])
```

## Performing 'XOR' with Quantum Operations

An 'XOR' can be performed with two quantum operations. The inputs of the 'XOR' come from qubits *q _{0}* and

*q*, and the output of the 'XOR' will go to qubit

_{1}*q*. The output qubit,

_{2}*q*, starts in the ground state, |0>.

_{2}We first apply a controlled-not operation with *q _{2}* as the target of the control and with

*q*as the source. The controlled-not is also called CNOT, or CX. This operation negates the target if the source is excited (|1>). By itself, this operation changes

_{0}*q*from |0> to |1> if

_{2}*q*is |1>, and it leaves

_{0}*q*unchanged if

_{2}*q*is |0>.

_{0}Next, we apply a CNOT with qubit *q _{2}* as the target and with

*q*as the source. If

_{1}*q*is |0>, then

_{1}*q*is unchanged from the effect of the CNOT with

_{2}*q*. Therefore, we have:

_{0}*q _{0}*=|0>

*q*=|0> results in

_{1}*q*=|0>

_{2}*q _{0}*=|1>

*q*=|0> results in

_{1}*q*=|1>

_{2}However, if *q _{1}* is |1>, then

*q*is inverted relative to the effect of the CNOT with

_{2}*q*. Therefore, we have:

_{0}*q _{0}*=|0>

*q*=|1> results in

_{1}*q*=|1>

_{2}*q _{0}*=|1>

*q*=|1> results in

_{1}*q*=|0>

_{2}This concludes the method for performing 'XOR' with quantum operation, which calculates the least significant bit of the single bit addition result.

```
[5] qc.cx(q[0], q[2])
qc.cx(q[1], q[2])
```

## Performing 'AND' with Quantum Operations

An 'AND' can be performed with three quantum operations. The inputs of the 'AND' come from qubits *q _{0}* and

*q*, and the output of the 'AND' will go to qubit

_{1}*q*. The output qubit,

_{3}*q*, starts in the ground state, |0>.

_{3}**Operation 1.** We target qubit *q _{3}* with a controlled-Hadamard operation that is controlled by the source qubit

*q*. This changes the target

_{0}*q*from |0> to |+x> if the source

_{3}*q*is |1>. The operation looks like this on the Bloch sphere:

_{0}**Operation 2.** Next, we target qubit *q _{3}* with a controlled-Z operation that is controlled by the source qubit

*q*. This changes the phase of the target

_{1}*q*by rotating

_{3}*pi*radians around Z-axis if the source qubit

*q*is |1>. The operation looks like this on the Bloch sphere:

_{1}The following are the results so far:

- For input
*q*_{1}*q*= |0> |0>,_{0}*q*is not changed from |0>_{3} - For input
*q*_{1}*q*= |0> |1>,_{0}*q*only changed to |+x>_{3} - For input
*q*_{1}*q*= |1> |0>,_{0}*q*is at |0> because_{3}*q*did not rotate it, and_{0}*q*requests a Z-axis phase rotation, but |0> is along the Z-axis, so rotating it does nothing._{1} - For input
*q*_{1}*q*= |1> |1>,_{0}*q*is |-x> due to_{3}*pi*phase rotation from |+x>

**Operation 3.** Finally, we target *q _{3}* with a controlled-Hadamard operation that is controlled by the source qubit

*q*. Note above that when input

_{0}*q*is |0>,

_{0}*q*is already in the correct state of |0>. Therefore, we only take a further action if

_{3}*q*is |1>.

_{0}When *q _{0}* is |1>, then the controlled-Hadamard operation maps the X-axis to the Z-axis, so |+x> is converted to |+z>=|0> and |-x> is converted to |-z>=|1>. The operation looks like this on the Bloch sphere:

This concludes the method for performing 'AND' with quantum operation, which calculates the most significant bit of the single bit addition result.

```
[6] qc.ch(q[0], q[3])
qc.cz(q[1], q[3])
qc.ch(q[0], q[3])
```

## Perform the Measurement

Use this code to measure the state of the qubits, giving a classical computing answer.

`[7] qc.measure(q, c)`

## Simulate the Quantum Circuit

On a simulator, use this code to execute the quantum circuit that defines the input, performs the processing, and measures the output. Then, render the output in the notebook user interface.

```
[8] simulator = Aer.get_backend('qasm_simulator')
job = execute(qc, simulator)
result = job.result()
print("Data Result:", result.get_data(qc))
```

Based on the initialization in cell [5] above, the simulator always produces the result '10' (2) in qubits *q _{3}* and

*q*.

_{2}## Run the Experiment on a Real IBM Q Quantum Computer

Now we will set up to run on a real IBM Q quantum computer. The first cell below contains code that only has to run once per Python run-time to get it to work with your IBM Q Experience account. The second cell should be run once per notebook session to load the user's IBM Q quantum computer access token.

[9] IBMQ.save_account('your API token') [10] IBMQ.load_accounts()

Now this cell obtains access to a real IBM Q quantum computer on which to compile and execute the code.

```
[11] result_counts = {}
try:
device = IBMQ.get_backend('ibmqx4')
job_exp = execute(qc, device, shots=1024, max_credits=10)
result_exp = job_exp.result()
result_counts = result_exp.get_counts(qc)
except:
print("Device is currently unavailable.")
```

In the results, the qubits are in the order *q _{3}*,

*q*,

_{2}*q*, and

_{1}*q*, so we tally the outcomes based on the first two qubits as they are the output qubits.

_{0}[12] result_freqs = {'00':0, '01':0, '10':0, '11':0 } for key in result_counts.keys(): freq_key = key[0:2] result_freqs[freq_key] = result_freqs[freq_key] + result_counts[key] import matplotlib.pyplot as plt D = result_freqs plt.bar(range(len(D)), list(D.values()), align='center') plt.xticks(range(len(D)), list(D.keys())) plt.show()

There are four possible outcomes for the two output qubits: 00, 01, 10, and 11. The expected outcome is 10. With 1024 shots, the noise outcome would be on the order of 256 shots per possible outcome. In the frequency results shown below, one can see that, by far, the correct final state of the output qubits occurs more frequently than all other possible outcomes combined. A most frequently occurring quantum computing outcome is precisely what a quantum experimentalist would investigate first within their real world application.

## Conclusion

In this notebook, we have demonstrated how quantum algorithms use quantum operations to coerce qubits into representing the outcome or outcomes that satisfy the constraints of a problem. In the case of quantum addition of two qubits initialized with classical bit values, one output qubit had to satisfy the constraint of being excited if and only if the two input qubits differed, and a second output qubit had to satisfy the constraint of being excited if and only if both input qubits were excited. Not only did we simulate this quantum circuit, we ran it on a real IBM Q quantum computer. When we did, we witnessed the fact that in the NISQ era, one plus one is most probably two!

Finally, note that the quantum logical AND method we built above is also signicant because one can append an X gate, which performs a logical NOT, resulting in a NAND operation. In classical cmputing, the NAND operation is a universal gate that can be used to build all other classical computing circuits. **Therefore, any classical computing solution can be expressed... and we have only used 4 points of the Bloch sphere representing the total expressive power available to each qubit of a quantum computer.**

### Related Links

Qiskit. An open-source quantum computing framework for leveraging today's quantum processors in research, education, and business.

### Acknowledgements

The author gratefully acknowledges the thorough reviews and feedback by Luuk Ament and Robert Loredo.