diff --git a/create_wmis_result_table.sql b/create_wmis_result_table.sql index b4d854f..5ccc49c 100644 --- a/create_wmis_result_table.sql +++ b/create_wmis_result_table.sql @@ -1,4 +1,4 @@ -create table c42_vLogistic_6_wmis_siman_results ( +create table c42_vLogistic_6_wmis_qpu_results ( result_id char(24), run int, instance_id char(24), @@ -7,6 +7,7 @@ create table c42_vLogistic_6_wmis_siman_results ( num_occurrences int, energy float, satisfiable boolean, + anneal_time int, primary key (result_id) ); \ No newline at end of file diff --git a/run_sampler_on_scope.py b/run_sampler_on_scope.py index c56727b..ccd862c 100755 --- a/run_sampler_on_scope.py +++ b/run_sampler_on_scope.py @@ -13,13 +13,22 @@ from dwave.system.samplers import DWaveSampler from tqdm import tqdm +__QUBO__ = 1 +__ISING__ = 2 + def main(): mode = __get_mode() + ising_qubo_collection = input("ising/qubo collection: ") + + model_type = __get_model_type() + + result_collection = input("result collection: ") + if mode == "SIMAN": - __run_siman() + __run_siman(ising_qubo_collection, model_type, result_collection) elif mode == "QPU": - __run_qpu() + __run_qpu(ising_qubo_collection, model_type, result_collection) def __get_mode(): print("choose mode:") @@ -31,32 +40,55 @@ def __get_mode(): return "SIMAN" elif mode == 2: return "QPU" - -def __run_siman(): + +def __get_model_type(): + print("model types:") + print("(q) qubo") + print("(i) ising") + model_type = input("choose: ") + + if model_type == "q": + return __QUBO__ + if model_type == "i": + return __ISING__ + +def __run_siman(ising_qubo_collection, model_type, result_collection): db = script.connect_to_instance_pool() target_graph = dnx.chimera_graph(16, 16, 4) - - solver_input_query = __get_solver_input_query(db, target_graph) + target_graph_id = queries.get_id_of_solver_graph(db["solver_graphs"], + nx.node_link_data(target_graph)) + + solver_input_query = __get_solver_input_query(db, + target_graph_id, + ising_qubo_collection) base_sampler = SimulatedAnnealingSampler() chimera_sampler = dimod.StructureComposite(base_sampler, target_graph.nodes(), target_graph.edges()) - __run_on_scope(solver_input_query, db["wmis_siman_results"], base_sampler) + __run_on_scope(solver_input_query, db[result_collection], chimera_sampler, model_type) -def __run_qpu(): +def __run_qpu(ising_qubo_collection, model_type, result_collection): db = script.connect_to_instance_pool() base_solver = DWaveSampler() + solver_graph_id = __get_solver_graph_id(db, base_solver.solver) - solver_input_query = __get_solver_input_query(db, solver_graph) - + solver_input_query = __get_solver_input_query(db, + solver_graph_id, + ising_qubo_collection) + solver_args = {} solver_args["annealing_time"] = int(input("annealing time (in us): ")) + solver_args["num_reads"] = int(input("number of reads per sample: ")) - __run_on_scope(solver_input_query, db["wmis_qpu_results"], base_solver, solver_args) + __run_on_scope(solver_input_query, + db[result_collection], + base_solver, + model_type, + solver_args) @@ -65,15 +97,20 @@ def __get_solver_graph_id(db, solver): return queries.get_id_of_solver_graph(db["solver_graphs"], nx.node_link_data(solver_graph)) -def __get_solver_input_query(db, solver): - solver_graph_id = __get_solver_graph_id(db, solver) - +def __get_solver_input_query(db, solver_graph_id, ising_qubo_collection): scope = input("scope: ") - solver_input_query = queries.WMIS_solver_input_scope_query(db) + solver_input_query = queries.WMIS_solver_input_scope_query(db, ising_qubo_collection) solver_input_query.query(scope, solver_graph_id) -def __run_on_scope(solver_input_query, result_collection, base_solver, solver_args={}): + return solver_input_query + +def __run_on_scope(solver_input_query, + result_collection, + base_solver, + model_type, + solver_args={}): + run = int(input("save as run (numbered): ")) for solver_input in tqdm(solver_input_query): @@ -83,13 +120,18 @@ def __run_on_scope(solver_input_query, result_collection, base_solver, solver_ar solver = FixedEmbeddingComposite(base_solver, embedding) - res = solver.sample_qubo(qubo, **solver_args) + if model_type == __QUBO__: + res = solver.sample_qubo(qubo, **solver_args) + elif model_type == __ISING__: + h, J = graph.split_ising(qubo) + + res = solver.sample_ising(h, J, **solver_args) - script.save_result(result_collection, - res, - solver_input, - emb_list_index = 0, - run = run) + script.save_sample_set(result_collection, + res, + solver_input, + emb_list_index = 0, + run = run) diff --git a/testSAT2QUBO.py b/testSAT2QUBO.py index a63c2e6..efa5116 100755 --- a/testSAT2QUBO.py +++ b/testSAT2QUBO.py @@ -2,11 +2,14 @@ from util import SAT2QUBO as s2q from util import randomSAT as rs +from util import queries +from util import graph import networkx as nx import dwave_networkx as dnx import minorminer from dwave_qbsolv import QBSolv +import dimod import matplotlib.pyplot as plt import seaborn as sns @@ -51,7 +54,7 @@ def test_kv_range(): ksatInstance = rs.generateRandomKSAT(k, v, 3) - p_qubo = s2q.primitiveQUBO(ksatInstance) + p_qubo = s2q.primitiveQUBO_5(ksatInstance) wmis_qubo = s2q.WMISdictQUBO(ksatInstance) @@ -233,16 +236,20 @@ def medianChainLength(emb): for chain in emb.values(): chl.append(len(chain)) - return np.median(chl) + sns.distplot(chl) + plt.show() + + return np.mean(chl) def test2(): - sat = rs.generateRandomKSAT(15, 4, 3) + sat = rs.generateRandomKSAT(42, 10, 3) print(sat.toString()) qubo = s2q.WMISdictQUBO(sat) - ising = s2q.primitiveQUBO(sat) + #ising = s2q.primitiveQUBO_8(sat) + ising = s2q.WMISdictQUBO_2(sat) qg = nx.Graph() @@ -261,7 +268,7 @@ def test2(): print(qg.number_of_nodes(), qg.number_of_edges()) print(ig.number_of_nodes(), ig.number_of_edges()) - target = dnx.chimera_graph(9, 9, 4) + target = dnx.chimera_graph(16, 16, 4) #nx.draw_shell(qg, with_labels=True, node_size=50) #nx.draw_shell(ig, with_labels=True, node_size=50) @@ -270,16 +277,20 @@ def test2(): emb = minorminer.find_embedding(eg.edges(), target.edges(), return_overlap=True, threads=8) - print("median chain length = {}".format(medianChainLength(emb[0]))) - print(emb[1]) + for node, chain in emb[0].items(): + print(node, chain) + + print("avrg chain length = {}".format(medianChainLength(emb[0]))) + dnx.draw_chimera_embedding(G=target, emb=emb[0], embedded_graph=eg, show_labels=True) plt.show() + def test3(): - sat = rs.generateRandomKSAT(15, 4, 3) + sat = rs.generateRandomKSAT(42, 10, 3) print(sat.toString()) @@ -296,6 +307,7 @@ def test3(): res = QBSolv().sample_ising(h, J, find_max=False) + sample = list(res.samples())[0] extracted = {} @@ -342,7 +354,94 @@ def test3(): print(model, sat.checkAssignment(model)) +def test3_3(): + sat = rs.generateRandomKSAT(42, 10, 3) + + print(sat.toString()) + + #ising = s2q.primitiveQUBO_8(sat) + ising = s2q.WMISdictQUBO_2(sat) + + #ising = {} + + #ising[("x1", "z1")] = +2 + #ising[("x2", "z2")] = +2 + + #ising[("z1", "z2")] = +2 + + #ising[("z1", "z1")] = -2 + #ising[("z2", "z2")] = -2 + + #ising[("x1", "z3")] = -2 + #ising[("x2", "z3")] = -2 + #ising[("x3", "z3")] = +2 + #ising[("z3", "z3")] = +2 + + h, J = graph.split_ising(ising) + + #res = QBSolv().sample_ising(h, J, find_max=False) + res = QBSolv().sample_qubo(ising, find_max=False) + + #res = dimod.ExactSolver().sample_ising(h, J) + #res = dimod.ExactSolver().sample_qubo(ising) + + sample = res.first.sample + + print(res.truncate(50)) + #print(res.truncate(10)) + + assignments = {} + vars = set() + + for node, energy in sample.items(): + if node[0] == "x": + lit = int(node[1:]) + + vars.add(abs(lit)) + + assignments[lit] = energy + + conflicts = set() + for var in vars: + if var in assignments and -var in assignments: + if assignments[var] == assignments[-var]: + print("conflict at var: {}".format(var)) + conflicts.add(var) + + #if conflicts: + # return + + model = [True for i in range(len(vars))] + + for var in vars: + if var in assignments: + model[var - 1] = True if assignments[var] == 1 else False + elif -var in assignments: + model[var - 1] = True if assignments[-var] == 0 else False + + print() + + print(model) + + print() + + print(sat.checkAssignment(model)) + + print() + + degrees = sat.getDegreesOfVariables() + + for var in conflicts: + node_var = "x{}".format(var) + node_nvar = "x{}".format(-var) + print("var {}: deg={}, coupler={}, e={}, ne={}" + .format(var, + degrees[var], + ising[(node_var, node_nvar)], + assignments[var], + assignments[-var])) + def test4(): sat = rs.generateRandomKSAT(50, 13, 3) @@ -400,4 +499,6 @@ def test4(): print("used nodes (embedding) = {}".format(len(used_nodes))) -test_k_range() +#test3_3() +test2() +#test_kv_range() diff --git a/test_data_extraction.py b/test_data_extraction.py index 8f84d85..67af2b9 100755 --- a/test_data_extraction.py +++ b/test_data_extraction.py @@ -3,15 +3,20 @@ import util.script as script import util.queries as queries import dimod +import random from tqdm import tqdm def main(): #instance_parameters() #wmis_results() - #wmis_siman_results_alpha_num_of_assignments() - #wmis_siman_results() - minisat_runs() + wmis_siman_results_alpha_num_of_assignments() + #wmis_qpu_results_alpha_num_of_assignments() + #primitive_2_siman_results_alpha_num_of_assignments() + #primitive_5_siman_results_alpha_num_of_assignments() + #primitive_5_qpu_results_alpha_num_of_assignments() + #primitive_8_siman_results_alpha_num_of_assignments() + #minisat_runs() def instance_parameters(): edb = script.connect_to_experimetns_db() @@ -60,9 +65,9 @@ def wmis_siman_results_alpha_num_of_assignments(): idb = script.connect_to_instance_pool() q = queries.WMIS_result_scope_query_raw(idb) - q.query("c42_vLogistic_6", "wmis_siman_results") + q.query("c42_vLogistic_6", "wmis_qubos_2_siman") - insert_row = ("INSERT INTO c42_vLogistic_6_wmis_siman_results " + insert_row = ("INSERT INTO c42_vLogistic_6_wmis_1_2_siman_results " "(result_id, " " run, " " instance_id, " @@ -71,7 +76,7 @@ def wmis_siman_results_alpha_num_of_assignments(): " num_occurrences, " " energy, " " satisfiable) " - "VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ") + "VALUES (%s, %s, %s, %s,wa %s, %s, %s, %s) ") for result in tqdm(q): sample_set = queries.read_raw_wmis_sample_set(result["data"]) @@ -96,6 +101,302 @@ def wmis_siman_results_alpha_num_of_assignments(): edb.commit() edb_cursor.close() edb.close() + +def primitive_2_siman_results_alpha_num_of_assignments(): + edb = script.connect_to_experimetns_db() + edb_cursor = edb.cursor() + + idb = script.connect_to_instance_pool() + + q = queries.WMIS_result_scope_query_raw(idb) + q.query("c42_vLogistic_6", "primitive_isings_2_siman_results") + + insert_row = ("INSERT INTO c42_vLogistic_6_primitive_2_siman_results " + "(result_id, " + " run, " + " instance_id, " + " chain_break_fraction, " + " num_occurrences, " + " energy, " + " satisfiable) " + "VALUES (%s, %s, %s, %s, %s, %s, %s) ") + + + for result in tqdm(q): + sample_set = queries.read_raw_primitive_ising_sample_set(result["data"]) + + data = script.analyze_wmis_sample(sample_set.first) + + sat = queries.get_instance_by_id(idb["instances"], result["instance"]) + + model = queries.extract_primitive_ising_model(sample_set.first.sample) + + isSatisfiable = sat.checkAssignment(model) + + edb_cursor.execute(insert_row, (str(result["_id"]), + int(result["run"]), + str(result["instance"]), + float(data["chain_break_fraction"]), + int(data["num_occurrences"]), + int(data["energy"]), + isSatisfiable)) + + edb.commit() + edb_cursor.close() + edb.close() + + +def primitive_5_siman_results_alpha_num_of_assignments(): + edb = script.connect_to_experimetns_db() + edb_cursor = edb.cursor() + + idb = script.connect_to_instance_pool() + + q = queries.WMIS_result_scope_query_raw(idb) + q.query("c42_vLogistic_6", "primitive_isigns_5_siman") + + insert_row = ("INSERT INTO c42_vLogistic_6_primitive_5_siman_results " + "(result_id, " + " run, " + " instance_id, " + " chain_break_fraction, " + " num_occurrences, " + " energy, " + " satisfiable, " + " num_conflicts, " + " monte_carlo_steps) " + "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) ") + + + for result in tqdm(q): + sample_set = queries.read_raw_primitive_ising_sample_set(result["data"]) + + data = script.analyze_wmis_sample(sample_set.first) + + sat = queries.get_instance_by_id(idb["instances"], result["instance"]) + + post_process_results = __post_process_prim_5_sample(sat, sample_set.first.sample) + + #print(post_process_results) + + edb_cursor.execute(insert_row, (str(result["_id"]), + int(result["run"]), + str(result["instance"]), + float(data["chain_break_fraction"]), + int(data["num_occurrences"]), + int(data["energy"]), + bool(post_process_results["satisfiable"]), + int(len(post_process_results["conflicts"])), + int(post_process_results["monte_carlo_steps"]))) + + edb.commit() + edb_cursor.close() + edb.close() + +def primitive_5_qpu_results_alpha_num_of_assignments(): + edb = script.connect_to_experimetns_db() + edb_cursor = edb.cursor() + + idb = script.connect_to_instance_pool() + + q = queries.WMIS_result_scope_query_raw(idb) + q.query("c42_vLogistic_6", "primitive_isings_5_qpu") + + insert_row = ("INSERT INTO c42_vLogistic_6_primitive_5_qpu_results " + "(result_id, " + " run, " + " instance_id, " + " chain_break_fraction, " + " num_occurrences, " + " energy, " + " satisfiable, " + " num_conflicts, " + " monte_carlo_steps, " + " anneal_time) " + "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ") + + + run = int(input("run: ")) + + for result in tqdm(q): + if True: + #if result["run"] == run: + sample_set = queries.read_raw_primitive_ising_sample_set(result["data"]) + + data = script.analyze_wmis_sample(sample_set.first) + + sat = queries.get_instance_by_id(idb["instances"], result["instance"]) + + post_process_results = __post_process_prim_5_sample(sat, + sample_set.first.sample) + + anneal_time = result["data"]["info"]["timing"]["qpu_anneal_time_per_sample"] + #print(post_process_results) + + edb_cursor.execute(insert_row, (str(result["_id"]), + int(result["run"]), + str(result["instance"]), + float(data["chain_break_fraction"]), + int(data["num_occurrences"]), + int(data["energy"]), + bool(post_process_results["satisfiable"]), + int(len(post_process_results["conflicts"])), + int(post_process_results["monte_carlo_steps"]), + int(anneal_time))) + + edb.commit() + edb_cursor.close() + edb.close() + +def primitive_8_siman_results_alpha_num_of_assignments(): + edb = script.connect_to_experimetns_db() + edb_cursor = edb.cursor() + + idb = script.connect_to_instance_pool() + + q = queries.WMIS_result_scope_query_raw(idb) + q.query("c42_vLogistic_6", "wmis_2_qubos_siman") + + insert_row = ("INSERT INTO c42_vLogistic_6_wmis_2_2_siman_results " + "(result_id, " + " run, " + " instance_id, " + " chain_break_fraction, " + " num_occurrences, " + " energy, " + " satisfiable) " + "VALUES (%s, %s, %s, %s, %s, %s, %s) ") + + + run = int(input("run: ")) + + for result in tqdm(q): + if result["run"] == run: + sample_set = queries.read_raw_primitive_ising_sample_set(result["data"]) + + data = script.analyze_wmis_sample(sample_set.first) + + sat = queries.get_instance_by_id(idb["instances"], result["instance"]) + + post_process_results = __post_process_prim_5_sample(sat, + sample_set.first.sample) + + #print(post_process_results) + + edb_cursor.execute(insert_row, (str(result["_id"]), + int(result["run"]), + str(result["instance"]), + float(data["chain_break_fraction"]), + int(data["num_occurrences"]), + int(data["energy"]), + bool(post_process_results["satisfiable"]))) + + edb.commit() + edb_cursor.close() + edb.close() + +def __post_process_prim_5_sample(sat, sample): + post_process_results = {} + + assignments = {} + vars = set() + + for node, energy in sample.items(): + if node[0] == "x": + lit = int(node[1:]) + + vars.add(abs(lit)) + + assignments[lit] = energy + + conflicts = set() + for var in vars: + if var in assignments and -var in assignments: + if assignments[var] == assignments[-var]: + conflicts.add(var) + + model = [True for i in range(len(vars))] + + for var in vars: + if var in assignments: + model[var - 1] = True if assignments[var] == 1 else False + elif -var in assignments: + model[var - 1] = True if assignments[-var] == 0 else False + + + + var_list = list(conflicts) + + monte_carlo_steps = 0 + if len(conflicts) > 0: + for i in range(1000): + rand_var = random.choice(var_list) + + if sat.checkAssignment(model): + monte_carlo_steps + break + + model[rand_var - 1] = not model[rand_var - 1] + + monte_carlo_steps += 1 + + post_process_results["conflicts"] = conflicts + post_process_results["satisfiable"] = sat.checkAssignment(model) + post_process_results["monte_carlo_steps"] = monte_carlo_steps + + return post_process_results + +def wmis_qpu_results_alpha_num_of_assignments(): + edb = script.connect_to_experimetns_db() + edb_cursor = edb.cursor() + + idb = script.connect_to_instance_pool() + + q = queries.WMIS_result_scope_query_raw(idb) + q.query("c42_vLogistic_6", "wmis_qpu_results") + + insert_row = ("INSERT INTO c42_vLogistic_6_wmis_qpu_results " + "(result_id, " + " run, " + " instance_id, " + " number_of_found_assignments, " + " chain_break_fraction, " + " num_occurrences, " + " energy, " + " satisfiable, " + " anneal_time) " + "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) ") + + run = int(input("run: ")) + for result in tqdm(q): + if result["run"] == run: + sample_set = queries.read_raw_wmis_sample_set(result["data"]) + + data = script.analyze_wmis_sample(sample_set.first) + + sat = queries.get_instance_by_id(idb["instances"], result["instance"]) + + model = script.majority_vote_sample(sample_set.first.sample) + + isSatisfiable = sat.checkAssignment(model) + + anneal_time = result["data"]["info"]["timing"]["qpu_anneal_time_per_sample"] + + + edb_cursor.execute(insert_row, (str(result["_id"]), + int(result["run"]), + str(result["instance"]), + int(data["number_of_assignments"]), + float(data["chain_break_fraction"]), + int(data["num_occurrences"]), + int(data["energy"]), + isSatisfiable, + int(anneal_time))) + + edb.commit() + edb_cursor.close() + edb.close() + def minisat_runs(): edb = script.connect_to_experimetns_db() diff --git a/test_sat_to_qubo_workflow.py b/test_sat_to_qubo_workflow.py index 779dc3c..c602957 100755 --- a/test_sat_to_qubo_workflow.py +++ b/test_sat_to_qubo_workflow.py @@ -23,13 +23,15 @@ from dwave_qbsolv import QBSolv import numpy as np import random +import re from tqdm import tqdm def main(): #__wmis() + __pqubo_3() #__pqubo() - __wmis3() + #__wmis3() def __qubo_to_nx_graph(qubo): @@ -119,64 +121,74 @@ def __wmis_qpu(): def __wmis(): - sat = rand_sat.generateRandomKSAT(25, 6, 3) - qubo = __negate_qubo(SAT2QUBO.WMISdictQUBO(sat)) - #qubo = SAT2QUBO.WMISdictQUBO(sat) - nx_qubo = __qubo_to_nx_graph(qubo) - - target_graph = dnx.chimera_graph(16, 16, 4) - - emb = minorminer.find_embedding(nx_qubo.edges(), - target_graph.edges(), - return_overlap=True) - - if emb[1] != 1: - print("no embedding found") - return - - print(emb[0]) - - chimera_sampler = dimod.StructureComposite(SimulatedAnnealingSampler(), - target_graph.nodes(), - target_graph.edges()) - - - - sampler = FixedEmbeddingComposite(chimera_sampler, emb[0]) + sat_count = 0 + no_embedding_count = 0 + + for i in range(200): + sat = rand_sat.generateRandomKSAT(40, 14, 3) + qubo = SAT2QUBO.WMISdictQUBO(sat) + #qubo = SAT2QUBO.WMISdictQUBO(sat) + nx_qubo = __qubo_to_nx_graph(qubo) + + target_graph = dnx.chimera_graph(16, 16, 4) + + emb = minorminer.find_embedding(nx_qubo.edges(), + target_graph.edges(), + return_overlap=True) + + if emb[1] != 1: + print("no embedding found") + no_embedding_count += 1 + continue + + #print(emb[0]) + + chimera_sampler = dimod.StructureComposite(SimulatedAnnealingSampler(), + target_graph.nodes(), + target_graph.edges()) + + + + sampler = FixedEmbeddingComposite(chimera_sampler, emb[0]) - - res = sampler.sample_qubo(qubo) - #res = SimulatedAnnealingSampler().sample_qubo(qubo) - - #dwave.embedding.chain_breaks.majority_vote(res, emb[0]) - - first = res.first - - print("chain_break_fraction={}".format(first.chain_break_fraction)) - for lit, spin in first.sample.items(): - print(lit, spin) - print("true count: {}".format(np.count_nonzero(list(first.sample.values())))) - - assignments = {} - - for coupler, energy in first.sample.items(): - var = abs(coupler[1]) + res = sampler.sample_qubo(qubo, chain_strength=2) + #res = SimulatedAnnealingSampler().sample_qubo(qubo) - if var not in assignments: - assignments[var] = {"all": []} + #dwave.embedding.chain_breaks.majority_vote(res, emb[0]) - if energy == 1: - assignments[var]["all"].append(1 if coupler[1] > 0 else 0) - - __majority_vote(assignments) - - #for var, a in assignments.items(): - ##print(var, np.sort(a["all"]), __majority_percentage(a["all"])) - #print(var, a) - final = __extract_assignment(assignments) - print(final) - print("satisfies sat: {}".format(sat.checkAssignment(final))) + first = res.first + + print("chain_break_fraction={}".format(first.chain_break_fraction)) + #for lit, spin in first.sample.items(): + #print(lit, spin) + print("true count: {}".format(np.count_nonzero(list(first.sample.values())))) + + assignments = {} + + for coupler, energy in first.sample.items(): + + var = abs(coupler[1]) + + if var not in assignments: + assignments[var] = {"all": []} + + if energy == 1: + assignments[var]["all"].append(1 if coupler[1] > 0 else 0) + + __majority_vote(assignments) + + #for var, a in assignments.items(): + ##print(var, np.sort(a["all"]), __majority_percentage(a["all"])) + #print(var, a) + final = __extract_assignment(assignments) + print(final) + print("satisfies sat: {}".format(sat.checkAssignment(final))) + + if sat.checkAssignment(final): + sat_count += 1 + + print("sat ratio: {}".format(sat_count / (200 - no_embedding_count))) def __optimize_assignment(sat, assignment, consistencies): rnd = random.Random() @@ -237,7 +249,7 @@ def __majority_percentage(a): return true_perc if true_perc >= 0.5 else 1 - true_perc def __pqubo(): - sat = rand_sat.generateRandomKSAT(25, 6, 3) + sat = rand_sat.generateRandomKSAT(42, 7, 3) ising = SAT2QUBO.primitiveQUBO(sat) nx_qubo = __qubo_to_nx_graph(ising) @@ -260,9 +272,167 @@ def __pqubo(): h, J = __split_ising(ising) res = sampler.sample_ising(h, J) - #res = QBSolv().sample_qubo(qubo, find_max=True) + #res = sampler.sample_ising(h, J, find_max=False) - print(res.first) + print(res.truncate(10)) + + sample = res.first.sample + + extracted = {} + + r = re.compile("c\d+_l-?\d*") + + for label, assignment in sample.items(): + if r.fullmatch(label): + + extracted[tuple(re.split(r"\_l", label[1:]))] = assignment + + model = [True for i in range(len(extracted))] + + assignments = {} + + for label, assignment in extracted.items(): + clause = int(label[0]) + lit = int(label[1]) + var = abs(lit) + + if lit < 0: + assignment *= -1 + + if var in assignments: + assignments[var].append(assignment) + else: + assignments[var] = [assignment] + + + conflicts = False + for var, a in assignments.items(): + if abs(np.sum(a)) != len(a): + conflicts = True + print("conflicts - no solution found") + print(var, np.sort(a)) + + if conflicts: + print(assignments) + return + + model = [True for i in range(sat.getNumberOfVariables())] + + for var, assignment in assignments.items(): + model[var - 1] = True if assignment[0] > 0 else False + + print(model, sat.checkAssignment(model)) + +def __pqubo_3(): + sat_count = 0 + no_embedding_count = 0 + + for i in range(200): + sat = rand_sat.generateRandomKSAT(40, 14, 3) + #ising = SAT2QUBO.primitiveQUBO_8(sat) + ising = SAT2QUBO.WMISdictQUBO_2(sat) + nx_qubo = __qubo_to_nx_graph(ising) + + target_graph = dnx.chimera_graph(16, 16, 4) + + emb = minorminer.find_embedding(nx_qubo.edges(), + target_graph.edges(), + return_overlap=True) + + if emb[1] != 1: + print("no embedding found") + no_embedding_count += 1 + continue + + chimera_sampler = dimod.StructureComposite(SimulatedAnnealingSampler(), + target_graph.nodes(), + target_graph.edges()) + + sampler = FixedEmbeddingComposite(chimera_sampler, emb[0]) + + + h, J = __split_ising(ising) + + res = sampler.sample_qubo(ising) + #res = sampler.sample_ising(h, J, find_max=False) + + print(res.truncate(10)) + + print("chain_break_fraction", res.first.chain_break_fraction) + + sample = res.first.sample + + assignments = {} + vars = set() + + for node, energy in sample.items(): + if node[0] == "x": + lit = int(node[1:]) + + vars.add(abs(lit)) + + assignments[lit] = energy + + print(assignments) + + conflicts = set() + for var in vars: + if var in assignments and -var in assignments: + if assignments[var] == assignments[-var]: + print("conflict at var: {}".format(var)) + conflicts.add(var) + + #if conflicts: + # return + + model = [True for i in range(len(vars))] + + for var in vars: + if var in assignments: + model[var - 1] = True if assignments[var] == 1 else False + elif -var in assignments: + model[var - 1] = True if assignments[-var] == 0 else False + + + + var_list = list(conflicts) + + print(sat.checkAssignment(model)) + if len(var_list) > 0: + for i in range(1000): + + if sat.checkAssignment(model): + print(i) + break + + rand_var = random.choice(var_list) + + model[rand_var - 1] = not model[rand_var - 1] + + + print() + + print(model) + print() + + print(sat.checkAssignment(model)) + if sat.checkAssignment(model): + sat_count += 1 + print() + + degrees = sat.getDegreesOfVariables() + + for var in conflicts: + node_var = "x{}".format(var) + node_nvar = "x{}".format(-var) + print("var {}: deg={}, coupler={}, e={}, ne={}" + .format(var, + degrees[var], + ising[(node_var, node_nvar)], + assignments[var], + assignments[-var])) + + print("sat ratio: {}".format(sat_count / (200 - no_embedding_count))) def __split_ising(ising): h = {} diff --git a/util/SAT2QUBO.py b/util/SAT2QUBO.py index 053a043..a602062 100644 --- a/util/SAT2QUBO.py +++ b/util/SAT2QUBO.py @@ -4,9 +4,10 @@ import numpy as np from . import kSAT from tqdm import tqdm import math +import random -__VERTEX_WEIGHT__ = -1 -__EDGE_WEIGHT__ = 2 +__VERTEX_WEIGHT__ = -2#-1 +__EDGE_WEIGHT__ = 2#2 def WMISdictQUBO(kSATInstance): quboInstance = {} @@ -32,6 +33,37 @@ def WMISdictQUBO(kSATInstance): return quboInstance +def WMISdictQUBO_2(kSATInstance): + quboInstance = {} + + for clauseIndex in range(kSATInstance.getNumberOfClauses()): + clause = kSATInstance.getClause(clauseIndex) + + # build triangles + for varIndexInClause in range(len(clause)): + lit = clause[varIndexInClause] + var = abs(lit) + + aux = "z{}_{}".format(clauseIndex, var) + var_node = "x{}".format(var) + + if lit < 0: + quboInstance[(aux, aux)] = __VERTEX_WEIGHT__ + quboInstance[(var_node, aux)] = __EDGE_WEIGHT__ + else: + quboInstance[(var_node, aux)] = __VERTEX_WEIGHT__ + + + + for i in range(varIndexInClause + 1, len(clause)): + var2 = abs(clause[i]) + + aux2 = "z{}_{}".format(clauseIndex, var2) + + quboInstance[(aux, aux2)] = __EDGE_WEIGHT__ + + return quboInstance + # only 3sat def primitiveQUBO(sat): quboInstance = {} @@ -47,10 +79,10 @@ def primitiveQUBO(sat): lit1 = "c{}_l{}".format(clauseIndex, clause[0]) lit2 = "c{}_l{}".format(clauseIndex, clause[1]) lit3 = "c{}_l{}".format(clauseIndex, clause[2]) - aux1 = "a{}_{}".format(clauseIndex, 1) - aux2 = "a{}_{}".format(clauseIndex, 2) - aux3 = "a{}_{}".format(clauseIndex, 3) - aux4 = "a{}_{}".format(clauseIndex, 4) + aux1 = "z{}_{}".format(clauseIndex, 1) + aux2 = "z{}_{}".format(clauseIndex, 2) + aux3 = "z{}_{}".format(clauseIndex, 3) + aux4 = "z{}_{}".format(clauseIndex, 4) quboInstance[(lit1, lit1)] = 1; quboInstance[(lit2, lit2)] = 1; @@ -91,7 +123,15 @@ def primitiveQUBO(sat): longestChain = len(nodes) if lit > 0 and -1 * lit in chains: - quboInstance[(chains[lit][0], chains[-1*lit][0])] = 2 + len_smaller_chain = min(len(chains[lit]), len(chains[-lit])) + + indices = random.sample(list(range(len_smaller_chain)), + round(len_smaller_chain / 2)) + + for index in indices: + quboInstance[(chains[lit][index], chains[-1*lit][index])] = 10 + + #quboInstance[(chains[lit][0], chains[-1*lit][0])] = 2 print("longest chain = {}".format(longestChain)) @@ -101,6 +141,574 @@ def primitiveQUBO(sat): nodes.pop(0) return quboInstance + +# only 3sat +def primitiveQUBO_2(sat): + quboInstance = {} + + chains = {} + + for clauseIndex in range(sat.getNumberOfClauses()): + clause = sat.getClause(clauseIndex) + + lit1 = clause[0] + lit2 = clause[1] + lit3 = clause[2] + + var1 = abs(lit1) + var2 = abs(lit2) + var3 = abs(lit3) + + sign1 = 1 if lit1 > 0 else -1 + sign2 = 1 if lit2 > 0 else -1 + sign3 = 1 if lit3 > 0 else -1 + + node_var1 = "x{}".format(var1) + node_var2 = "x{}".format(var2) + node_var3 = "x{}".format(var3) + + node_aux1 = "a{}_{}".format(clauseIndex, 1) + node_aux2 = "a{}_{}".format(clauseIndex, 2) + node_aux3 = "a{}_{}".format(clauseIndex, 3) + node_aux4 = "a{}_{}".format(clauseIndex, 4) + + + quboInstance[(node_var1, node_var1)] = 1 * sign1 + quboInstance[(node_var2, node_var2)] = 1 * sign2 + quboInstance[(node_var3, node_var3)] = 1 * sign3 + quboInstance[(node_aux1, node_aux1)] = -2 + quboInstance[(node_aux2, node_aux2)] = 1 + quboInstance[(node_aux3, node_aux3)] = -2 + quboInstance[(node_aux4, node_aux4)] = -2 + + quboInstance[(node_var1, node_var2)] = 1 * sign1 * sign2 + quboInstance[(node_var1, node_aux1)] = -2 * sign1 + quboInstance[(node_var2, node_aux1)] = -2 * sign2 + quboInstance[(node_aux1, node_aux2)] = -2 + quboInstance[(node_aux2, node_var3)] = 1 * sign3 + + quboInstance[(node_var3, node_aux3)] = -2 * sign3 + quboInstance[(node_aux2, node_aux3)] = -2 + quboInstance[(node_var3, node_aux4)] = -2 + + return quboInstance + +# only 3sat +def primitiveQUBO_3(sat): + quboInstance = {} + + chains = {} + + lits = {} + vars = {} + + n_clauses = sat.getNumberOfClauses() + + for clauseIndex in range(sat.getNumberOfClauses()): + clause = sat.getClause(clauseIndex) + + lit1 = clause[0] + lit2 = clause[1] + lit3 = clause[2] + + lits[lit1] = True + lits[lit2] = True + lits[lit3] = True + + var1 = abs(lit1) + var2 = abs(lit2) + var3 = abs(lit3) + + vars[var1] = True + vars[var2] = True + vars[var3] = True + + node_lit1 = "x{}".format(lit1) + node_lit2 = "x{}".format(lit2) + node_lit3 = "x{}".format(lit3) + + node_aux1 = "z{}_{}".format(clauseIndex, 1) + node_aux2 = "z{}_{}".format(clauseIndex, 2) + node_aux3 = "z{}_{}".format(clauseIndex, 3) + node_aux4 = "z{}_{}".format(clauseIndex, 4) + + + quboInstance[(node_lit1, node_lit1)] = 1 + quboInstance[(node_lit2, node_lit2)] = 1 + quboInstance[(node_lit3, node_lit3)] = 1 + quboInstance[(node_aux1, node_aux1)] = -2 + quboInstance[(node_aux2, node_aux2)] = 1 + quboInstance[(node_aux3, node_aux3)] = -2 + quboInstance[(node_aux4, node_aux4)] = -2 + + quboInstance[(node_lit1, node_lit2)] = 1 + quboInstance[(node_lit1, node_aux1)] = -2 + quboInstance[(node_lit2, node_aux1)] = -2 + + quboInstance[(node_aux1, node_aux2)] = -2 + + quboInstance[(node_aux2, node_lit3)] = 1 + quboInstance[(node_lit3, node_aux3)] = -2 + quboInstance[(node_aux2, node_aux3)] = -2 + + quboInstance[(node_aux3, node_aux4)] = -2 + + for var in vars.keys(): + if var in lits and -var in lits: + node_var = "x{}".format(var) + node_nvar = "x{}".format(-var) + + print((node_var, node_nvar)) + quboInstance[(node_var, node_nvar)] = 2 + + return quboInstance + +def primitiveQUBO_4(sat): + quboInstance = {} + + + clauses_per_lit = {} + + lits = {} + vars = {} + + n_clauses = sat.getNumberOfClauses() + + master_z = "zm" + + #quboInstance[(master_z, master_z)] = -2 + + for clauseIndex in range(sat.getNumberOfClauses()): + clause = sat.getClause(clauseIndex) + + lit1 = clause[0] + lit2 = clause[1] + lit3 = clause[2] + + lits[lit1] = True + lits[lit2] = True + lits[lit3] = True + + sign1 = 1 if lit1 > 0 else -1 + sign2 = 1 if lit2 > 0 else -1 + sign3 = 1 if lit3 > 0 else -1 + + for lit in clause: + if lit in clauses_per_lit: + clauses_per_lit[lit] += 1 + else: + clauses_per_lit[lit] = 1 + + var1 = abs(lit1) + var2 = abs(lit2) + var3 = abs(lit3) + + vars[var1] = True + vars[var2] = True + vars[var3] = True + + node_lit1 = "x{}".format(lit1) + node_lit2 = "x{}".format(lit2) + node_lit3 = "x{}".format(lit3) + + node_aux = "z{}".format(clauseIndex) + + #quboInstance[(node_aux, node_aux)] = -2 + #quboInstance[(node_aux, master_z)] = -2 + + #quboInstance[(node_lit1, node_lit1)] = +1 #* sign3 + #quboInstance[(node_lit2, node_lit2)] = +1 #* sign3 + #quboInstance[(node_lit3, node_lit3)] = +1 #* sign3 + + quboInstance[(node_lit1, node_aux)] = -2 #* sign1 + quboInstance[(node_lit2, node_aux)] = -2 #* sign2 + quboInstance[(node_lit3, node_aux)] = -2 #* sign3 + + for lit in lits.keys(): + node_lit = "x{}".format(lit) + + #quboInstance[(node_lit, node_lit)] = 2 * clauses_per_lit[lit] + + for var in vars.keys(): + if var in lits and -var in lits: + node_var = "x{}".format(var) + node_nvar = "x{}".format(-var) + + max_clauses = max(clauses_per_lit[var], clauses_per_lit[-var]) + num_clauses = clauses_per_lit[var] + clauses_per_lit[-var] + + print((node_var, node_nvar)) + quboInstance[(node_var, node_nvar)] = 2 * num_clauses + #quboInstance[(node_var, node_nvar)] = 2# * num_clauses + + return quboInstance + +def primitiveQUBO_5(sat): + quboInstance = {} + + + clauses_per_lit = {} + + lits = {} + vars = {} + + n_clauses = sat.getNumberOfClauses() + + master_z = "zm" + + #quboInstance[(master_z, master_z)] = -2 + + for clauseIndex in range(sat.getNumberOfClauses()): + clause = sat.getClause(clauseIndex) + + lit1 = clause[0] + lit2 = clause[1] + lit3 = clause[2] + + lits[lit1] = True + lits[lit2] = True + lits[lit3] = True + + for lit in clause: + if lit in clauses_per_lit: + clauses_per_lit[lit] += 1 + else: + clauses_per_lit[lit] = 1 + + var1 = abs(lit1) + var2 = abs(lit2) + var3 = abs(lit3) + + vars[var1] = True + vars[var2] = True + vars[var3] = True + + node_lit1 = "x{}".format(lit1) + node_lit2 = "x{}".format(lit2) + node_lit3 = "x{}".format(lit3) + + node_aux1 = "z{}_1".format(clauseIndex) + node_aux2 = "z{}_2".format(clauseIndex) + + quboInstance[(node_lit1, node_aux1)] = -2 + quboInstance[(node_lit2, node_aux1)] = -2 + quboInstance[(node_lit1, node_lit2)] = +2 + + quboInstance[(node_aux1, node_lit3)] = +2 + quboInstance[(node_lit3, node_aux2)] = -2 + + + + for var in vars.keys(): + if var in lits and -var in lits: + node_var = "x{}".format(var) + node_nvar = "x{}".format(-var) + + max_clauses = max(clauses_per_lit[var], clauses_per_lit[-var]) + num_clauses = clauses_per_lit[var] + clauses_per_lit[-var] + + #print((node_var, node_nvar)) + quboInstance[(node_var, node_nvar)] = 2 * max_clauses + + return quboInstance + +def primitiveQUBO_6(sat): + quboInstance = {} + + + clauses_per_lit = {} + + lits = {} + vars = {} + + n_clauses = sat.getNumberOfClauses() + + master_z = "zm" + + #quboInstance[(master_z, master_z)] = -2 + + for clauseIndex in range(sat.getNumberOfClauses()): + clause = sat.getClause(clauseIndex) + + lit1 = clause[0] + lit2 = clause[1] + lit3 = clause[2] + + lits[lit1] = True + lits[lit2] = True + lits[lit3] = True + + for lit in clause: + if lit in clauses_per_lit: + clauses_per_lit[lit] += 1 + else: + clauses_per_lit[lit] = 1 + + var1 = abs(lit1) + var2 = abs(lit2) + var3 = abs(lit3) + + vars[var1] = True + vars[var2] = True + vars[var3] = True + + node_lit1 = "x{}".format(lit1) + node_lit2 = "x{}".format(lit2) + node_lit3 = "x{}".format(lit3) + + node_aux1 = "z{}_1".format(clauseIndex) + node_aux2 = "z{}_2".format(clauseIndex) + node_aux3 = "z{}_3".format(clauseIndex) + node_aux4 = "z{}_4".format(clauseIndex) + + quboInstance[(node_lit1, node_aux1)] = -2 + quboInstance[(node_lit2, node_aux2)] = -2 + quboInstance[(node_aux1, node_aux2)] = +2 + + quboInstance[(node_aux1, node_aux3)] = -2 + quboInstance[(node_aux2, node_aux3)] = -2 + + quboInstance[(node_aux1, node_aux1)] = +2 + quboInstance[(node_aux2, node_aux2)] = +2 + + quboInstance[(node_aux3, node_lit3)] = +2 + quboInstance[(node_lit3, node_aux4)] = -2 + + + + for var in vars.keys(): + if var in lits and -var in lits: + node_var = "x{}".format(var) + node_nvar = "x{}".format(-var) + + max_clauses = max(clauses_per_lit[var], clauses_per_lit[-var]) + num_clauses = clauses_per_lit[var] + clauses_per_lit[-var] + + #print((node_var, node_nvar)) + quboInstance[(node_var, node_nvar)] = 2 * max_clauses + + return quboInstance + +def primitiveQUBO_7(sat): + quboInstance = {} + + + clauses_per_lit = {} + + lits = {} + vars = {} + + n_clauses = sat.getNumberOfClauses() + + master_z = "zm" + + #quboInstance[(master_z, master_z)] = -2 + direct_cupplers = {} + + for clauseIndex in range(sat.getNumberOfClauses()): + clause = sat.getClause(clauseIndex) + + lit1 = clause[0] + lit2 = clause[1] + lit3 = clause[2] + + lits[lit1] = True + lits[lit2] = True + lits[lit3] = True + + for lit in clause: + if lit in clauses_per_lit: + clauses_per_lit[lit] += 1 + else: + clauses_per_lit[lit] = 1 + + var1 = abs(lit1) + var2 = abs(lit2) + var3 = abs(lit3) + + vars[var1] = True + vars[var2] = True + vars[var3] = True + + node_lit1 = "x{}".format(lit1) + node_lit2 = "x{}".format(lit2) + node_lit3 = "x{}".format(lit3) + + node_aux1 = "z{}_1".format(clauseIndex) + node_aux2 = "z{}_2".format(clauseIndex) + + quboInstance[(node_lit1, node_aux1)] = -2 + quboInstance[(node_lit2, node_aux1)] = -2 + quboInstance[(node_lit1, node_lit2)] = +2 + + quboInstance[(node_aux1, node_lit3)] = +2 + quboInstance[(node_lit3, node_aux2)] = -2 + + + + if (node_lit1, node_lit2) in direct_cupplers: + direct_cupplers[(node_lit1, node_lit2)] += 1 + else: + direct_cupplers[(node_lit1, node_lit2)] = 1 + + + + for var in vars.keys(): + if var in lits and -var in lits: + node_var = "x{}".format(var) + node_nvar = "x{}".format(-var) + + max_clauses = max(clauses_per_lit[var], clauses_per_lit[-var]) + num_clauses = clauses_per_lit[var] + clauses_per_lit[-var] + + print((node_var, node_nvar)) + quboInstance[(node_var, node_nvar)] = 2 * max_clauses + + + for coupler, count in direct_cupplers.items(): + quboInstance[coupler] = count * 2 + + + return quboInstance + +def primitiveQUBO_8(sat): + quboInstance = {} + + + clauses_per_lit = {} + + lits = {} + vars = {} + + n_clauses = sat.getNumberOfClauses() + + direct_cupplers = {} + + for clauseIndex in range(sat.getNumberOfClauses()): + clause = sorted(sat.getClause(clauseIndex)) + + if clause[2] < 0: + __add_3not_or_clause(quboInstance, clause, clauseIndex) + elif clause[1] < 0: + __add_2not_or_clause(quboInstance, clause, clauseIndex) + elif clause[0] < 0: + __add_1not_or_clause(quboInstance, clause, clauseIndex, direct_cupplers) + else: + __add_3_or_clause(quboInstance, clause, clauseIndex, direct_cupplers) + + + for coupler, count in direct_cupplers.items(): + quboInstance[coupler] = count * 2 + + + return quboInstance + +def __add_3not_or_clause(quboInstance, clause, clause_index): + var1 = abs(clause[0]) + var2 = abs(clause[1]) + var3 = abs(clause[2]) + + + node_var1 = "x{}".format(var1) + node_var2 = "x{}".format(var2) + node_var3 = "x{}".format(var3) + + node_aux1 = "z{}_1".format(clause_index) + node_aux2 = "z{}_2".format(clause_index) + node_aux3 = "z{}_3".format(clause_index) + + quboInstance[(node_var1, node_aux1)] = +2 + quboInstance[(node_var2, node_aux2)] = +2 + quboInstance[(node_aux1, node_aux2)] = +2 + + quboInstance[(node_aux1, node_aux1)] = -2 + quboInstance[(node_aux2, node_aux2)] = -2 + + quboInstance[(node_var1, node_aux3)] = -2 + quboInstance[(node_var2, node_aux3)] = -2 + quboInstance[(node_var3, node_aux3)] = +2 + quboInstance[(node_aux3, node_aux3)] = +2 + +def __add_2not_or_clause(quboInstance, clause, clause_index): + var1 = abs(clause[0]) + var2 = abs(clause[1]) + var3 = abs(clause[2]) + + + node_var1 = "x{}".format(var1) + node_var2 = "x{}".format(var2) + node_var3 = "x{}".format(var3) + + node_aux1 = "z{}_1".format(clause_index) + node_aux2 = "z{}_2".format(clause_index) + node_aux3 = "z{}_3".format(clause_index) + node_aux4 = "z{}_4".format(clause_index) + node_aux5 = "z{}_5".format(clause_index) + + quboInstance[(node_var1, node_aux1)] = +2 + quboInstance[(node_var2, node_aux2)] = +2 + quboInstance[(node_aux1, node_aux2)] = +2 + + quboInstance[(node_aux1, node_aux3)] = -2 + quboInstance[(node_aux2, node_aux3)] = -2 + quboInstance[(node_aux3, node_aux3)] = +2 + + quboInstance[(node_aux3, node_aux4)] = -2 + quboInstance[(node_var3, node_aux5)] = -2 + quboInstance[(node_aux4, node_aux5)] = +2 + +def __add_1not_or_clause(quboInstance, clause, clause_index, direct_cupplers): + var1 = abs(clause[1]) + var2 = abs(clause[2]) + var3 = abs(clause[0]) + + + node_var1 = "x{}".format(var1) + node_var2 = "x{}".format(var2) + node_var3 = "x{}".format(var3) + + node_aux1 = "z{}_1".format(clause_index) + node_aux2 = "z{}_2".format(clause_index) + + quboInstance[(node_var1, node_var2)] = +2 + quboInstance[(node_var1, node_aux1)] = -2 + quboInstance[(node_var2, node_aux1)] = -2 + + quboInstance[(node_aux1, node_aux2)] = +2 + quboInstance[(node_var3, node_aux2)] = +2 + + quboInstance[(node_aux2, node_aux2)] = -2 + + if (node_var1, node_var2) in direct_cupplers: + direct_cupplers[(node_var1, node_var2)] += 1 + else: + direct_cupplers[(node_var1, node_var2)] = 1 + +def __add_3_or_clause(quboInstance, clause, clause_index, direct_cupplers): + var1 = abs(clause[0]) + var2 = abs(clause[1]) + var3 = abs(clause[2]) + + + node_var1 = "x{}".format(var1) + node_var2 = "x{}".format(var2) + node_var3 = "x{}".format(var3) + + node_aux1 = "z{}_1".format(clause_index) + node_aux2 = "z{}_2".format(clause_index) + + quboInstance[(node_var1, node_var2)] = +2 + quboInstance[(node_var1, node_aux1)] = -2 + quboInstance[(node_var2, node_aux1)] = -2 + + quboInstance[(node_aux1, node_var3)] = +2 + quboInstance[(node_var3, node_aux2)] = -2 + + if (node_var1, node_var2) in direct_cupplers: + direct_cupplers[(node_var1, node_var2)] += 1 + else: + direct_cupplers[(node_var1, node_var2)] = 1 + class QuboWriter: def __init__(self, qubo): diff --git a/util/graph.py b/util/graph.py index bcb8ff2..86ff221 100644 --- a/util/graph.py +++ b/util/graph.py @@ -25,3 +25,15 @@ def create_qpu_solver_nxgraph(solver): graph.add_edges_from(solver.edges) return graph + +def split_ising(ising): + h = {} + J = {} + + for coupler, energy in ising.items(): + if coupler[0] == coupler[1]: + h[coupler[0]] = energy + else: + J[coupler] = energy + + return h, J diff --git a/util/queries.py b/util/queries.py index ea4232d..91c3551 100644 --- a/util/queries.py +++ b/util/queries.py @@ -59,6 +59,56 @@ class Instance_scope_query: return sat, document["_id"] +class Qubo_ising_scope_query_raw: + def __init__(self, database, collection): + self.__database = database + self.__collection = collection + self.__query = None + self.__qubo_ids = [] + self.__qubo_id_iterator = None + + def query(self, scope): + self.__query = self.__database["experiment_scopes"].aggregate([ + { + "$match": {"_id": scope} + }, + { + "$unwind": "$instances" + }, + { + "$lookup": + { + "from": self.__collection, + "localField": "instances", + "foreignField": "instance", + "as": "qubo" + } + }, + { + "$unwind": "$qubo" + }, + { + "$project": {"qubo_id": "$qubo._id"} + } + ]) + + self.__qubo_ids = [] + for doc in self.__query: + self.__qubo_ids.append(doc["qubo_id"]) + + self.__qubo_id_iterator = iter(self.__qubo_ids) + + def __len__(self): + return self.query.count_documents({}) + + def __iter__(self): + return self + + def __next__(self): + qubo_filter = {"_id": self.__qubo_id_iterator.__next__()} + + return self.__database[self.__collection].find_one(qubo_filter) + class WMIS_scope_query_raw: def __init__(self, database): @@ -115,12 +165,27 @@ class WMIS_scope_query (WMIS_scope_query_raw): doc = super(WMIS_scope_query, self).__next__() + return read_raw_qubo(doc["qubo"]), doc["_id"] + +class Ising_scope_query (Qubo_ising_scope_query_raw): + + def __next__(self): + doc = super(Ising_scope_query, self).__next__() + + return read_raw_ising(doc["qubo"]), doc["_id"] + +class Qubo_scope_query (Qubo_ising_scope_query_raw): + + def __next__(self): + doc = super(Qubo_scope_query, self).__next__() + return read_raw_qubo(doc["qubo"]), doc["_id"] class WMIS_solver_input_scope_query_raw: - def __init__(self, database): + def __init__(self, database, ising_qubo_collection): self.__database = database + self.__ising_qubo_collection = ising_qubo_collection self.__query = None self.__ids = [] self.__id_iterator = None; @@ -139,7 +204,7 @@ class WMIS_solver_input_scope_query_raw: { "$lookup": { - "from": "wmis_qubos", + "from": self.__ising_qubo_collection, "localField": "instance_id", "foreignField": "instance", "as": "wmis_qubo" @@ -230,7 +295,9 @@ class WMIS_solver_input_scope_query_raw: doc["instance_id"] = ids["instance_id"] qubo_filter = {"_id": ids["wmis_qubo_id"]} - doc["wmis_qubo"] = self.__database["wmis_qubos"].find_one(qubo_filter) + + ising_qubo_collection = self.__database[self.__ising_qubo_collection] + doc["wmis_qubo"] = ising_qubo_collection.find_one(qubo_filter) embeddings_filter = {"_id": ids["embeddings_id"]} doc["embeddings"] = self.__database["embeddings"].find_one(embeddings_filter) @@ -257,6 +324,26 @@ class WMIS_solver_input_scope_query (WMIS_solver_input_scope_query_raw): return data +class Ising_solver_input_scope_query (WMIS_solver_input_scope_query_raw): + + def __next__(self): + doc = super(Ising_solver_input_scope_query, self).__next__() + + data = {} + + data["instance_id"] = doc["instance_id"] + + data["qubo_id"] = doc["wmis_qubo"]["_id"] + data["qubo"] = read_raw_ising(doc["wmis_qubo"]["qubo"]) + + data["embeddings_id"] = doc["embeddings"]["_id"] + + data["embeddings"] = [] + for raw_emb in doc["embeddings"]["embeddings"]: + data["embeddings"].append(read_raw_ising_embedding(raw_emb)) + + return data + class WMIS_result_scope_query_raw: def __init__(self, database): self.__database = database @@ -395,6 +482,19 @@ def read_raw_qubo(raw_qubo): return qubo +def read_raw_ising(raw_ising): + ising = {} + + for entry in raw_ising: + energy = entry[1] + raw_coupler = entry[0] + node1 = raw_coupler[0] + node2 = raw_coupler[1] + + ising[(node1, node2)] = energy + + return ising + def read_raw_embedding(raw_embedding): emb = {} @@ -406,6 +506,17 @@ def read_raw_embedding(raw_embedding): return emb +def read_raw_ising_embedding(raw_embedding): + emb = {} + + if "embedding" in raw_embedding: + raw_embedding = raw_embedding["embedding"] + + for entry in raw_embedding: + emb[entry[0]] = entry[1] + + return emb + def read_raw_wmis_sample_set(raw_sample_set): sample_set_data = raw_sample_set.copy() @@ -416,6 +527,16 @@ def read_raw_wmis_sample_set(raw_sample_set): return dimod.SampleSet.from_serializable(sample_set_data) +def read_raw_primitive_ising_sample_set(raw_sample_set): + sample_set_data = raw_sample_set.copy() + + sample_set_data["variable_labels"] = [] + + for label in raw_sample_set["variable_labels"]: + sample_set_data["variable_labels"].append("".join(label)) + + return dimod.SampleSet.from_serializable(sample_set_data) + def get_instance_by_id(collection, id): doc = collection.find_one({"_id": bson.ObjectId(id)}) @@ -425,4 +546,21 @@ def get_instance_by_id(collection, id): sat.addClause(clause); return sat + +def extract_primitive_ising_model(sample): + variable_bindings = {} + + for node, energy in sample.items(): + if node[0] == "x": + var = int(node[1:]) + variable_bindings[var] = True if energy > 0 else False + + model = [True for i in range(len(variable_bindings))] + + for var, binding in variable_bindings.items(): + model[var - 1] = binding + + return model + + diff --git a/util/script.py b/util/script.py index aff6624..ea4b4e0 100644 --- a/util/script.py +++ b/util/script.py @@ -186,7 +186,43 @@ def create_wmis_qubos_for_scope(db, scope): for instance, instance_id in instances: qubo = SAT2QUBO.WMISdictQUBO(instance) - write_qubo_to_pool_db(db["wmis_qubos"], qubo, instance_id) + write_qubo_to_pool_db(db["wmis_qubos_2"], qubo, instance_id) + +def create_wmis_2_qubos_for_scope(db, scope): + instances = queries.Instance_scope_query(db) + instances.query(scope) + + for instance, instance_id in instances: + qubo = SAT2QUBO.WMISdictQUBO_2(instance) + + write_qubo_to_pool_db(db["wmis_2_qubos"], qubo, instance_id) + +def create_primitive_isings_for_scope_2(db, scope): + instances = queries.Instance_scope_query(db) + instances.query(scope) + + for instance, instance_id in instances: + ising = SAT2QUBO.primitiveQUBO_2(instance) + + write_qubo_to_pool_db(db["primitive_isings_2"], ising, instance_id) + +def create_primitive_qubo_for_scope_5(db, scope): + instances = queries.Instance_scope_query(db) + instances.query(scope) + + for instance, instance_id in tqdm(instances): + ising = SAT2QUBO.primitiveQUBO_5(instance) + + write_qubo_to_pool_db(db["primitive_isings_5"], ising, instance_id) + +def create_primitive_qubo_for_scope_8(db, scope): + instances = queries.Instance_scope_query(db) + instances.query(scope) + + for instance, instance_id in tqdm(instances): + ising = SAT2QUBO.primitiveQUBO_8(instance) + + write_qubo_to_pool_db(db["primitive_isings_8"], ising, instance_id) def __qubo_to_JSON(qubo): quboJSON = [] @@ -305,6 +341,53 @@ def find_wmis_embeddings_for_scope(db, scope, solver_graph): total_count, percentage)) print("{} new embeddigns found".format(new_embeddings_found)) + +def find_embeddings_for_scope(db, solver_graph, qubo_ising_query): + solver_graph_id = write_solver_graph_to_pool_db(db["solver_graphs"], + solver_graph) + + new_embeddings_found = 0 + already_found = 0 + total_count = 0 + for qubo, qubo_id in tqdm(qubo_ising_query): + total_count += 1 + + max_no_improvement = 10 + for i in range(5): + if __embedding_entry_exists(db["embeddings"], qubo_id, solver_graph_id): + if i == 0: + already_found += 1 + break; + else: + nx_qubo = graph.qubo_to_nx_graph(qubo) + + seed = random.randint(0, sys.maxsize) + + emb = minorminer.find_embedding(nx_qubo.edges(), + solver_graph.edges(), + return_overlap=True, + max_no_improvement=max_no_improvement, + random_seed=seed) + + if emb[1] == 1: + write_wmis_embedding_to_pool_db(db["embeddings"], + qubo_id, + solver_graph_id, + seed, + emb[0]) + new_embeddings_found += 1 + + max_no_improvement *= 1.5 + + percentage = 0 + + if total_count > 0: + percentage = round(((new_embeddings_found + already_found) / total_count) * 100) + + print("found {} of {} embeddigns ({}%)".format(new_embeddings_found + already_found, + total_count, + percentage)) + print("{} new embeddigns found".format(new_embeddings_found)) def save_sample_set(collection, result, solver_input, emb_list_index, run): doc = {}