You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

504 lines
14 KiB

6 years ago
6 years ago
5 years ago
6 years ago
5 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. #!/usr/bin/env python3
  2. from util import SAT2QUBO as s2q
  3. from util import randomSAT as rs
  4. from util import queries
  5. from util import graph
  6. import networkx as nx
  7. import dwave_networkx as dnx
  8. import minorminer
  9. from dwave_qbsolv import QBSolv
  10. import dimod
  11. import matplotlib.pyplot as plt
  12. import seaborn as sns
  13. import numpy as np
  14. import re
  15. def frange(start, stop, steps):
  16. while start < stop:
  17. yield start
  18. start += steps
  19. def test_kv_range():
  20. k = 75
  21. data = {
  22. "p_node_counts" : [],
  23. "wmis_node_counts" : [],
  24. "p_conn_counts" : [],
  25. "wmis_conn_counts" : [],
  26. "a_arr" : [],
  27. "k_arr" : []
  28. }
  29. target = dnx.chimera_graph(25, 25, 4)
  30. print(target.number_of_nodes())
  31. for r in range(2):
  32. #for k in range(50, 5001, 50):
  33. for a in frange(3.5, 5.5, 0.1):
  34. #v = int(k/4)
  35. #a = k/v
  36. v = int(k/a)
  37. print("k={} v={} k/v={}".format(k, v, k/v))
  38. ksatInstance = rs.generateRandomKSAT(k, v, 3)
  39. p_qubo = s2q.primitiveQUBO_5(ksatInstance)
  40. wmis_qubo = s2q.WMISdictQUBO(ksatInstance)
  41. qg = nx.Graph()
  42. for coupler, energy in wmis_qubo.items():
  43. if coupler[0] != coupler[1]:
  44. qg.add_edge(coupler[0], coupler[1], weight=energy)
  45. ig = nx.Graph()
  46. for coupler, energy in p_qubo.items():
  47. if coupler[0] != coupler[1]:
  48. ig.add_edge(coupler[0], coupler[1], weight=energy)
  49. qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True, threads=8)
  50. print("wmis emb. found: {}".format(qemb[1]))
  51. iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True, threads=8)
  52. print("primitive emb. found: {}".format(iemb[1]))
  53. if qemb[1] == 0 or iemb[1] == 0:
  54. print()
  55. continue
  56. p_node_count = 0;
  57. p_conn_count = 0;
  58. used_nodes = []
  59. for var, chain in iemb[0].items():
  60. used_nodes.extend(chain)
  61. p_node_count = len(np.unique(used_nodes))
  62. wmis_node_count = 0;
  63. wmis_conn_count = 0;
  64. used_nodes = []
  65. for var, chain in qemb[0].items():
  66. used_nodes.extend(chain)
  67. wmis_node_count = len(np.unique(used_nodes))
  68. #print("p_qubo: nodes={} connections={}".format(p_node_count, p_conn_count))
  69. #print("wmis_qubo: nodes={} connections={}".format(wmis_node_count, wmis_conn_count))
  70. print("p_qubo nodes= {}".format(p_node_count));
  71. print("wwmis qubo nodes= {}".format(wmis_node_count));
  72. print("nodes= {}".format(p_node_count / wmis_node_count));
  73. #print("conns= {}".format(p_conn_count / wmis_conn_count));
  74. data["p_node_counts"].append(p_node_count)
  75. data["wmis_node_counts"].append(wmis_node_count)
  76. data["p_conn_counts"].append(p_conn_count)
  77. data["wmis_conn_counts"].append(wmis_conn_count)
  78. data["a_arr"].append(k/v)
  79. data["k_arr"].append(k)
  80. print()
  81. sns.set()
  82. ax = sns.scatterplot(x="a_arr", y="p_node_counts", data=data, label="p_qubo")
  83. ax.set(xlabel='k/v', ylabel='used verticies after embedding')
  84. ax = sns.scatterplot(x="a_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo")
  85. plt.show()
  86. def test_k_range():
  87. k = 75
  88. data = {
  89. "p_node_counts" : [],
  90. "wmis_node_counts" : [],
  91. "p_conn_counts" : [],
  92. "wmis_conn_counts" : [],
  93. "a_arr" : [],
  94. "k_arr" : []
  95. }
  96. target = dnx.chimera_graph(25, 25, 4)
  97. print(target.number_of_nodes())
  98. for r in range(2):
  99. for k in range(15, 76, 1):
  100. v = int(k/4)
  101. print("k={} v={} k/v={}".format(k, v, k/v))
  102. ksatInstance = rs.generateRandomKSAT(k, v, 3)
  103. p_qubo = s2q.primitiveQUBO(ksatInstance)
  104. wmis_qubo = s2q.WMISdictQUBO(ksatInstance)
  105. qg = nx.Graph()
  106. for coupler, energy in wmis_qubo.items():
  107. if coupler[0] != coupler[1]:
  108. qg.add_edge(coupler[0], coupler[1], weight=energy)
  109. ig = nx.Graph()
  110. for coupler, energy in p_qubo.items():
  111. if coupler[0] != coupler[1]:
  112. ig.add_edge(coupler[0], coupler[1], weight=energy)
  113. qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True, threads=8)
  114. print("wmis emb. found: {}".format(qemb[1]))
  115. iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True, threads=8)
  116. print("primitive emb. found: {}".format(iemb[1]))
  117. if qemb[1] == 0 or iemb[1] == 0:
  118. print()
  119. continue
  120. p_node_count = 0;
  121. p_conn_count = 0;
  122. used_nodes = []
  123. for var, chain in iemb[0].items():
  124. used_nodes.extend(chain)
  125. p_node_count = len(np.unique(used_nodes))
  126. wmis_node_count = 0;
  127. wmis_conn_count = 0;
  128. used_nodes = []
  129. for var, chain in qemb[0].items():
  130. used_nodes.extend(chain)
  131. wmis_node_count = len(np.unique(used_nodes))
  132. #print("p_qubo: nodes={} connections={}".format(p_node_count, p_conn_count))
  133. #print("wmis_qubo: nodes={} connections={}".format(wmis_node_count, wmis_conn_count))
  134. print("p_qubo nodes= {}".format(p_node_count));
  135. print("wwmis qubo nodes= {}".format(wmis_node_count));
  136. print("nodes= {}".format(p_node_count / wmis_node_count));
  137. #print("conns= {}".format(p_conn_count / wmis_conn_count));
  138. data["p_node_counts"].append(p_node_count)
  139. data["wmis_node_counts"].append(wmis_node_count)
  140. data["p_conn_counts"].append(p_conn_count)
  141. data["wmis_conn_counts"].append(wmis_conn_count)
  142. data["a_arr"].append(k/v)
  143. data["k_arr"].append(k)
  144. print()
  145. sns.set()
  146. ax = sns.scatterplot(x="k_arr", y="p_node_counts", data=data, label="p_qubo")
  147. ax.set(xlabel='k',
  148. ylabel='used verticies after embedding')
  149. ax = sns.scatterplot(x="k_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo")
  150. plt.show()
  151. def medianChainLength(emb):
  152. chl = []
  153. for chain in emb.values():
  154. chl.append(len(chain))
  155. sns.distplot(chl)
  156. plt.show()
  157. return np.mean(chl)
  158. def test2():
  159. sat = rs.generateRandomKSAT(42, 10, 3)
  160. print(sat.toString())
  161. qubo = s2q.WMISdictQUBO(sat)
  162. #ising = s2q.primitiveQUBO_8(sat)
  163. ising = s2q.WMISdictQUBO_2(sat)
  164. qg = nx.Graph()
  165. for coupler, energy in qubo.items():
  166. if coupler[0] != coupler[1]:
  167. qg.add_edge(coupler[0], coupler[1], weight=energy)
  168. ig = nx.Graph()
  169. for coupler, energy in ising.items():
  170. if coupler[0] != coupler[1]:
  171. ig.add_edge(coupler[0], coupler[1], weight=energy)
  172. #plt.ion()
  173. print(qg.number_of_nodes(), qg.number_of_edges())
  174. print(ig.number_of_nodes(), ig.number_of_edges())
  175. target = dnx.chimera_graph(16, 16, 4)
  176. #nx.draw_shell(qg, with_labels=True, node_size=50)
  177. #nx.draw_shell(ig, with_labels=True, node_size=50)
  178. eg = ig
  179. emb = minorminer.find_embedding(eg.edges(), target.edges(), return_overlap=True,
  180. threads=8)
  181. print(emb[1])
  182. for node, chain in emb[0].items():
  183. print(node, chain)
  184. print("avrg chain length = {}".format(medianChainLength(emb[0])))
  185. dnx.draw_chimera_embedding(G=target, emb=emb[0], embedded_graph=eg, show_labels=True)
  186. plt.show()
  187. def test3():
  188. sat = rs.generateRandomKSAT(42, 10, 3)
  189. print(sat.toString())
  190. ising = s2q.primitiveQUBO(sat)
  191. h = {}
  192. J = {}
  193. for coupler, energy in ising.items():
  194. if coupler[0] == coupler[1]:
  195. h[coupler[0]] = energy
  196. else:
  197. J[coupler] = energy
  198. res = QBSolv().sample_ising(h, J, find_max=False)
  199. sample = list(res.samples())[0]
  200. extracted = {}
  201. r = re.compile("c\d+_l-?\d*")
  202. for label, assignment in sample.items():
  203. if r.fullmatch(label):
  204. extracted[tuple(re.split(r"\_l", label[1:]))] = assignment
  205. model = [True for i in range(len(extracted))]
  206. assignments = {}
  207. for label, assignment in extracted.items():
  208. clause = int(label[0])
  209. lit = int(label[1])
  210. var = abs(lit)
  211. if lit < 0:
  212. assignment *= -1
  213. if var in assignments:
  214. assignments[var].append(assignment)
  215. else:
  216. assignments[var] = [assignment]
  217. conflicts = False
  218. for var, a in assignments.items():
  219. if abs(np.sum(a)) != len(a):
  220. conflicts = True
  221. print("conflicts - no solution found")
  222. print(var, np.sort(a))
  223. if conflicts:
  224. return
  225. model = [True for i in range(sat.getNumberOfVariables())]
  226. for var, assignment in assignments.items():
  227. model[var - 1] = True if assignment[0] > 0 else False
  228. print(model, sat.checkAssignment(model))
  229. def test3_3():
  230. sat = rs.generateRandomKSAT(42, 10, 3)
  231. print(sat.toString())
  232. #ising = s2q.primitiveQUBO_8(sat)
  233. ising = s2q.WMISdictQUBO_2(sat)
  234. #ising = {}
  235. #ising[("x1", "z1")] = +2
  236. #ising[("x2", "z2")] = +2
  237. #ising[("z1", "z2")] = +2
  238. #ising[("z1", "z1")] = -2
  239. #ising[("z2", "z2")] = -2
  240. #ising[("x1", "z3")] = -2
  241. #ising[("x2", "z3")] = -2
  242. #ising[("x3", "z3")] = +2
  243. #ising[("z3", "z3")] = +2
  244. h, J = graph.split_ising(ising)
  245. #res = QBSolv().sample_ising(h, J, find_max=False)
  246. res = QBSolv().sample_qubo(ising, find_max=False)
  247. #res = dimod.ExactSolver().sample_ising(h, J)
  248. #res = dimod.ExactSolver().sample_qubo(ising)
  249. sample = res.first.sample
  250. print(res.truncate(50))
  251. #print(res.truncate(10))
  252. assignments = {}
  253. vars = set()
  254. for node, energy in sample.items():
  255. if node[0] == "x":
  256. lit = int(node[1:])
  257. vars.add(abs(lit))
  258. assignments[lit] = energy
  259. conflicts = set()
  260. for var in vars:
  261. if var in assignments and -var in assignments:
  262. if assignments[var] == assignments[-var]:
  263. print("conflict at var: {}".format(var))
  264. conflicts.add(var)
  265. #if conflicts:
  266. # return
  267. model = [True for i in range(len(vars))]
  268. for var in vars:
  269. if var in assignments:
  270. model[var - 1] = True if assignments[var] == 1 else False
  271. elif -var in assignments:
  272. model[var - 1] = True if assignments[-var] == 0 else False
  273. print()
  274. print(model)
  275. print()
  276. print(sat.checkAssignment(model))
  277. print()
  278. degrees = sat.getDegreesOfVariables()
  279. for var in conflicts:
  280. node_var = "x{}".format(var)
  281. node_nvar = "x{}".format(-var)
  282. print("var {}: deg={}, coupler={}, e={}, ne={}"
  283. .format(var,
  284. degrees[var],
  285. ising[(node_var, node_nvar)],
  286. assignments[var],
  287. assignments[-var]))
  288. def test4():
  289. sat = rs.generateRandomKSAT(50, 13, 3)
  290. print(sat.toString())
  291. qubo = s2q.WMISdictQUBO(sat)
  292. ising = s2q.primitiveQUBO(sat)
  293. qg = nx.Graph()
  294. for coupler, energy in qubo.items():
  295. if coupler[0] != coupler[1]:
  296. qg.add_edge(coupler[0], coupler[1], weight=energy)
  297. ig = nx.Graph()
  298. for coupler, energy in ising.items():
  299. if coupler[0] != coupler[1]:
  300. ig.add_edge(coupler[0], coupler[1], weight=energy)
  301. #plt.ion()
  302. print(qg.number_of_nodes(), qg.number_of_edges())
  303. print(ig.number_of_nodes(), ig.number_of_edges())
  304. target = dnx.chimera_graph(12, 12, 4)
  305. #nx.draw_shell(qg, with_labels=True, node_size=50)
  306. #nx.draw_shell(ig, with_labels=True, node_size=50)
  307. print()
  308. print("wmis:")
  309. qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True)
  310. print(qemb[1])
  311. print("median chain length = {}".format(medianChainLength(qemb[0])))
  312. used_nodes = []
  313. for var, chain in qemb[0].items():
  314. used_nodes.extend(chain)
  315. used_nodes = np.unique(used_nodes)
  316. print("used nodes (embedding) = {}".format(len(used_nodes)))
  317. print()
  318. print("primitves:")
  319. iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True)
  320. print(iemb[1])
  321. print("median chain length = {}".format(medianChainLength(iemb[0])))
  322. used_nodes = []
  323. for var, chain in iemb[0].items():
  324. used_nodes.extend(chain)
  325. used_nodes = np.unique(used_nodes)
  326. print("used nodes (embedding) = {}".format(len(used_nodes)))
  327. #test3_3()
  328. test2()
  329. #test_kv_range()