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.

472 lines
15 KiB

6 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 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
  1. import configparser
  2. import os
  3. import argparse
  4. import pymongo
  5. import ssl
  6. import mysql.connector
  7. import networkx as nx
  8. from . import queries
  9. from . import graph
  10. from . import SAT2QUBO
  11. import minorminer
  12. from tqdm import tqdm
  13. import numpy as np
  14. import random
  15. import sys
  16. def readConfig(configFilePath):
  17. config = configparser.ConfigParser()
  18. if os.path.isfile(configFilePath):
  19. config.read(configFilePath)
  20. return config
  21. class ArgParser:
  22. def __init__(self):
  23. self.__flags = {}
  24. self.__parser = argparse.ArgumentParser()
  25. self.__instanceDirArgSet = False
  26. self.__config = None
  27. self.__parsedArgs = {}
  28. def addArg(self, alias,
  29. shortFlag,
  30. longFlag,
  31. help,
  32. type,
  33. default=None,
  34. ignoreDatabaseConfig=False):
  35. self.__flags[alias] = {"longFlag": longFlag,
  36. "hasDefault": False,
  37. "ignoreDatabaseConfig": ignoreDatabaseConfig,
  38. "type": type}
  39. if default != None:
  40. self.__flags[alias]["hasDefault"] = True
  41. self.__parser.add_argument("-%s" % shortFlag,
  42. "--%s" % longFlag,
  43. help=help,
  44. type=type,
  45. default=default)
  46. def addInstanceDirArg(self):
  47. self.__instanceDirArgSet = True
  48. self.addArg(alias="datasetDir", shortFlag="d", longFlag="dataset_dir",
  49. help="the base direcotry of the dataset; if this flag is given the others can be omitted",
  50. type=str, ignoreDatabaseConfig=True)
  51. def parse(self):
  52. self.__parsedArgs = {}
  53. args = vars(self.__parser.parse_args())
  54. if self.__instanceDirArgSet:
  55. self.__config = readConfig(os.path.join(args["dataset_dir"],
  56. "dataset.config"))
  57. self.__parseDatasetConfig()
  58. for alias, flag in self.__flags.items():
  59. self.__parsedArgs[alias] = self.__processFlag(args, flag)
  60. self.__config = None
  61. return self.__parsedArgs
  62. def __parseDatasetConfig(self):
  63. for flag, value in self.__config["STRUCTURE"].items():
  64. self.__parsedArgs[flag] = value
  65. def __processFlag(self, args, flag):
  66. longFlag = flag["longFlag"]
  67. tmpValue = self.__parsedArgs[longFlag] if longFlag in self.__parsedArgs else None
  68. if flag["ignoreDatabaseConfig"] == True:
  69. tmpValue = None
  70. if args[longFlag]:
  71. tmpValue = args[longFlag]
  72. if tmpValue == None:
  73. tmpValue = flag["type"](input("pass arguement %s: " % longFlag))
  74. return tmpValue
  75. def getDBContext(dbConfigPath):
  76. dbContext = {}
  77. dbContext["client"] = connect_to_instance_pool(dbConfigPath)
  78. dbContext["db"] = dbContext["client"]["experiments"]
  79. dbContext["instances"] = dbContext["db"]["instances"]
  80. dbContext["experimentScopes"] = dbContext["db"]["experiment_scopes"]
  81. return dbContext
  82. def connect_to_instance_pool(dbConfigPath = "database.config"):
  83. dbConf = readConfig(dbConfigPath)
  84. client = pymongo.MongoClient(
  85. "mongodb://%s:%s@%s:%s/%s"
  86. % ( dbConf["INSTANCE_POOL"]["user"],
  87. dbConf["INSTANCE_POOL"]["pw"],
  88. dbConf["INSTANCE_POOL"]["url"],
  89. dbConf["INSTANCE_POOL"]["port"],
  90. dbConf["INSTANCE_POOL"]["database"]),
  91. ssl=True,
  92. ssl_cert_reqs=ssl.CERT_NONE)
  93. return client[dbConf["INSTANCE_POOL"]["database"]]
  94. def connect_to_experimetns_db(dbConfigPath = "database.config"):
  95. dbConfig = readConfig(dbConfigPath)
  96. return mysql.connector.connect(
  97. host=dbConfig["EXPERIMENT_DB"]["url"],
  98. port=dbConfig["EXPERIMENT_DB"]["port"],
  99. user=dbConfig["EXPERIMENT_DB"]["user"],
  100. password=dbConfig["EXPERIMENT_DB"]["pw"],
  101. database=dbConfig["EXPERIMENT_DB"]["database"]
  102. )
  103. def frange(start, stop, steps):
  104. while start < stop:
  105. yield start
  106. start += steps
  107. def create_experiment_scope(db, description, name):
  108. experimentScope = {}
  109. experimentScope["instances"] = []
  110. experimentScope["description"] = description
  111. experimentScope["_id"] = name.strip()
  112. db["experiment_scopes"].insert_one(experimentScope)
  113. def write_instance_to_pool_db(db, instance):
  114. instance_document = instance.writeJSONLike()
  115. result = db["instances"].insert_one(instance_document)
  116. return result.inserted_id
  117. def add_instance_to_experiment_scope(db, scope_name, instance_id):
  118. db["experiment_scopes"].update_one(
  119. {"_id": scope_name},
  120. {"$push": {"instances": instance_id}}
  121. )
  122. def write_qubo_to_pool_db(collection, qubo, sat_instance_id):
  123. doc = {}
  124. doc["instance"] = sat_instance_id
  125. doc["description"] = {"<qubo>": "<entrys>",
  126. "<entrys>": "<entry><entrys> | <entry> | \"\"",
  127. "<entry>": "<coupler><energy>",
  128. "<energy>": "<real_number>",
  129. "<coupler>": "<node><node>",
  130. "<node>": "<clause><literal>",
  131. "<clause>": "<natural_number>",
  132. "<literal>": "<integer>"}
  133. doc["qubo"] = __qubo_to_JSON(qubo)
  134. collection.insert_one(doc)
  135. def create_wmis_qubos_for_scope(db, scope):
  136. instances = queries.Instance_scope_query(db)
  137. instances.query(scope)
  138. for instance, instance_id in instances:
  139. qubo = SAT2QUBO.WMISdictQUBO(instance)
  140. write_qubo_to_pool_db(db["wmis_qubos"], qubo, instance_id)
  141. def create_wmis_2_qubos_for_scope(db, scope):
  142. instances = queries.Instance_scope_query(db)
  143. instances.query(scope)
  144. for instance, instance_id in instances:
  145. qubo = SAT2QUBO.WMISdictQUBO_2(instance)
  146. write_qubo_to_pool_db(db["wmis_2_qubos"], qubo, instance_id)
  147. def create_wmis_3_qubos_for_scope(db, scope):
  148. instances = queries.Instance_scope_query(db)
  149. instances.query(scope)
  150. for instance, instance_id in tqdm(instances):
  151. qubo = SAT2QUBO.WMISdictQUBO_3(instance)
  152. write_qubo_to_pool_db(db["wmis_3_qubos"], qubo, instance_id)
  153. def create_wmis_4_qubos_for_scope(db, scope):
  154. instances = queries.Instance_scope_query(db)
  155. instances.query(scope)
  156. for instance, instance_id in tqdm(instances):
  157. qubo = SAT2QUBO.WMISdictQUBO_4(instance)
  158. write_qubo_to_pool_db(db["wmis_4_qubos"], qubo, instance_id)
  159. def create_primitive_isings_for_scope_2(db, scope):
  160. instances = queries.Instance_scope_query(db)
  161. instances.query(scope)
  162. for instance, instance_id in instances:
  163. ising = SAT2QUBO.primitiveQUBO_2(instance)
  164. write_qubo_to_pool_db(db["primitive_isings_2"], ising, instance_id)
  165. def create_primitive_qubo_for_scope_5(db, scope):
  166. instances = queries.Instance_scope_query(db)
  167. instances.query(scope)
  168. for instance, instance_id in tqdm(instances):
  169. ising = SAT2QUBO.primitiveQUBO_5(instance)
  170. write_qubo_to_pool_db(db["primitive_isings_5"], ising, instance_id)
  171. def create_primitive_qubo_for_scope_8(db, scope):
  172. instances = queries.Instance_scope_query(db)
  173. instances.query(scope)
  174. for instance, instance_id in tqdm(instances):
  175. ising = SAT2QUBO.primitiveQUBO_8(instance)
  176. write_qubo_to_pool_db(db["primitive_isings_8"], ising, instance_id)
  177. def __qubo_to_JSON(qubo):
  178. quboJSON = []
  179. for coupler, value in qubo.items():
  180. quboJSON.append([coupler, float(value)])
  181. return quboJSON
  182. def write_wmis_embedding_to_pool_db(collection, qubo_id, solver_graph_id, seed, embedding):
  183. if not __embedding_entry_exists(collection, qubo_id, solver_graph_id):
  184. __prepare_new_wmis_embedding_entry(collection, qubo_id, solver_graph_id)
  185. collection.update_one(
  186. {"qubo": qubo_id, "solver_graph": solver_graph_id},
  187. {
  188. "$push":
  189. {
  190. "embeddings":
  191. {
  192. "embedding": __embedding_to_array(embedding),
  193. "seed": seed
  194. }
  195. }
  196. }
  197. )
  198. def __embedding_entry_exists(collection, qubo_id, solver_graph_id):
  199. filter = {"qubo": qubo_id, "solver_graph": solver_graph_id}
  200. if collection.count_documents(filter) > 0:
  201. return True
  202. return False
  203. def __prepare_new_wmis_embedding_entry(collection, qubo_id, solver_graph_id):
  204. doc = {}
  205. doc["qubo"] = qubo_id
  206. doc["solver_graph"] = solver_graph_id
  207. doc["description"] = {"<embedding>": "<chains>",
  208. "<chains>": "<chain><chains> | \"\"",
  209. "<chain>" : "<original_node><chimera_nodes>",
  210. "<chimera_nodes>": "<chimera_node><chimera_nodes> | \"\""}
  211. doc["embeddings"] = []
  212. collection.insert_one(doc)
  213. def __embedding_to_array(embedding):
  214. emb_arr = []
  215. for node, chain in embedding.items():
  216. emb_arr.append([node, chain])
  217. return emb_arr
  218. def write_solver_graph_to_pool_db(collection, graph):
  219. data = nx.node_link_data(graph)
  220. id = queries.get_id_of_solver_graph(collection, data)
  221. if id != None:
  222. return id
  223. doc = {}
  224. doc["data"] = data
  225. return collection.insert_one(doc).inserted_id
  226. def find_wmis_embeddings_for_scope(db, scope, solver_graph):
  227. solver_graph_id = write_solver_graph_to_pool_db(db["solver_graphs"],
  228. solver_graph)
  229. qubos = queries.WMIS_scope_query(db)
  230. qubos.query(scope)
  231. new_embeddings_found = 0
  232. already_found = 0
  233. total_count = 0
  234. for qubo, qubo_id in tqdm(qubos):
  235. total_count += 1
  236. max_no_improvement = 10
  237. for i in range(5):
  238. if __embedding_entry_exists(db["embeddings"], qubo_id, solver_graph_id):
  239. if i == 0:
  240. already_found += 1
  241. break;
  242. else:
  243. nx_qubo = graph.qubo_to_nx_graph(qubo)
  244. seed = random.randint(0, sys.maxsize)
  245. emb = minorminer.find_embedding(nx_qubo.edges(),
  246. solver_graph.edges(),
  247. return_overlap=True,
  248. max_no_improvement=max_no_improvement,
  249. random_seed=seed)
  250. if emb[1] == 1:
  251. write_wmis_embedding_to_pool_db(db["embeddings"],
  252. qubo_id,
  253. solver_graph_id,
  254. seed,
  255. emb[0])
  256. new_embeddings_found += 1
  257. max_no_improvement *= 1.5
  258. percentage = 0
  259. if total_count > 0:
  260. percentage = round(((new_embeddings_found + already_found) / total_count) * 100)
  261. print("found {} of {} embeddigns ({}%)".format(new_embeddings_found + already_found,
  262. total_count,
  263. percentage))
  264. print("{} new embeddigns found".format(new_embeddings_found))
  265. def find_embeddings_for_scope(db, solver_graph, qubo_ising_query):
  266. solver_graph_id = write_solver_graph_to_pool_db(db["solver_graphs"],
  267. solver_graph)
  268. new_embeddings_found = 0
  269. already_found = 0
  270. total_count = 0
  271. for qubo, qubo_id in tqdm(qubo_ising_query):
  272. total_count += 1
  273. max_no_improvement = 10
  274. for i in range(5):
  275. if __embedding_entry_exists(db["embeddings"], qubo_id, solver_graph_id):
  276. if i == 0:
  277. already_found += 1
  278. break;
  279. else:
  280. nx_qubo = graph.qubo_to_nx_graph(qubo)
  281. seed = random.randint(0, sys.maxsize)
  282. emb = minorminer.find_embedding(nx_qubo.edges(),
  283. solver_graph.edges(),
  284. return_overlap=True,
  285. max_no_improvement=max_no_improvement,
  286. random_seed=seed)
  287. if emb[1] == 1:
  288. write_wmis_embedding_to_pool_db(db["embeddings"],
  289. qubo_id,
  290. solver_graph_id,
  291. seed,
  292. emb[0])
  293. new_embeddings_found += 1
  294. max_no_improvement *= 1.5
  295. percentage = 0
  296. if total_count > 0:
  297. percentage = round(((new_embeddings_found + already_found) / total_count) * 100)
  298. print("found {} of {} embeddigns ({}%)".format(new_embeddings_found + already_found,
  299. total_count,
  300. percentage))
  301. print("{} new embeddigns found".format(new_embeddings_found))
  302. def save_sample_set(collection, result, solver_input, emb_list_index, run):
  303. doc = {}
  304. doc["data"] = result.to_serializable()
  305. doc["instance"] = solver_input["instance_id"]
  306. doc["embedding"] = {
  307. "embedding_id": solver_input["embeddings_id"],
  308. "list_index": emb_list_index
  309. }
  310. doc["run"] = run
  311. collection.insert_one(doc)
  312. def save_qpu_result():
  313. doc = {}
  314. def analyze_wmis_sample(sample):
  315. data = {}
  316. data["number_of_assignments"] = np.count_nonzero(list(sample.sample.values()))
  317. data["chain_break_fraction"] = sample.chain_break_fraction
  318. data["num_occurrences"] = sample.num_occurrences
  319. data["energy"] = sample.energy
  320. return data
  321. def analyde_minisat_run(run_document):
  322. data = {}
  323. data["satisfiable"] = run_document["satisfiable"]
  324. return data
  325. def majority_vote_sample(sample):
  326. assignments = {}
  327. for coupler, energy in sample.items():
  328. var = abs(coupler[1])
  329. if var not in assignments:
  330. assignments[var] = {"all": []}
  331. if energy == 1:
  332. assignments[var]["all"].append(1 if coupler[1] > 0 else 0)
  333. for var, a in assignments.items():
  334. assignments[var]["majority"] = 1 if __true_percentage(a["all"]) >= 0.5 else 0
  335. assignment = [0 for i in range(len(assignments))]
  336. for var, a in assignments.items():
  337. assignment[var - 1] = a["majority"]
  338. return assignment
  339. def __true_percentage(a):
  340. if len(a) == 0:
  341. return 0
  342. return np.count_nonzero(a) / len(a)