Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quantum-kittens
GitHub Repository: quantum-kittens/platypus
Path: blob/main/notebooks/ch-paper-implementations/tsp.ipynb
3855 views
Kernel: Python 3

Travelling Salesman Problem using Quantum Phase Estimation

Introduction

What is the Travelling Salesman Problem ?

The Travelling Salesman Problem belongs to the class of NP-Hard problems in combinatorial optimization. The problem is:

"Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city exactly once and returns to the origin city?"

The similar Hamiltonian cycle problem is:

"The cycle of visiting each vertex once in a graph, and returning to the starting vertex is known as a Hamiltonian cycle. Given a graph, determine whether it contains a Hamiltonian cycle or not."

The Hamiltonian cycle problem is NP-Hard. The Hamiltonian cycle problem can be converted to the Travelling Salesman Problem.

This looks a lot similar to the TSP. Actually, the Hamiltonian cycle is at the heart of the TSP. That's why these 2 problems are interconnected and solving one will solve the other.

What is the time complexity of it ?

Multiple techniques are used to solve this problem:

  1. Brute Force Method: Find every possible combination of all the vertices. O(n !) where n = Number of vertex/nodes of the graph O(n\ !)\ \text{where n = Number of vertex/nodes of the graph}

  2. Dynamic Programming: Break the problem into smaller problems, compute those smaller problems and whenever needed use the result of those small problems, instead of computing same chunk over and over. O(n22n) where n = Number of vertex/nodes of the graph O(n^22^n)\ \text{where n = Number of vertex/nodes of the graph}

  3. Branch and Bound: Branch and Bound refers to all the state space search methods in which we generate the childern of all the expanded nodes, before making any live node an expanded one. In this method, we find the most promising node and expand it. The term "promising node" means "choosing a node that can expand and give us an optimal solution". We start from the root and expand the tree until we approach an optimal (minimum cost in case of this problem) solution. O(n22n) where n = Number of vertex/nodes of the graph O(n^22^n)\ \text{where n = Number of vertex/nodes of the graph}

  4. Heuristic Approach: Heuristic approaches are based on providing a set of rules on optimal selection of next city to travel. But this does not give optimal solution in every case as heuristics result in approximations.

Why is brute force not a good idea ?

The time complexity of TSP using brute force technique is O(n !) where n = number of nodesO(n\ !)\ \text{where n = number of nodes}. Now imagine using n = 10n\ =\ 10, then we will get 10 ! = 36,28,0010\ !\ =\ 36,28,00, which has 66 digits. Now imagine 20 ! = 24,32,90,20,08,17,66,40,00020\ !\ =\ 24,32,90,20,08,17,66,40,000, which has 1919 digits. Now imagine 100 ! = ....100\ !\ =\ ...., it has 158 digits so on. So, as the no. of nodes increases, the time complexity increases exponentially. So, using brute force is not an optimal way to solve TSP.

Why is it important ?

The Travelling salesman problem is very important in theoretical computer science and operational research. Every scientist trying to find an algorithm which can solve it in polynomial time. The reason of this importance is not specifically TSP, but instead the class to which TSP belongs to. Its the NP class. If we can find an algorithm for TSP, it will open an wide range of possibilitis for the thousands of other problems which belongs to the same class. The travelling purchaser problem and the vehicle routing problem are both generalizations of TSP.

Why are quantum computers used to approach this problem instead of classical computers?

Recently, quantum computers are being used to approach these kinds of problems using various techniques, even though we have supercomputers all over the world. It's beacuse of the fact of what a quantum computer can do over classical computer, using the wierdness of quantum mechanics and all the different properties which only a quantum computer can possess/provide and using algorithm developed for quantum computer over the years. Even though after using quantum computer, it doesn't guarantee it will solve the problem. But it's a new way to aproach these kinds of class problems.

Some of these techniques involve quantum heuristic algorithms, generalizing Grover Search, Bounded-degree graphs, QAOA etc.

Approach

Lets consider the whole problem in terms of graphs. The cities are represented as vertices, and the cost/path as edges.

  • We approach the problem by encoding the given distances/cost between the cities as phases.

  • Each city is connected to other cities with a specific cost associated to each connection.

  • We construct unitary operators whose eigenvectors are the computational basis states and eigenvalues are various combinations of these phases.

  • Then we apply phase estimation algorithm to certain eigenstates which gives us all the total distances possible for all the routes.

  • After obtaining the distances we can search through this information using the quantum search algorithm for finding the minimum to find the least possible distance as well the route taken.

  • This provides us a quadratic speedup over the classical brute force method for a large number of cities.

General Strategy

So, now that we have gone through the general approach, we have an idea of what to do. Now let's explain step by step:

  • Lets consider the travelling salesman problem as an undirected complete graph, whose vertices represent cities and whose edges represent cost/distance.

  • Before going any further, lets consider the case where the number of cities/nodes n = 4n\ =\ 4.

