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.

706 lines
20 KiB

6 years ago
6 years ago
5 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 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
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. from util import script
  7. import networkx as nx
  8. import dwave_networkx as dnx
  9. import minorminer
  10. from dwave_qbsolv import QBSolv
  11. import dimod
  12. from dwave.system.composites import FixedEmbeddingComposite
  13. from neal import SimulatedAnnealingSampler
  14. import matplotlib.pyplot as plt
  15. import seaborn as sns
  16. import numpy as np
  17. import re
  18. from tqdm import tqdm
  19. def frange(start, stop, steps):
  20. while start < stop:
  21. yield start
  22. start += steps
  23. def test_kv_range():
  24. k = 75
  25. v = 40
  26. data = {
  27. "p_node_counts" : [],
  28. "wmis_node_counts" : [],
  29. "p_conn_counts" : [],
  30. "wmis_conn_counts" : [],
  31. "p_avrg_connectivity" : [],
  32. "wmis_avrg_connectivity" : [],
  33. "a_arr" : [],
  34. "k_arr" : []
  35. }
  36. target = dnx.chimera_graph(25, 25, 4)
  37. print(target.number_of_nodes())
  38. for r in range(2):
  39. #for k in range(50, 5001, 50):
  40. for a in frange(0.5, 8, 0.5):
  41. #v = int(k/4)
  42. #a = k/v
  43. #v = int(k/a)
  44. k = int(a*v)
  45. print("k={} v={} k/v={}".format(k, v, k/v))
  46. ksatInstance = rs.generateRandomKSAT(k, v, 3)
  47. p_qubo = s2q.WMISdictQUBO_2(ksatInstance)
  48. wmis_qubo = s2q.WMISdictQUBO(ksatInstance)
  49. qg = nx.Graph()
  50. for coupler, energy in wmis_qubo.items():
  51. if coupler[0] != coupler[1]:
  52. qg.add_edge(coupler[0], coupler[1], weight=energy)
  53. ig = nx.Graph()
  54. for coupler, energy in p_qubo.items():
  55. if coupler[0] != coupler[1]:
  56. ig.add_edge(coupler[0], coupler[1], weight=energy)
  57. p_node_count = ig.number_of_nodes();
  58. p_conn_count = ig.number_of_edges();
  59. wmis_node_count = qg.number_of_nodes();
  60. wmis_conn_count = qg.number_of_edges();
  61. print("p_qubo nodes= {}".format(p_node_count));
  62. print("wwmis qubo nodes= {}".format(wmis_node_count));
  63. print("nodes= {}".format(p_node_count / wmis_node_count));
  64. data["p_node_counts"].append(p_node_count)
  65. data["wmis_node_counts"].append(wmis_node_count)
  66. data["p_conn_counts"].append(p_conn_count)
  67. data["wmis_conn_counts"].append(wmis_conn_count)
  68. print("calculating connectivity...")
  69. data["p_avrg_connectivity"].append(nx.edge_connectivity(ig))
  70. print("calculating connectivity...")
  71. data["wmis_avrg_connectivity"].append(nx.edge_connectivity(qg))
  72. data["a_arr"].append(k/v)
  73. data["k_arr"].append(k)
  74. print()
  75. sns.set()
  76. ax = sns.scatterplot(x="a_arr", y="p_node_counts", data=data, label="p_qubo")
  77. ax.set(xlabel='k/v', ylabel='used verticies')
  78. ax = sns.scatterplot(x="a_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo")
  79. plt.show()
  80. ax = sns.scatterplot(x="a_arr", y="p_conn_counts", data=data, label="p_qubo")
  81. ax.set(xlabel='k/v', ylabel='used edges')
  82. ax = sns.scatterplot(x="a_arr", y="wmis_conn_counts", data=data, ax=ax, label="wmis_qubo")
  83. plt.show()
  84. ax = sns.scatterplot(x="a_arr", y="p_avrg_connectivity", data=data, label="p_qubo")
  85. ax.set(xlabel='k/v', ylabel='avrg connectivity')
  86. ax = sns.scatterplot(x="a_arr", y="wmis_avrg_connectivity", data=data, ax=ax, label="wmis_qubo")
  87. plt.show()
  88. def test_kv_range_emb():
  89. k = 75
  90. data = {
  91. "p_node_counts" : [],
  92. "wmis_node_counts" : [],
  93. "p_conn_counts" : [],
  94. "wmis_conn_counts" : [],
  95. "a_arr" : [],
  96. "k_arr" : []
  97. }
  98. target = dnx.chimera_graph(25, 25, 4)
  99. print(target.number_of_nodes())
  100. for r in range(2):
  101. #for k in range(50, 5001, 50):
  102. for a in frange(3.5, 5.5, 0.1):
  103. #v = int(k/4)
  104. #a = k/v
  105. v = int(k/a)
  106. print("k={} v={} k/v={}".format(k, v, k/v))
  107. ksatInstance = rs.generateRandomKSAT(k, v, 3)
  108. p_qubo = s2q.WMISdictQUBO_2(ksatInstance)
  109. wmis_qubo = s2q.WMISdictQUBO(ksatInstance)
  110. qg = nx.Graph()
  111. for coupler, energy in wmis_qubo.items():
  112. if coupler[0] != coupler[1]:
  113. qg.add_edge(coupler[0], coupler[1], weight=energy)
  114. ig = nx.Graph()
  115. for coupler, energy in p_qubo.items():
  116. if coupler[0] != coupler[1]:
  117. ig.add_edge(coupler[0], coupler[1], weight=energy)
  118. qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True, threads=8)
  119. print("wmis emb. found: {}".format(qemb[1]))
  120. iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True, threads=8)
  121. print("primitive emb. found: {}".format(iemb[1]))
  122. if qemb[1] == 0 or iemb[1] == 0:
  123. print()
  124. continue
  125. p_node_count = 0;
  126. p_conn_count = 0;
  127. used_nodes = []
  128. for var, chain in iemb[0].items():
  129. used_nodes.extend(chain)
  130. p_node_count = len(np.unique(used_nodes))
  131. wmis_node_count = 0;
  132. wmis_conn_count = 0;
  133. used_nodes = []
  134. for var, chain in qemb[0].items():
  135. used_nodes.extend(chain)
  136. wmis_node_count = len(np.unique(used_nodes))
  137. #print("p_qubo: nodes={} connections={}".format(p_node_count, p_conn_count))
  138. #print("wmis_qubo: nodes={} connections={}".format(wmis_node_count, wmis_conn_count))
  139. print("p_qubo nodes= {}".format(p_node_count));
  140. print("wwmis qubo nodes= {}".format(wmis_node_count));
  141. print("nodes= {}".format(p_node_count / wmis_node_count));
  142. #print("conns= {}".format(p_conn_count / wmis_conn_count));
  143. data["p_node_counts"].append(p_node_count)
  144. data["wmis_node_counts"].append(wmis_node_count)
  145. data["p_conn_counts"].append(p_conn_count)
  146. data["wmis_conn_counts"].append(wmis_conn_count)
  147. data["a_arr"].append(k/v)
  148. data["k_arr"].append(k)
  149. print()
  150. sns.set()
  151. ax = sns.scatterplot(x="a_arr", y="p_node_counts", data=data, label="p_qubo")
  152. ax.set(xlabel='k/v', ylabel='used verticies after embedding')
  153. ax = sns.scatterplot(x="a_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo")
  154. plt.show()
  155. def test_k_range():
  156. k = 75
  157. data = {
  158. "p_node_counts" : [],
  159. "wmis_node_counts" : [],
  160. "p_conn_counts" : [],
  161. "wmis_conn_counts" : [],
  162. "a_arr" : [],
  163. "k_arr" : []
  164. }
  165. target = dnx.chimera_graph(25, 25, 4)
  166. print(target.number_of_nodes())
  167. for r in range(2):
  168. for k in range(15, 76, 1):
  169. v = int(k/4)
  170. print("k={} v={} k/v={}".format(k, v, k/v))
  171. ksatInstance = rs.generateRandomKSAT(k, v, 3)
  172. p_qubo = s2q.primitiveQUBO(ksatInstance)
  173. wmis_qubo = s2q.WMISdictQUBO(ksatInstance)
  174. qg = nx.Graph()
  175. for coupler, energy in wmis_qubo.items():
  176. if coupler[0] != coupler[1]:
  177. qg.add_edge(coupler[0], coupler[1], weight=energy)
  178. ig = nx.Graph()
  179. for coupler, energy in p_qubo.items():
  180. if coupler[0] != coupler[1]:
  181. ig.add_edge(coupler[0], coupler[1], weight=energy)
  182. qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True, threads=8)
  183. print("wmis emb. found: {}".format(qemb[1]))
  184. iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True, threads=8)
  185. print("primitive emb. found: {}".format(iemb[1]))
  186. if qemb[1] == 0 or iemb[1] == 0:
  187. print()
  188. continue
  189. p_node_count = 0;
  190. p_conn_count = 0;
  191. used_nodes = []
  192. for var, chain in iemb[0].items():
  193. used_nodes.extend(chain)
  194. p_node_count = len(np.unique(used_nodes))
  195. wmis_node_count = 0;
  196. wmis_conn_count = 0;
  197. used_nodes = []
  198. for var, chain in qemb[0].items():
  199. used_nodes.extend(chain)
  200. wmis_node_count = len(np.unique(used_nodes))
  201. #print("p_qubo: nodes={} connections={}".format(p_node_count, p_conn_count))
  202. #print("wmis_qubo: nodes={} connections={}".format(wmis_node_count, wmis_conn_count))
  203. print("p_qubo nodes= {}".format(p_node_count));
  204. print("wwmis qubo nodes= {}".format(wmis_node_count));
  205. print("nodes= {}".format(p_node_count / wmis_node_count));
  206. #print("conns= {}".format(p_conn_count / wmis_conn_count));
  207. data["p_node_counts"].append(p_node_count)
  208. data["wmis_node_counts"].append(wmis_node_count)
  209. data["p_conn_counts"].append(p_conn_count)
  210. data["wmis_conn_counts"].append(wmis_conn_count)
  211. data["a_arr"].append(k/v)
  212. data["k_arr"].append(k)
  213. print()
  214. sns.set()
  215. ax = sns.scatterplot(x="k_arr", y="p_node_counts", data=data, label="p_qubo")
  216. ax.set(xlabel='k',
  217. ylabel='used verticies after embedding')
  218. ax = sns.scatterplot(x="k_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo")
  219. plt.show()
  220. def medianChainLength(emb):
  221. chl = []
  222. for chain in emb.values():
  223. chl.append(len(chain))
  224. sns.distplot(chl)
  225. plt.show()
  226. return np.mean(chl)
  227. def test2():
  228. sat = rs.generateRandomKSAT(42, 10, 3)
  229. print(sat.toString())
  230. qubo = s2q.WMISdictQUBO(sat)
  231. #ising = s2q.primitiveQUBO_8(sat)
  232. ising = s2q.WMISdictQUBO_2(sat)
  233. qg = nx.Graph()
  234. for coupler, energy in qubo.items():
  235. if coupler[0] != coupler[1]:
  236. qg.add_edge(coupler[0], coupler[1], weight=energy)
  237. ig = nx.Graph()
  238. for coupler, energy in ising.items():
  239. if coupler[0] != coupler[1]:
  240. ig.add_edge(coupler[0], coupler[1], weight=energy)
  241. #plt.ion()
  242. print(qg.number_of_nodes(), qg.number_of_edges())
  243. print(ig.number_of_nodes(), ig.number_of_edges())
  244. target = dnx.chimera_graph(16, 16, 4)
  245. #nx.draw_shell(qg, with_labels=True, node_size=50)
  246. #nx.draw_shell(ig, with_labels=True, node_size=50)
  247. eg = ig
  248. emb = minorminer.find_embedding(eg.edges(), target.edges(), return_overlap=True,
  249. threads=8)
  250. print(emb[1])
  251. for node, chain in emb[0].items():
  252. print(node, chain)
  253. print("avrg chain length = {}".format(medianChainLength(emb[0])))
  254. dnx.draw_chimera_embedding(G=target, emb=emb[0], embedded_graph=eg, show_labels=True)
  255. plt.show()
  256. def test3():
  257. sat = rs.generateRandomKSAT(42, 10, 3)
  258. print(sat.toString())
  259. ising = s2q.primitiveQUBO(sat)
  260. h = {}
  261. J = {}
  262. for coupler, energy in ising.items():
  263. if coupler[0] == coupler[1]:
  264. h[coupler[0]] = energy
  265. else:
  266. J[coupler] = energy
  267. res = QBSolv().sample_ising(h, J, find_max=False)
  268. sample = list(res.samples())[0]
  269. extracted = {}
  270. r = re.compile("c\d+_l-?\d*")
  271. for label, assignment in sample.items():
  272. if r.fullmatch(label):
  273. extracted[tuple(re.split(r"\_l", label[1:]))] = assignment
  274. model = [True for i in range(len(extracted))]
  275. assignments = {}
  276. for label, assignment in extracted.items():
  277. clause = int(label[0])
  278. lit = int(label[1])
  279. var = abs(lit)
  280. if lit < 0:
  281. assignment *= -1
  282. if var in assignments:
  283. assignments[var].append(assignment)
  284. else:
  285. assignments[var] = [assignment]
  286. conflicts = False
  287. for var, a in assignments.items():
  288. if abs(np.sum(a)) != len(a):
  289. conflicts = True
  290. print("conflicts - no solution found")
  291. print(var, np.sort(a))
  292. if conflicts:
  293. return
  294. model = [True for i in range(sat.getNumberOfVariables())]
  295. for var, assignment in assignments.items():
  296. model[var - 1] = True if assignment[0] > 0 else False
  297. print(model, sat.checkAssignment(model))
  298. def test3_3():
  299. sat = rs.generateRandomKSAT(42, 10, 3)
  300. print(sat.toString())
  301. #ising = s2q.primitiveQUBO_8(sat)
  302. ising = s2q.WMISdictQUBO_2(sat)
  303. #ising = {}
  304. #ising[("x1", "z1")] = +2
  305. #ising[("x2", "z2")] = +2
  306. #ising[("z1", "z2")] = +2
  307. #ising[("z1", "z1")] = -2
  308. #ising[("z2", "z2")] = -2
  309. #ising[("x1", "z3")] = -2
  310. #ising[("x2", "z3")] = -2
  311. #ising[("x3", "z3")] = +2
  312. #ising[("z3", "z3")] = +2
  313. h, J = graph.split_ising(ising)
  314. #res = QBSolv().sample_ising(h, J, find_max=False)
  315. res = QBSolv().sample_qubo(ising, find_max=False)
  316. #res = dimod.ExactSolver().sample_ising(h, J)
  317. #res = dimod.ExactSolver().sample_qubo(ising)
  318. sample = res.first.sample
  319. print(res.truncate(50))
  320. #print(res.truncate(10))
  321. assignments = {}
  322. vars = set()
  323. for node, energy in sample.items():
  324. if node[0] == "x":
  325. lit = int(node[1:])
  326. vars.add(abs(lit))
  327. assignments[lit] = energy
  328. conflicts = set()
  329. for var in vars:
  330. if var in assignments and -var in assignments:
  331. if assignments[var] == assignments[-var]:
  332. print("conflict at var: {}".format(var))
  333. conflicts.add(var)
  334. #if conflicts:
  335. # return
  336. model = [True for i in range(len(vars))]
  337. for var in vars:
  338. if var in assignments:
  339. model[var - 1] = True if assignments[var] == 1 else False
  340. elif -var in assignments:
  341. model[var - 1] = True if assignments[-var] == 0 else False
  342. print()
  343. print(model)
  344. print()
  345. print(sat.checkAssignment(model))
  346. print()
  347. degrees = sat.getDegreesOfVariables()
  348. for var in conflicts:
  349. node_var = "x{}".format(var)
  350. node_nvar = "x{}".format(-var)
  351. print("var {}: deg={}, coupler={}, e={}, ne={}"
  352. .format(var,
  353. degrees[var],
  354. ising[(node_var, node_nvar)],
  355. assignments[var],
  356. assignments[-var]))
  357. def test3_4():
  358. sat_count = 0
  359. steps = 200
  360. for i in tqdm(range(steps)):
  361. sat = rs.generateRandomKSAT(35, 10, 3)
  362. ising = s2q.WMISdictQUBO_2(sat)
  363. res = QBSolv().sample_qubo(ising, find_max=False)
  364. #res = dimod.ExactSolver().sample_qubo(ising)
  365. sample = res.first.sample
  366. assignments = {}
  367. vars = set()
  368. for node, energy in sample.items():
  369. if node[0] == "x":
  370. lit = int(node[1:])
  371. vars.add(abs(lit))
  372. assignments[lit] = energy
  373. model = [True for i in range(len(vars))]
  374. for var in vars:
  375. if var in assignments:
  376. model[var - 1] = True if assignments[var] == 1 else False
  377. elif -var in assignments:
  378. model[var - 1] = True if assignments[-var] == 0 else False
  379. if sat.checkAssignment(model):
  380. sat_count += 1
  381. print("sat percentage: {}".format(sat_count / steps))
  382. def test_wmis():
  383. sat_count = 0
  384. #steps = 100
  385. steps = 1
  386. for i in tqdm(range(steps)):
  387. sat = rs.generateRandomKSAT(35, 10, 3)
  388. target = dnx.chimera_graph(16, 16, 4)
  389. qubo = s2q.WMISdictQUBO(sat)
  390. qg = nx.Graph()
  391. for coupler, energy in qubo.items():
  392. if coupler[0] != coupler[1]:
  393. qg.add_edge(coupler[0], coupler[1], weight=energy)
  394. qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True)
  395. chimera_sampler = dimod.StructureComposite(SimulatedAnnealingSampler(),
  396. target.nodes(),
  397. target.edges())
  398. solver = FixedEmbeddingComposite(chimera_sampler, qemb[0])
  399. res = solver.sample_qubo(__negate_qubo(qubo))
  400. #res = solver.sample_qubo(qubo)
  401. #res = dimod.ExactSolver().sample_qubo(ising)
  402. sample = res.first.sample
  403. model = script.majority_vote_sample(sample)
  404. print("energy={}".format(res.first.energy))
  405. if sat.checkAssignment(model):
  406. sat_count += 1
  407. print("sat percentage: {}".format(sat_count / steps))
  408. def test4():
  409. sat = rs.generateRandomKSAT(50, 13, 3)
  410. print(sat.toString())
  411. qubo = s2q.WMISdictQUBO(sat)
  412. ising = s2q.primitiveQUBO(sat)
  413. qg = nx.Graph()
  414. for coupler, energy in qubo.items():
  415. if coupler[0] != coupler[1]:
  416. qg.add_edge(coupler[0], coupler[1], weight=energy)
  417. ig = nx.Graph()
  418. for coupler, energy in ising.items():
  419. if coupler[0] != coupler[1]:
  420. ig.add_edge(coupler[0], coupler[1], weight=energy)
  421. #plt.ion()
  422. print(qg.number_of_nodes(), qg.number_of_edges())
  423. print(ig.number_of_nodes(), ig.number_of_edges())
  424. target = dnx.chimera_graph(12, 12, 4)
  425. #nx.draw_shell(qg, with_labels=True, node_size=50)
  426. #nx.draw_shell(ig, with_labels=True, node_size=50)
  427. print()
  428. print("wmis:")
  429. qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True)
  430. print(qemb[1])
  431. print("median chain length = {}".format(medianChainLength(qemb[0])))
  432. used_nodes = []
  433. for var, chain in qemb[0].items():
  434. used_nodes.extend(chain)
  435. used_nodes = np.unique(used_nodes)
  436. print("used nodes (embedding) = {}".format(len(used_nodes)))
  437. print()
  438. print("primitves:")
  439. iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True)
  440. print(iemb[1])
  441. print("median chain length = {}".format(medianChainLength(iemb[0])))
  442. used_nodes = []
  443. for var, chain in iemb[0].items():
  444. used_nodes.extend(chain)
  445. used_nodes = np.unique(used_nodes)
  446. print("used nodes (embedding) = {}".format(len(used_nodes)))
  447. def __negate_qubo(qubo):
  448. negative_qubo = {}
  449. for coupler, energy in qubo.items():
  450. negative_qubo[coupler] = -1 * energy
  451. return negative_qubo
  452. #test3_4()
  453. #test2()
  454. #test_kv_range
  455. test_wmis()