-
Notifications
You must be signed in to change notification settings - Fork 0
/
k_n-grover-vs-classical-demo.py
157 lines (106 loc) · 3.12 KB
/
k_n-grover-vs-classical-demo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# ---
# jupyter:
# jupytext:
# formats: ipynb,py:light
# text_representation:
# extension: .py
# format_name: light
# format_version: '1.5'
# jupytext_version: 1.7.1
# kernelspec:
# display_name: Python 3
# language: python
# name: python3
# ---
# # Grover's on $K_n$
#
# Create a complete graph, delete some of the edges, and juxtapose the computations.
# ## Imports
# Import our custom framework first
from graph_utils import groversearch, naivesearch, evaluators
# Misc imports
# +
from qiskit.tools.visualization import plot_histogram
from time import time
import matplotlib.pyplot as plt
import networkx as nx
import itertools
import random
import math
import scipy
# %matplotlib inline
# -
# ## Graph Creation
# Set $n$ = $v$ = The number of vertices
n = int(input('Enter the value for n (# of vertices): '))
# Generate a complete graph...
edge_set = list(itertools.combinations(range(n), 2))
# ...and visualize it
# +
graph = nx.Graph()
graph.add_edges_from(edge_set)
fig = plt.figure()
ax = plt.axes()
nx.draw_networkx(graph, ax=ax)
# -
# ### (Optional) Delete a subset of the edges to make the problem harder
del_perc = float(input('Percentage of edges to delete: ')) / 100
# Delete the edges...
# +
for _ in range(int(del_perc * len(edge_set))):
random_edge = random.choice(edge_set)
edge_set.remove(random_edge)
len(edge_set)
# -
# ...and revisualize it
# +
graph = nx.Graph()
graph.add_edges_from(edge_set)
fig = plt.figure()
ax = plt.axes()
nx.draw_networkx(graph, ax=ax)
# -
# ## Report Constants
print("""
Vertices: {}
Edges: {}
Total Combinations: {}""".format(n, len(edge_set),
math.comb(len(edge_set), n)))
# ## Compare the two solutions
# ### Naive search
evlr = evaluators.HamiltonianEvaluator(edge_set)
# Recall that the naive search is simply going through all of the edge subsets and running the Hamiltonian cycle test.
# +
start = time()
truth_table = evlr.generate_truth_table()
end = time()
print('It took {:.8f}s for the naive search'.format(end - start))
# -
# Find out how many hamiltonian cycles there are and print them out
# +
combinations = []
ham_cycles = []
for i, (comb, is_ham) in enumerate(truth_table.items()):
combinations.append(comb)
if is_ham:
ham_cycles.append(i)
print('There are {} total hamiltonian cycles: \n'.format(len(ham_cycles)))
for i in ham_cycles:
print(combinations[i])
# -
# ### Grover's Search
# Compute the min number of shots
shots = math.ceil(math.sqrt(len(combinations)))
shots #= 1024
# Data preprocessing for qiskit
truth_map = groversearch.get_truth_map(truth_table)
# Run Grovers
result = groversearch.call_grover(truth_map, len(evlr.vertices),
shots=shots)
# Visualize the results
plot_histogram(result['measurement'], title='Possible Hamiltonian Cycles\n for $K_{}$'.format(n))
# ## Binary2EdgeSet
bin2edgeset = lambda bin_combo: combinations[int(str(bin_combo), 2)]
binary = input('Enter the binary representation: ')
print(bin2edgeset(binary))
print('Is hamiltonian?: {}'.format(truth_table[bin2edgeset(binary)]))