# Baths 2023 Quantum Bootcamp¶

Welcome to the OpenQAOA challenge!

Our challenge is to solve the Graph Colouring problem, one of the famous NP-complete problems, with a quantum computer.

As far as we know, it is not possible to solve a NP-complete problem in polynomial time. Therefore, one way to tackle NP problems is to employ heuristics. The **quantum approximate optimization algorithm (QAOA)** is one such heuristic algorithm, and it can be used to solve (small!) binary optimization problems. What interests us today, is that QAOA is an algorithm that can be run on existing quantum computers!

For the curious

The original QAOA paper can be found on the arxiv (Farhi, Edward, Jeffrey Goldstone, and Sam Gutmann. "A quantum approximate optimization algorithm"). The paper is a bit technical, and may not be the best reference for a 12h challenge. So, if you need a more lay-down intro, please check out the OpenQAOA what-is-the-qaoa reference.

**How to approach the challenge**¶

Quantum computations are not easy. So, we broke the challenge into a series of sequential steps.

You don't need to strictly follow the steps as we have outlined them. The most important things are:

- A correct implementation of the graph coloring problem
- Your exploration of the problem space!

The last section includes some ideas on how to further explore the challenge.

**STEP 1. Find the cost Hamiltonian**¶

First things first: what are we trying to do? We are given a graph with \(N\) vertices and some connectivity, and a set of \(k\) colors. The optimization problem then is to **find a color for each vertex such that no edge connects two vertices of same color.** Four simple examples are given by the following choices of graphs and coloring:

**STEP 1.1. Understand the cost function**¶

Now that we have an idea of the problem that we are trying to solve, we need to encode the graph colouring problem as a cost function \(f(\vec y)\), a function to minimize. The input of this function could be a vector \(\vec y = (y_1, y_2, ..., y_N)\), where \(y_i \in \{0, 1, ..., k-1\}\) indicates the color of the \(i\) node. Then the solution of the problem could be expressed as:

However, we want to solve the problem on a quantum computer, where qubits can only take one of two values when measured: \(\uparrow\) and \(\downarrow\). This requires you to write the cost function in terms of \(n\) **binary variables**, \(\vec x = (x_1, ..., x_n)\) where \(x_i \in \{0,1\}\) and \(n>N\) *(note that \(n\) is also the number of qubits that you will use)*.

A good place to familiarize yourself with these type of cost functions is the great paper Ising formulations of many NP problems by Andrew Lucas. In section \(6.1\) he introduces graph colouring problems, and it offers the following cost function:

Here the indices \(u, v\) indicate the label of the graph node, \(i\) indicates the color and \(E\) the edges of the graph that we want to color.

Think

Spend some time convincing yourself that the above cost function makes sense! What is the significance of the first term? And the second?

How many **binary variables \(n\)** would you need to encode a N-nodes graph given k-colours? How does that scale?

Try to use a very simple encoding, since compressed encodings can make your life harder.

**STEP 1.2. Get the QUBO problem**¶

Although the function above is the right cost function, it is not trivial to see the decomposition of the QAOA circuit from it. Instead, you should convert it to a QUBO problem:

where \(Q\) is a matrix that encodes the whole problem.

**Therefore, your task is to find the expression for the \(Q_{ij}\) for coloring any given graph with \(k\) colors.**

Once we have the expression for the \(Q\) matrix, we will be very close to be able to color graphs with QAOA.

**STEP 1.3. Understand the Ising model**¶

However, to optimize this function and to find one solution \(\vec x^*\) in a quantum computer using QAOA we need to use the Ising encoding, which means that the binary encoding must be \(\{-1,+1\}\), instead of \(\{0, 1\}\). This is more detailed in the what-is-the-qaoa page.

The cost function of a QUBO problem in the Ising encoding reads:

here, \(\vec s = (s_1, ..., s_n)\) with \(s_i\in\{-1,1\}\). The \(J\) is a symmetric matrix with zeros in the diagonal, and \(h\) is a vector. These two are related with the \(Q\) as follows:

So for any given problem, after we find \(Q\), we can get \(J\) and \(h\) with this transformation. We are, now, ready to code!