# Building the graph with nodes = 4 import networkx as nx import matplotlib.pyplot as plt G = nx.DiGraph(directed=True) G.add_node(1) G.add_node(2) G.add_node(3) G.add_node(4) G.add_edge(1, 2) G.add_edge(1, 3) G.add_edge(1, 4) G.add_edge(2, 1) G.add_edge(2, 3) G.add_edge(2, 4) G.add_edge(3, 1) G.add_edge(3, 2) G.add_edge(3, 4) G.add_edge(4, 1) G.add_edge(4, 2) G.add_edge(4, 3) pos = {1: [0.75, 1.0], 2: [0.75, 0.15], 3: [0.5, -0.5], 4: [1.0, -0.5]} edge_labels = {(1, 2): '$\\phi_{2\\to 1}$\n $\\phi_{1\\to 2}$', (1, 3): '$\\phi_{1\\to 3}$\n $\\phi_{3\\to 1}$', (1, 4): '$\\phi_{4\\to 1}$\n $\\phi_{1\\to 4}$', (2, 3): '$\\phi_{2\\to 3}$\n $\\phi_{3\\to 2}$', (2, 4): '$\\phi_{4\\to 2}$\n $\\phi_{2\\to 4}$', (3, 4): '$\\phi_{4\\to 3}$\n $\\phi_{3\\to 4}$' } fig = plt.figure(1, figsize=(14, 10)) nx.draw(G, with_labels=True, node_color='skyblue', edge_cmap=plt.cm.Blues, pos=pos, connectionstyle='arc3, rad = 0.2', node_size=3000, arrowsize=14, arrowstyle='simple', font_size=30) nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=20, bbox=dict(alpha=0)) plt.show()
Image in a Jupyter notebook
  • We encode the given distance/cost as phases(ϕ\phi). $$ \phi_{i\to j}\ \text{means cost encoded as phase from city 'i' to city 'j', where i,j $\inParseError: KaTeX parse error: Expected 'EOF', got '}' at position 7: [1,n]}̲ Forexample: For example: \phi_{1\to 2}meansfromcity/node1tocity/node2. means from city/node '1' to city/node '2'. \phi_{2\to 3}meansfromcity/node2tocity/node3soon.Incaseofselfloopi.e means from city/node '2' to city/node '3' so on. In case of self-loop i.e \phi_{i\to i}$ the cost is '0'.

  • The classical brute force method uses an n×nn\times n matrix to store the distance/cost between each pair of nodes. A = [ϕ11ϕ12ϕ13ϕ14ϕ21ϕ22ϕ23ϕ24ϕ31ϕ32ϕ33ϕ34ϕ41ϕ42ϕ43ϕ44] A\ =\ \begin{bmatrix} \phi_{1\to 1}&\phi_{1\to 2}&\phi_{1\to 3}&\phi_{1\to 4}\\ \phi_{2\to 1}&\phi_{2\to 2}&\phi_{2\to 3}&\phi_{2\to 4}\\ \phi_{3\to 1}&\phi_{3\to 2}&\phi_{3\to 3}&\phi_{3\to 4}\\ \phi_{4\to 1}&\phi_{4\to 2}&\phi_{4\to 3}&\phi_{4\to 4}\\ \end{bmatrix}

Note that all the diagonal elements in this matrix A\text{A} are '0'.

But on representing this matrix as only phases:

  1. The matrix made of the given distances using the above procedure is not unitary in general, which means the implementation and manipulation of this operator is not possible on a quantum computer.

  2. The phases will get added when we multiply them or take tensor products of states with these phases as coefficients, that is the distances will get added as phases which is required for the search.

So, we represent the matrix as: B = [eiϕ11eiϕ12eiϕ13eiϕ14eiϕ21eiϕ22eiϕ23eiϕ24eiϕ31eiϕ32eiϕ33eiϕ34eiϕ41eiϕ42eiϕ43eiϕ44] B\ =\ \begin{bmatrix} e^{i\phi_{1\to 1}} & e^{i\phi_{1\to 2}} & e^{i\phi_{1\to 3}} & e^{i\phi_{1\to 4}}\\ e^{i\phi_{2\to 1}} & e^{i\phi_{2\to 2}} & e^{i\phi_{2\to 3}} & e^{i\phi_{2\to 4}}\\ e^{i\phi_{3\to 1}} & e^{i\phi_{3\to 2}} & e^{i\phi_{3\to 3}} & e^{i\phi_{3\to 4}}\\ e^{i\phi_{4\to 1}} & e^{i\phi_{4\to 2}} & e^{i\phi_{4\to 3}} & e^{i\phi_{4\to 4}}\\ \end{bmatrix}

Here, all the diagonal elements of this matrix B\text{B} are '1'.

For unitary matrices:

  • Now we will construct a unitary matrix (UU) from the matrix BB for each city/node for the phase estimation as: $$ U_{j}\ =\ (\sum_{i=1}^{n}B[j][i]\ \times\ \text{outer product of all possible basis vectors})\ \text{where j, i ≥ 0 and j, i $\inParseError: KaTeX parse error: Expected 'EOF', got '}' at position 8: [1, n]}̲. Therestoftheelementsinthematrix The rest of the elements in the matrix U_{j}aresettozero.Basically, are set to zero. Basically, U_{j}isadiagonalunitarymatrixconstructedfromeachofthecolumnsofmatrix is a diagonal unitary matrix constructed from each of the columns of matrix B$.

Lets construct the unitarie for j = 1, 2, 3, & 4:

  1. U1U_{1}: eiϕ110000+eiϕ210101+eiϕ311010+eiϕ411111e^{i\phi_{1\to 1}}|00\rangle\langle00| + e^{i\phi_{2\to 1}}|01\rangle\langle01| + e^{i\phi_{3\to 1}}|10\rangle\langle10| + e^{i\phi_{4\to 1}}|11\rangle\langle11|

In quantum computing, we can write our matrices in terms of basis vectors. For more info refer to Qiskit Textbook Single Qubit Gates

UjU_{j} are diagonal unitary matrices. It will be n×n (here, 4×4)n\times n\ (\text{here},\ 4\times4) matrices. And these matrics are expressed in terms of basis vectors with the phases as coefficients.

Now, lets break down U1U_{1} part by part to see what's happening. Ultimately we have to make sure UjU_{j} is a diagonal unitary matrix:

aaaa|aa\rangle\langle aa|, gives the position of the coefficient in the diagonal elements of the 4×44\times4 matrix. 0000 = ([10][10])  ([10][10])= ([1000][1000])= [1000000000000000] |00\rangle\langle00|\ =\ (\begin{bmatrix}1\\0\end{bmatrix}\otimes\begin{bmatrix}1\\0\end{bmatrix})\ \otimes\ (\begin{bmatrix}1&0\end{bmatrix}\otimes\begin{bmatrix}1&0\end{bmatrix}) =\ (\begin{bmatrix}1\\0\\0\\0\end{bmatrix}\otimes\begin{bmatrix}1&0&0&0\end{bmatrix}) =\ \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}

Similarly, we can find for 0101|01\rangle\langle01|, 1010|10\rangle\langle10|, 1111|11\rangle\langle11| (click to expand) 0101 = ([10][01])  ([10][01])= ([0100][0100])= [0000010000000000] |01\rangle\langle01|\ =\ (\begin{bmatrix}1\\0\end{bmatrix}\otimes\begin{bmatrix}0\\1\end{bmatrix})\ \otimes\ (\begin{bmatrix}1&0\end{bmatrix}\otimes\begin{bmatrix}0&1\end{bmatrix}) =\ (\begin{bmatrix}0\\1\\0\\0\end{bmatrix}\otimes\begin{bmatrix}0&1&0&0\end{bmatrix}) =\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix} 1010 = ([01][10])  ([01][10])= ([0010][0010])= [0000000000100000] |10\rangle\langle10|\ =\ (\begin{bmatrix}0\\1\end{bmatrix}\otimes\begin{bmatrix}1\\0\end{bmatrix})\ \otimes\ (\begin{bmatrix}0&1\end{bmatrix}\otimes\begin{bmatrix}1&0\end{bmatrix}) =\ (\begin{bmatrix}0\\0\\1\\0\end{bmatrix}\otimes\begin{bmatrix}0&0&1&0\end{bmatrix}) =\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix} 1111 = ([01][01])  ([11][01])= ([0001][0001])= [0000000000000001] |11\rangle\langle11|\ =\ (\begin{bmatrix}0\\1\end{bmatrix}\otimes\begin{bmatrix}0\\1\end{bmatrix})\ \otimes\ (\begin{bmatrix}1&1\end{bmatrix}\otimes\begin{bmatrix}0&1\end{bmatrix}) =\ (\begin{bmatrix}0\\0\\0\\1\end{bmatrix}\otimes\begin{bmatrix}0&0&0&1\end{bmatrix}) =\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

For more info refer to Qiskit Textbook Density Matrix

Next, we multiply these matrices with the phases as coefficients: eiϕ110000 = [eiϕ11000000000000000] e^{i\phi_{1\to1}}|00\rangle\langle00|\ =\ \begin{bmatrix} e^{i\phi_{1\to1}} & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}

Same operation will be done for eiϕ210101e^{i\phi_{2\to1}}|01\rangle\langle01|, eiϕ311010e^{i\phi_{3\to1}}|10\rangle\langle10|, eiϕ411111e^{i\phi_{4\to1}}|11\rangle\langle11| eiϕ210101 = [00000eiϕ210000000000] e^{i\phi_{2\to1}}|01\rangle\langle01|\ =\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & e^{i\phi_{2\to1}} & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix} eiϕ311010 = [0000000000eiϕ3100000] e^{i\phi_{3\to1}}|10\rangle\langle10|\ =\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & e^{i\phi_{3\to1}} & 0\\ 0 & 0 & 0 & 0 \end{bmatrix} eiϕ411111 = [000000000000000eiϕ41] e^{i\phi_{4\to1}}|11\rangle\langle11|\ =\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & e^{i\phi_{4\to1}} \end{bmatrix}

Then, adding them all up: U1=eiϕ110000+eiϕ210101+eiϕ311010+eiϕ411111=[eiϕ11000000000000000] +[00000eiϕ210000000000] +[0000000000eiϕ3100000]+[000000000000000eiϕ41]=[eiϕ110000eiϕ210000eiϕ310000eiϕ41] \begin{aligned} U_{1} &= e^{i\phi_{1\to1}}|00\rangle\langle00| + e^{i\phi_{2\to1}}|01\rangle\langle01| + e^{i\phi_{3\to1}}|10\rangle\langle10| + e^{i\phi_{4\to1}}|11\rangle\langle11|\\ &= \begin{bmatrix} e^{i\phi_{1\to1}} & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ + \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & e^{i\phi_{2\to1}} & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ + \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & e^{i\phi_{3\to1}} & 0\\ 0 & 0 & 0 & 0 \end{bmatrix} + \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & e^{i\phi_{4\to1}} \end{bmatrix}\\ & = \begin{bmatrix} e^{i\phi_{1\to1}} & 0 & 0 & 0\\ 0 & e^{i\phi_{2\to1}} & 0 & 0\\ 0 & 0 & e^{i\phi_{3\to1}} & 0\\ 0 & 0 & 0 & e^{i\phi_{4\to1}} \end{bmatrix}\\ \end{aligned}

In similar way, we have to find $U_{2},\ U_{3},\ U_{4}$
  1. U2U_{2}: eiϕ120000+eiϕ220101+eiϕ321010+eiϕ421111e^{i\phi_{1\to 2}}|00\rangle\langle00| + e^{i\phi_{2\to 2}}|01\rangle\langle01| + e^{i\phi_{3\to 2}}|10\rangle\langle10| + e^{i\phi_{4\to 2}}|11\rangle\langle11| [eiϕ12000000000000000] + [00000eiϕ220000000000] + [0000000000eiϕ3200000] + [000000000000000eiϕ42] = [eiϕ120000eiϕ220000eiϕ320000eiϕ42] \begin{bmatrix} e^{i\phi_{1\to2}} & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ +\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & e^{i\phi_{2\to2}} & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ +\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & e^{i\phi_{3\to2}} & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ +\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & e^{i\phi_{4\to2}} \end{bmatrix}\ =\ \begin{bmatrix} e^{i\phi_{1\to2}} & 0 & 0 & 0\\ 0 & e^{i\phi_{2\to2}} & 0 & 0\\ 0 & 0 & e^{i\phi_{3\to2}} & 0\\ 0 & 0 & 0 & e^{i\phi_{4\to2}} \end{bmatrix}

  2. U3U_{3}: eiϕ130000+eiϕ230101+eiϕ331010+eiϕ431111e^{i\phi_{1\to 3}}|00\rangle\langle00| + e^{i\phi_{2\to 3}}|01\rangle\langle01| + e^{i\phi_{3\to 3}}|10\rangle\langle10| + e^{i\phi_{4\to 3}}|11\rangle\langle11| [eiϕ13000000000000000] + [00000eiϕ230000000000] + [0000000000eiϕ3300000] + [000000000000000eiϕ43] = [eiϕ130000eiϕ230000eiϕ330000eiϕ43] \begin{bmatrix} e^{i\phi_{1\to3}} & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ +\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & e^{i\phi_{2\to3}} & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ +\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & e^{i\phi_{3\to3}} & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ +\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & e^{i\phi_{4\to3}} \end{bmatrix}\ =\ \begin{bmatrix} e^{i\phi_{1\to3}} & 0 & 0 & 0\\ 0 & e^{i\phi_{2\to3}} & 0 & 0\\ 0 & 0 & e^{i\phi_{3\to3}} & 0\\ 0 & 0 & 0 & e^{i\phi_{4\to3}} \end{bmatrix}

  3. U4U_{4}: eiϕ140000+eiϕ240101+eiϕ341010+eiϕ441111e^{i\phi_{1\to 4}}|00\rangle\langle00| + e^{i\phi_{2\to 4}}|01\rangle\langle01| + e^{i\phi_{3\to 4}}|10\rangle\langle10| + e^{i\phi_{4\to 4}}|11\rangle\langle11| [eiϕ14000000000000000] + [00000eiϕ240000000000] + [0000000000eiϕ3400000] + [000000000000000eiϕ44] = [eiϕ140000eiϕ240000eiϕ340000eiϕ44] \begin{bmatrix} e^{i\phi_{1\to4}} & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ +\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & e^{i\phi_{2\to4}} & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ +\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & e^{i\phi_{3\to4}} & 0\\ 0 & 0 & 0 & 0 \end{bmatrix}\ +\ \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & e^{i\phi_{4\to4}} \end{bmatrix}\ =\ \begin{bmatrix} e^{i\phi_{1\to4}} & 0 & 0 & 0\\ 0 & e^{i\phi_{2\to4}} & 0 & 0\\ 0 & 0 & e^{i\phi_{3\to4}} & 0\\ 0 & 0 & 0 & e^{i\phi_{4\to4}} \end{bmatrix}

  • Now we see all the unitaries are of same form. So, lets generalize it: Uj = [eia0000eib0000eic0000eid] U_{j}\ =\ \begin{bmatrix} e^{ia} & 0 & 0 & 0\\ 0 & e^{ib} & 0 & 0\\ 0 & 0 & e^{ic} & 0\\ 0 & 0 & 0 & e^{id} \end{bmatrix} Putting a, b, c, da,\ b,\ c,\ d different phases, will give U1, U2, U3, U4U_{1},\ U_{2},\ U_{3},\ U_{4}.

  • The quantum phase estimation algorithm uses phase kickback to write the phase of UU(in the Fourier basis) to the tt qubits. When we use a qubit to control the UU gate, the qubit will turn (due to kickback) proportionally to the phase e2iπθe^{2iπθ}. We need to introduce the controlled unitary CUC−U that applies the unitary operator UU on the target register only if its corresponding control bit is 1|1\rangle. For quantum phase estimation, we need controlled unitaries, so, we need to decompose these unitaries as controlled unitaries. We need to convert U1, U2, U3, U4U_{1},\ U_{2},\ U_{3},\ U_{4} to CU1, CU2, CU3, CU4CU_{1},\ CU_{2},\ CU_{3},\ CU_{4} respectively. Uj = [eia0000eib0000eic0000eid]= ([100ei(ca)]  [eia00eib]) . [100001000010000ei(dc+ab)]= [eia0000eib0000eic0000eid] \begin{aligned} U_{j}\ &=\ \begin{bmatrix} e^{ia} & 0 & 0 & 0\\ 0 & e^{ib} & 0 & 0\\ 0 & 0 & e^{ic} & 0\\ 0 & 0 & 0 & e^{id} \end{bmatrix}\\ &=\ \left(\begin{bmatrix} 1 & 0\\ 0 & e^{i(c-a)} \end{bmatrix}\ \otimes\ \begin{bmatrix} e^{ia} & 0\\ 0 & e^{ib} \end{bmatrix}\right)\ .\ \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & e^{i(d-c+a-b)} \end{bmatrix}\\ &=\ \begin{bmatrix} e^{ia} & 0 & 0 & 0\\ 0 & e^{ib} & 0 & 0\\ 0 & 0 & e^{ic} & 0\\ 0 & 0 & 0 & e^{id} \end{bmatrix}\\ \end{aligned}

  • Finally, we need to find the tensor products of all the unitaries to find the overall unitary.

U = U1  U2  U3  U4.U\ =\ U_{1}\ \otimes\ U_{2}\ \otimes\ U_{3}\ \otimes\ U_{4}.

But as we discussed earlier, we need controlledU\text{controlled}-U for the phase estimation. CU  C (U1  U2  U3  U4)  CU1  CU2  CU3  CU4. CU\ \equiv\ C\ (U_{1}\ \otimes\ U_{2}\ \otimes\ U_{3}\ \otimes\ U_{4})\ \equiv\ CU_{1}\ \otimes\ CU_{2}\ \otimes\ CU_{3}\ \otimes\ CU_{4}. The eigenvalues of this unitary matrix UU, are estimated using the quantum phase estimation algorithm. The phases can be easily normalized to be bound within 0\text{0} and \text{2π} once we know the range of distances between the cities which is given to us in the problem. Here, UU is a diagonal matrix since it is a tensor product of nn diagonal matrices. This means that the eigenstates of this matrix UU are computational basis states with eigenvalues as the corresponding diagonal elements.

NOTE: The quantum phase estimation algorithm (also referred to as quantum eigenvalue estimation) can be used to estimate the eigenvalue (or phase) of an eigenvector of a unitary operator. For more information on quantum phase estimation, check the Quantum Phase Estimation qiskit textbook page.

For eigenstates:

Now that we have developed the unitary matrix, let's analyze it.

  • UU is diagonal matrix, since UU is the tensor product of diagonal matrices. So, out of nnn^n elements in UU, only the (n1) ⁣(n-1)\! contain length of all distinct possible Hamiltonian cycles in TSP. Each eigenvector is represented as distinct Hamiltonian cycle. So, (n1) !(n-1)\ ! eigenstates are possible of UU with eigenvalues being the total cost of the corresponding Hamiltonian cycle as phase. We estimate the phase corresponding to the route going through cities in some order and coming to the starting state. The eigenstates are represented in binary form to convert the city to computational basis vectors using a function- ψ = ji(j)1 where j  [1..n] |\psi\rangle\ =\ \otimes_{j}|i(j)−1\rangle\ where\ j\ \in\ [1..n] where the function i(j)i(j) says- From which city we travelled to city jj ?

Lets analyze these concepts with our 4 city model-

  • Our U1, U2, U3, U4U_{1},\ U_{2},\ U_{3},\ U_{4} is a 4×44\times4 matrices. So, taking the tensor product of all (=U=U) will give total elements in UU as 44 = 2564^4\ =\ 256. Out of these 256256 elements, only the diagonals elements are non-zero.

  • The number of distinct Hamiltonian cycle in our 4 city model = (n1) !(n-1)\ ! = (41) !(4-1)\ ! = 3 !3\ ! = 6. And so, the no. of eigenstates is 6.

  • Lets see how the eigenstates are calculated:

With 4 cities taken, the total combination of all possible Hamiltonian cycle is n ⁣ = 4 ! = 4×3×2×1 = 24n\!\ =\ 4\ !\ =\ 4\times3\times2\times1\ =\ 24. Out of this 2424, 66 are distinct Hamiltonian cycle.

Now, what do we mean by distinct?

Well lets take the following paths, 12342341341241231-2-3-4 \to 2-3-4-1 \to 3-4-1-2 \to 4-1-2-3. If we can observe carefully we can see- 23412-3-4-1 is just the left rotation of 12341-2-3-4, that is if we rotate 12341-2-3-4 by 1, it wll become 23412-3-4-1. Similarly, if we rotate 23412-3-4-1 by 1 we get 34123-4-1-2, and again rotate by 1 we get 41234-1-2-3. So 23412-3-4-1, 34123-4-1-2, 41234-1-2-3 are just the circular permutation version of 12341-2-3-4. And most importantly the reason we are neglecting is because all 3 will provide the same cost as 12341-2-3-4.

Out of all possible combinations, pick the one which on circular permutation will give other combination.

We are taking the first 66 states, since these states on different circular permutations will give all the states:

Possible States
12341-2-3-4
12431-2-4-3
14231-4-2-3
14321-4-3-2
13241-3-2-4
13421-3-4-2

These 66 distinct Hamiltonian cycles are not unique. We can also take one of the results of circular permutations in place of that. So, in place of 12341-2-3-4 we can also take 23412-3-4-1, as we saw above it is one of the circular permuatations of 12341-2-3-4.

If the cost of travelling from city ii to city jj is same cost as travelling from city jj to city ii, then the number of distinct Hamiltonian cycle is (n1) !2\frac{(n-1)\ !}{2}. So, in 12341-2-3-4 and 12431-2-4-3, the cost of travelling from city 33 to city 44 is same as travelling from city 44 to city 33. So, 12341-2-3-4 and 12431-2-4-3 will produce the same total cost.

If the cost of travelling from city ii to city jj is not same cost as travelling from city jj to city ii, then the number of distinct Hamiltonian cycle is (n1) !(n-1)\ !. In our city model, it will be 33.

  • Now, lets see how the eigenstates are calculated from a sequence of paths. Let's recall our function i(j)i(j), which states from which city we travelled to city jj, to convert into binary form:

ψ = ji(j)1 where j in [1..n]|\psi\rangle\ =\ \otimes_{j}|i(j)−1\rangle\ \text{where j in [1..n]}

So, lets take an example say 12341-2-3-4: i(1) = 4 i(1)\ =\ 4 means from city 4 we travelled to city 1. So, we need to convert it to binary form for the computational basis states. According to the formula- i(1)1 = 41 = 310 = 112 |i(1)-1\rangle\ =\ |4-1\rangle\ =\ |3_{10}\rangle\ =\ |11_{2}\rangle

Similarly, we have to do for all the city in the sequence: i(2)1 = 11 = 010 = 002 |i(2)-1\rangle\ =\ |1-1\rangle\ =\ |0_{10}\rangle\ =\ |00_{2}\rangle i(3)1 = 21 = 110 = 012 |i(3)-1\rangle\ =\ |2-1\rangle\ =\ |1_{10}\rangle\ =\ |01_{2}\rangle i(4)1 = 31 = 210 = 102 |i(4)-1\rangle\ =\ |3-1\rangle\ =\ |2_{10}\rangle\ =\ |10_{2}\rangle

Finally taking tensor product of all: 11  00  01  10 = 11000110 |11\rangle\ \otimes\ |00\rangle\ \otimes\ |01\rangle\ \otimes\ |10\rangle\ =\ |11000110\rangle We found the eigenstates in binary form.

For 12431-2-4-3: i(1)1 = 31 = 210 = 102 |i(1)-1\rangle\ =\ |3-1\rangle\ =\ |2_{10}\rangle\ =\ |10_{2}\rangle i(2)1 = 11 = 010 = 002 |i(2)-1\rangle\ =\ |1-1\rangle\ =\ |0_{10}\rangle\ =\ |00_{2}\rangle i(4)1 = 21 = 110 = 012 |i(4)-1\rangle\ =\ |2-1\rangle\ =\ |1_{10}\rangle\ =\ |01_{2}\rangle i(3)1 = 41 = 310 = 112 |i(3)-1\rangle\ =\ |4-1\rangle\ =\ |3_{10}\rangle\ =\ |11_{2}\rangle 10  00  01  11 = 10000111 |10\rangle\ \otimes\ |00\rangle\ \otimes\ |01\rangle\ \otimes\ |11\rangle\ =\ |10000111\rangle

Lets see all of them:

Sequence path Eigenstates
12341-2-3-4 11000110 |11000110\ \rangle
12431-2-4-3 10000111 |10000111\ \rangle
14231-4-2-3 10001101 |10001101\ \rangle
14321-4-3-2 01001110 |01001110\ \rangle
13241-3-2-4 11001001 |11001001\ \rangle
13421-3-4-2 01001011 |01001011\ \rangle

If we consider the cost is same from going and returning, there will be 33 sequence path out of 66. For example we can take any one of 12341-2-3-4 or 12431-2-4-3, since cost from 343-4 will be same as 434-3. So these 66 will reduce to:

Sequence path Eigenstates
12341-2-3-4 11000110 |11000110\ \rangle
14231-4-2-3 10001101 |10001101\ \rangle
13241-3-2-4 11001001 |11001001\ \rangle

Building the Components

Now we have gone through all the theory, lets build it part by part:

For the Unitaries:

Building the unitary UU is the crucial part of quantum phase estimation. Building the UU, means building CU1, CU2, CU3, CU4CU_{1},\ CU_{2},\ CU_{3},\ CU_{4}. Now if we remember we generalized UjU_{j} and decomposed it in terms of controlled-unitaries.

Uj = [eia0000eib0000eic0000eid] = ([100ei(ca)]  [eia00eib]) . [100001000010000ei(dc+ab)]U_{j}\ =\ \begin{bmatrix} e^{ia} & 0 & 0 & 0\\ 0 & e^{ib} & 0 & 0\\ 0 & 0 & e^{ic} & 0\\ 0 & 0 & 0 & e^{id} \end{bmatrix}\ =\ \left(\begin{bmatrix} 1 & 0\\ 0 & e^{i(c-a)} \end{bmatrix}\ \otimes\ \begin{bmatrix} e^{ia} & 0\\ 0 & e^{ib} \end{bmatrix}\right)\ .\ \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & e^{i(d-c+a-b)} \end{bmatrix}

In this matrix, [100ei(ca)]\begin{bmatrix}1 & 0 \\ 0 & e^{i(c-a)}\end{bmatrix} means an unitary gate U1(ca)U1(c-a). Similarly, [eia00eib]\begin{bmatrix}e^{ia} & 0 \\ 0 & e^{ib}\end{bmatrix} means an unitary gate U1(ba)U1(b-a) when we factor out the global phase eiae^{ia} from it and make it a unitary U(a)U(a). The matrix [100001000010000ei(dc+ab)]\begin{bmatrix}1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & e^{i(d-c+a-b)}\end{bmatrix} is a controlled unitary CU1(dc+ab)CU1(d-c+a-b).

NOTE: U1(λ)=P(λ)=[100eiλ]U1(\lambda) = P(\lambda) = \begin{bmatrix}1 & 0\\ 0 & e^{i\lambda}\end{bmatrix}. For more info see Phase Gate in Qiskit Textbook

But we need to make CUjC-U_{j}. For that, the matrix UU will change from a 4×44\times4 matrix to 8×88\times8 matrix.

UjCUj =[eia0000eib0000eic0000eid][100000000100000000100000000100000000eia00000000eib00000000eic00000000eid]U_{j} \to CU_{j}\ = \begin{bmatrix} e^{ia} & 0 & 0 & 0\\ 0 & e^{ib} & 0 & 0\\ 0 & 0 & e^{ic} & 0\\ 0 & 0 & 0 & e^{id} \end{bmatrix} \to \begin{bmatrix} 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 & e^{ia} & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & e^{ib} & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & e^{ic} & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & e^{id} \end{bmatrix}

So, when we are converting UjU_{j} to CUjC-U_{j}, we have to control everything in UjU_{j}. So U1(ca)U1(c-a) will become CU1(ca)CU1(c-a), U1(ba)U1(b-a) to CU1(ba)CU1(b-a), U1(a)U1(a) act as global phase, will be on the control qubit. And most importantly, CU1(dc+ab)CU1(d-c+a-b) will become controlled controlled U1(dc+ab)\text{controlled controlled}\ U1(d-c+a-b), i.e. CCU1(dc+ab)CCU1(d-c+a-b).

So, we can decompose any controlled controlled unitary by a series of unitary gates. By lemma 6.1[2]\text{lemma}\ 6.1^{[2]}: where VV is unitary.

Similarly, using this we can decompose controlled controlled U1(dc+ab)\text{controlled controlled}\ U1(d-c+a-b). The UU in the image will be U1(dc+ab)U1(d-c+a-b), the VV will be U1(dc+ab)U1(d-c+a-b) and VV^{\dagger} will be U1((dc+ab))U1(-(d-c+a-b)).

Lets analyze this CCU1(dc+ab)CCU1(d-c+a-b) using a test circuit

# Lets import all the necessary libraries from qiskit import QuantumCircuit, Aer, QuantumRegister, ClassicalRegister, execute from qiskit.visualization import plot_histogram, array_to_latex from qiskit.circuit.library import QFT from numpy import pi
at = 0 bt = pi/2 ct = pi/8 dt = pi/4 qt = QuantumRegister(3, 'qt') qct = QuantumCircuit(qt) qct.cp(ct - at, qt[0], qt[1]) qct.p(at, qt[0]) qct.cp(bt - at, qt[0], qt[2]) qct.cp((dt - ct + at - bt)/2, qt[1], qt[2]) qct.cx(qt[0], qt[1]) qct.cp(-(dt - ct + at - bt)/2, qt[1], qt[2]) qct.cx(qt[0], qt[1]) qct.cp((dt - ct + at - bt)/2, qt[0], qt[2]) qct.draw()
Image in a Jupyter notebook

Unitary Simulator

backend_unitary_t = Aer.get_backend('unitary_simulator') job_unitary_t = execute(qct, backend_unitary_t, shots=8192) count_unitary_t = job_unitary_t.result().get_unitary() array_to_latex(count_unitary_t, prefix="\\text{Circuit = }\n")
$$\text{Circuit = } [1000000001000000001000000000.92388+0.38268i00000000100000000i0000000010000000012(1+i)]\begin{bmatrix} 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.92388 + 0.38268i & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & i & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & \tfrac{1}{\sqrt{2}}(1 + i) \\ \end{bmatrix}$$

See the unitary matrix we are getting above is not exactly like [100000000100000000100000000100000000eia00000000eib00000000eic00000000eid] \begin{bmatrix} 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 & e^{ia} & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & e^{ib} & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & e^{ic} & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & e^{id} \end{bmatrix} but kind of rearranged version of this. Though the matrix we are getting and the CUjCU_{j} matrix is mathematically same. This is because Qiskit interpret the tensor product from bottom qubit to top qubit. So to get exactly same form as the CUjCU_{j}, we have to make the circuit inverted.

Lets see the inverted circuit

ai = 0 bi = pi/2 ci = pi/8 di = pi/4 qi = QuantumRegister(3, 'qi') qci = QuantumCircuit(qi) qci.cp(ci - ai, qi[2], qi[1]) qci.p(ai, qi[2]) qci.cp(bi - ai, qi[2], qi[0]) qci.cp((di - ci + ai - bi)/2, qi[1], qi[0]) qci.cx(qi[2], qi[1]) qci.cp(-(di - ci + ai - bi)/2, qi[1], qi[0]) qci.cx(qi[2], qi[1]) qci.cp((di - ci + ai - bi)/2, qi[2], qi[0]) qci.draw()
Image in a Jupyter notebook

Unitary Simulator

backend_unitary_i = Aer.get_backend('unitary_simulator') job_unitary_i = execute(qci, backend_unitary_i, shots=8192) count_unitary_i = job_unitary_i.result().get_unitary() array_to_latex(count_unitary_i, prefix="\\text{Circuit = }\n")
$$\text{Circuit = } [100000000100000000100000000100000000100000000i000000000.92388+0.38268i0000000012(1+i)]\begin{bmatrix} 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 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & i & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0.92388 + 0.38268i & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & \tfrac{1}{\sqrt{2}}(1 + i) \\ \end{bmatrix}$$

Now this looks a lot like UjU_{j} matrix. So both the version, we just have to pay attention to QFT\text{QFT} part, depending on which version we used. For more info about QFT\text{QFT} and IQFT\text{IQFT}, refer to Qiskit Textbook QFT Page

Circuit

Now lets build the whole circuit part by part, by unitaries, and by eigenstates.

Creating a function to create CUjCU_{j}

def controlled_unitary(qc, qubits: list, phases: list): # x,y,z = Specific Qubit; a,b,c,d = Phases qc.cp(phases[2]-phases[0], qubits[0], qubits[1]) # controlled-U1(c-a) qc.p(phases[0], qubits[0]) # U1(a) qc.cp(phases[1]-phases[0], qubits[0], qubits[2]) # controlled-U1(b-a) # controlled controlled U1(d-c+a-b) qc.cp((phases[3]-phases[2]+phases[0]-phases[1])/2, qubits[1], qubits[2]) qc.cx(qubits[0], qubits[1]) qc.cp(-(phases[3]-phases[2]+phases[0]-phases[1])/2, qubits[1], qubits[2]) qc.cx(qubits[0], qubits[1]) qc.cp((phases[3]-phases[2]+phases[0]-phases[1])/2, qubits[0], qubits[2])

Now lets make the U = U1  U2  U3  U4U\ =\ U_{1}\ \otimes\ U_{2}\ \otimes\ U_{3}\ \otimes\ U_{4}

def U(times, qc, unit, eigen, phases: list): # a,b,c = phases for U1; d,e,f = phases for U2; g,h,i = phases for U3; j,k,l = phases for U4; m_list=[m, n, o, p, q, r, s, t, u, a, b, c, d, e, f, g, h, i, j, k, l] controlled_unitary(qc, [unit[0]]+eigen[0:2], [0]+phases[0:3]) controlled_unitary(qc, [unit[0]]+eigen[2:4], [phases[3]]+[0]+phases[4:6]) controlled_unitary(qc, [unit[0]]+eigen[4:6], phases[6:8]+[0]+[phases[8]]) controlled_unitary(qc, [unit[0]]+eigen[6:8], phases[9:12]+[0])

Now lets make final CUCU, CU2CU^{2}, CU4CU^{4}, CU8CU^{8}, CU16CU^{16}, CU32CU^{32}

def final_U(times, eigen, phases: list): unit = QuantumRegister(1, 'unit') qc = QuantumCircuit(unit, eigen) for _ in range(2**times): U(times, qc, unit, eigen, phases) return qc.to_gate(label='U'+'_'+(str(2**times)))

Lets consider all the phases:

The phases are normalized to be bound within [0, 2π][0,\ 2π] once we know the range of distances between the cities.

Phases Encoded as Phase value
ϕ11\phi_{1\to1} 0\text{0}
ϕ21\phi_{2\to1} a\text{a} π2\frac{\pi}{2}
ϕ31\phi_{3\to1} b\text{b} π8\frac{\pi}{8}
ϕ41\phi_{4\to1} c\text{c} π4\frac{\pi}{4}
-- -- --
ϕ12\phi_{1\to2} d\text{d} π2\frac{\pi}{2}
ϕ22\phi_{2\to2} 0\text{0}
ϕ32\phi_{3\to2} e\text{e} π4\frac{\pi}{4}
ϕ42\phi_{4\to2} f\text{f} π4\frac{\pi}{4}
-- -- --
ϕ13\phi_{1\to3} g\text{g} π8\frac{\pi}{8}
ϕ23\phi_{2\to3} h\text{h} π4\frac{\pi}{4}
ϕ33\phi_{3\to3} 0\text{0}
ϕ43\phi_{4\to3} i\text{i} π8\frac{\pi}{8}
-- -- --
ϕ14\phi_{1\to4} j\text{j} π4\frac{\pi}{4}
ϕ24\phi_{2\to4} k\text{k} π4\frac{\pi}{4}
ϕ34\phi_{3\to4} l\text{l} π8\frac{\pi}{8}
ϕ44\phi_{4\to4} 0\text{0}

Building the eigenstates

# Storing the eigenvalues in a list eigen_values = ["11000110", "10001101", "11001001"] # Function to place appropriate corresponding gate according to eigenstates def eigenstates(qc, eigen, index): for i in range(0, len(eigen)): if eigen_values[index][i] == '1': qc.x(eigen[i]) if eigen_values[index][i] == '0': pass qc.barrier() return qc

Building the circuit

# Initialization unit = QuantumRegister(6, 'unit') eigen = QuantumRegister(8, 'eigen') unit_classical = ClassicalRegister(6, 'unit_classical') qc = QuantumCircuit(unit, eigen, unit_classical) # # Setting one eigenstate # Playing with the first eigenstate here i.e. 11000110 from eigen_values list. # (Try to play with other eigenstates from the eigen_values list) eigenstates(qc, eigen, 0) # # Hadamard on the 'unit' qubits qc.h(unit[:]) qc.barrier() # # Controlled Unitary phases = [pi / 2, pi / 8, pi / 4, pi / 2, pi / 4, pi / 4, pi / 8, pi / 4, pi / 8, pi / 4, pi / 4, pi / 8] # a, b, c, d, e, f, g, h, i, j, k, l for i in range(0, 6): qc.append(final_U(i, eigen, phases), [unit[5-i]] + eigen[:]) # # Inverse QFT qc.barrier() qft = QFT(num_qubits=len(unit), inverse=True, insert_barriers=True, do_swaps=False, name='Inverse QFT') qc.append(qft, qc.qubits[:len(unit)]) qc.barrier() # # Measure qc.measure(unit, unit_classical) # # Draw qc.draw()
Image in a Jupyter notebook

QASM Simulator

backend = Aer.get_backend('qasm_simulator') job = execute(qc, backend, shots=8192) count = job.result().get_counts() print(count) plot_histogram(count)
{'100100': 8192}
Image in a Jupyter notebook

Conclusion

Firstly, this process is not complete yet. We only used the first eigenstates 11000110|11000110\rangle here, this process has to be done for all the eigenstates to find the total distance for all the route. After that, use quantum search algorithm to find the minimum of those distances. This means, the time required scales with the number of eigenstates.

Secondly, the paper[1]\text{paper}^{[1]} we took the reference for this has many mistakes for the circuit. We fixed it and used the improved version.

Thirdly, Now that we have went theough the theory, concept and build the circuit, lets discuss- Does using this process of quantum phase estimation to solve a problem of NP-Hard\text{NP-Hard} gives a algorithm/way to solve these kind of problems more efficiently and optimally or in other word Is this a perfect solution ? The answer is No. This process of using phase estimation, which encode the cost as phases is one of the many ways to solve these category of problems. But these approach is also not perfect. Perfect in the sense, it does not give any efficient algorithm to solve these (NP-Hard) problems in polynomial time. In this process, we find all the possible Hamiltonian cycle in the graph and based on those cycle we calculated the total cost. But, keep in mind, Finding all Hamiltonian cycle of a graph is itself a NP-Complete problem. So we gave precomputed Hamiltonian cycle in the beginning to get the eigenstates. We used 4\text{4} nodes/city, but for large number of cities say 10,000, finding all possible Hamiltonian cycle is tedious job.

References

This notebook/writing is based on:

Version Information

import qiskit.tools.jupyter %qiskit_version_table