For the curious

QUBO stands for quadratic unconstrained binary optimization. You can check out the what-is-a-qubo to learn more about it and see some examples.

**STEP 2. Solve the Graph coloring problem using OpenQAOA**¶

Take a look at the OpenQAOA workflows to check how you can solve problems using QAOA. You can find them at the-simplest-workflow and customise-the-QAOA-workflow. But as a quick recap, the easiest way to run QAOA is:

where `qubo_problem`

is defined as:

```
from openqaoa.problems import QUBO
qubo_problem = QUBO(terms=[[..], [..], ...],
weights=[...],
n=number_of_vertices)
```

`terms`

is a list of lists, and `weights`

is a list of integers. As an example, if one has a QUBO problem encoded in a matrix \(J\) and a vector \(h\) like
where the second equality holds because QUBO matrices are symmetric, and

then the QUBO object would be initialized as:

```
qubo_problem = QUBO(terms= [[0,1], [0,2], [1,2], [0], [1], [2]],
weights= [J_01, J_02, J_12, h_0, h_1, h_2],
n=number_of_vertices)
```

Info

When initializing the QUBO object in OpenQAOA there is no need to include the terms that are weighted 0, and make sure that `len(terms) == len(weights)`

.

**STEP 2.1. Code the QUBO problem**¶

Your job is to write a function that takes as an input a graph to be colored, and the number of colors and it returns a QUBO object:

Hint

If you are stuck, and you need some inspiration you can check how some of the other problem classes are structured in OpenQAOA by checking out the OpenQAOA github page. In particular, the method `get_qubo_problem()`

has the same functionality that you are tackling here.

**STEP 2.2. Run QAOA**¶

Now it's time to try to color some graphs running a QAOA on a quantum simulator.

Let's start with only \(k=3\) colors on a small graph such as:

Now convert this problem instance to a qubo using the `graph_coloring_qubo`

function that you have implemented already by doing:

You can try to color other more complicated graphs, some examples could be:

QAOA is an heuristic

You may find solutions that are not optimal (or even not feasible!). This can happen because QAOA is an approximation and quantum computers are noisy. We recommend you to solve the problem classically to see the optimal solutions that we are trying to find with QAOA. You can do that with OpenQAOA:

```
ground_state_hamiltonian(gc_qubo.hamiltonian)
```

Try not to crash your laptop!

Remember that to simulate a quantum computer you need \(2^{n}\) variables, where \(n\) is the number of qubits. In our case this means that given \(k\) colors and \(N\) vertices you will need \(2^{kN}\) numbers. Typically each number is represented by 128bits. You can try to plot \(128 * 2^{kN}\) to see how quickly you will run out RAM!

**STEP 3. Interpret the result**¶

So, you ran a QAOA workflow successfully ... what next? Well, you can start studying the `q.result`

object. First, read the making-sense-of-the-result page.

The result will look at so

This represents the most probable quantum state identified by the QAOA. In order to figure out how to interpret this result, you need to go back to the cost function. You need to make sure you know how to map each binary variable within the bistring back to the binary variable \(x_{v,i}\)!

**Try to plot the problem graphs with the coloring solution.**

**OPTIONAL. Study the QAOA parameters**¶

Our goal is to achieve the lowest cost value. How does the lowest cost change as we vary certain QAOA Parameters?

What happens when you vary the number of layers \(p\)? And as you increase the number of vertices? What can you tell about the size of the graph? And is there anything special when it comes to the initialization parameters?

You can easily test many of these parameters through OpenQAOA workflow setters:

Can you find a combination of QAOA Parameters that gives you the best result for any random graph?

**OPTIONAL. Study the Graph and the Solution**¶

Andrew Lukas paper says that given `k`

colors and `N`

vertices it takes `nN`

qubits to encode the problem. Without saturating your RAM, do you think you can play around with different graph topologies and colouring schemes?

Maybe try to plot a scaling of the performance of the algorithm as a function of changing graph properties (e.g. edge connectivity).

**Extras**¶

In the eventuality that you have had the time to explore QAOA and the graph colouring problem, here are a few ideas to keep you entertained: