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

#!/usr/bin/env python3
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
import numpy as np
import re
def frange(start, stop, steps):
while start < stop:
yield start
start += steps
def test_kv_range():
k = 75
data = {
"p_node_counts" : [],
"wmis_node_counts" : [],
"p_conn_counts" : [],
"wmis_conn_counts" : [],
"a_arr" : [],
"k_arr" : []
}
target = dnx.chimera_graph(25, 25, 4)
print(target.number_of_nodes())
for r in range(2):
#for k in range(50, 5001, 50):
for a in frange(3.5, 5.5, 0.1):
#v = int(k/4)
#a = k/v
v = int(k/a)
print("k={} v={} k/v={}".format(k, v, k/v))
ksatInstance = rs.generateRandomKSAT(k, v, 3)
p_qubo = s2q.primitiveQUBO_5(ksatInstance)
wmis_qubo = s2q.WMISdictQUBO(ksatInstance)
qg = nx.Graph()
for coupler, energy in wmis_qubo.items():
if coupler[0] != coupler[1]:
qg.add_edge(coupler[0], coupler[1], weight=energy)
ig = nx.Graph()
for coupler, energy in p_qubo.items():
if coupler[0] != coupler[1]:
ig.add_edge(coupler[0], coupler[1], weight=energy)
qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True, threads=8)
print("wmis emb. found: {}".format(qemb[1]))
iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True, threads=8)
print("primitive emb. found: {}".format(iemb[1]))
if qemb[1] == 0 or iemb[1] == 0:
print()
continue
p_node_count = 0;
p_conn_count = 0;
used_nodes = []
for var, chain in iemb[0].items():
used_nodes.extend(chain)
p_node_count = len(np.unique(used_nodes))
wmis_node_count = 0;
wmis_conn_count = 0;
used_nodes = []
for var, chain in qemb[0].items():
used_nodes.extend(chain)
wmis_node_count = len(np.unique(used_nodes))
#print("p_qubo: nodes={} connections={}".format(p_node_count, p_conn_count))
#print("wmis_qubo: nodes={} connections={}".format(wmis_node_count, wmis_conn_count))
print("p_qubo nodes= {}".format(p_node_count));
print("wwmis qubo nodes= {}".format(wmis_node_count));
print("nodes= {}".format(p_node_count / wmis_node_count));
#print("conns= {}".format(p_conn_count / wmis_conn_count));
data["p_node_counts"].append(p_node_count)
data["wmis_node_counts"].append(wmis_node_count)
data["p_conn_counts"].append(p_conn_count)
data["wmis_conn_counts"].append(wmis_conn_count)
data["a_arr"].append(k/v)
data["k_arr"].append(k)
print()
sns.set()
ax = sns.scatterplot(x="a_arr", y="p_node_counts", data=data, label="p_qubo")
ax.set(xlabel='k/v', ylabel='used verticies after embedding')
ax = sns.scatterplot(x="a_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo")
plt.show()
def test_k_range():
k = 75
data = {
"p_node_counts" : [],
"wmis_node_counts" : [],
"p_conn_counts" : [],
"wmis_conn_counts" : [],
"a_arr" : [],
"k_arr" : []
}
target = dnx.chimera_graph(25, 25, 4)
print(target.number_of_nodes())
for r in range(2):
for k in range(15, 76, 1):
v = int(k/4)
print("k={} v={} k/v={}".format(k, v, k/v))
ksatInstance = rs.generateRandomKSAT(k, v, 3)
p_qubo = s2q.primitiveQUBO(ksatInstance)
wmis_qubo = s2q.WMISdictQUBO(ksatInstance)
qg = nx.Graph()
for coupler, energy in wmis_qubo.items():
if coupler[0] != coupler[1]:
qg.add_edge(coupler[0], coupler[1], weight=energy)
ig = nx.Graph()
for coupler, energy in p_qubo.items():
if coupler[0] != coupler[1]:
ig.add_edge(coupler[0], coupler[1], weight=energy)
qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True, threads=8)
print("wmis emb. found: {}".format(qemb[1]))
iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True, threads=8)
print("primitive emb. found: {}".format(iemb[1]))
if qemb[1] == 0 or iemb[1] == 0:
print()
continue
p_node_count = 0;
p_conn_count = 0;
used_nodes = []
for var, chain in iemb[0].items():
used_nodes.extend(chain)
p_node_count = len(np.unique(used_nodes))
wmis_node_count = 0;
wmis_conn_count = 0;
used_nodes = []
for var, chain in qemb[0].items():
used_nodes.extend(chain)
wmis_node_count = len(np.unique(used_nodes))
#print("p_qubo: nodes={} connections={}".format(p_node_count, p_conn_count))
#print("wmis_qubo: nodes={} connections={}".format(wmis_node_count, wmis_conn_count))
print("p_qubo nodes= {}".format(p_node_count));
print("wwmis qubo nodes= {}".format(wmis_node_count));
print("nodes= {}".format(p_node_count / wmis_node_count));
#print("conns= {}".format(p_conn_count / wmis_conn_count));
data["p_node_counts"].append(p_node_count)
data["wmis_node_counts"].append(wmis_node_count)
data["p_conn_counts"].append(p_conn_count)
data["wmis_conn_counts"].append(wmis_conn_count)
data["a_arr"].append(k/v)
data["k_arr"].append(k)
print()
sns.set()
ax = sns.scatterplot(x="k_arr", y="p_node_counts", data=data, label="p_qubo")
ax.set(xlabel='k',
ylabel='used verticies after embedding')
ax = sns.scatterplot(x="k_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo")
plt.show()
def medianChainLength(emb):
chl = []
for chain in emb.values():
chl.append(len(chain))
sns.distplot(chl)
plt.show()
return np.mean(chl)
def test2():
sat = rs.generateRandomKSAT(42, 10, 3)
print(sat.toString())
qubo = s2q.WMISdictQUBO(sat)
#ising = s2q.primitiveQUBO_8(sat)
ising = s2q.WMISdictQUBO_2(sat)
qg = nx.Graph()
for coupler, energy in qubo.items():
if coupler[0] != coupler[1]:
qg.add_edge(coupler[0], coupler[1], weight=energy)
ig = nx.Graph()
for coupler, energy in ising.items():
if coupler[0] != coupler[1]:
ig.add_edge(coupler[0], coupler[1], weight=energy)
#plt.ion()
print(qg.number_of_nodes(), qg.number_of_edges())
print(ig.number_of_nodes(), ig.number_of_edges())
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)
eg = ig
emb = minorminer.find_embedding(eg.edges(), target.edges(), return_overlap=True,
threads=8)
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(42, 10, 3)
print(sat.toString())
ising = s2q.primitiveQUBO(sat)
h = {}
J = {}
for coupler, energy in ising.items():
if coupler[0] == coupler[1]:
h[coupler[0]] = energy
else:
J[coupler] = energy
res = QBSolv().sample_ising(h, J, find_max=False)
sample = list(res.samples())[0]
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:
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 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)
print(sat.toString())
qubo = s2q.WMISdictQUBO(sat)
ising = s2q.primitiveQUBO(sat)
qg = nx.Graph()
for coupler, energy in qubo.items():
if coupler[0] != coupler[1]:
qg.add_edge(coupler[0], coupler[1], weight=energy)
ig = nx.Graph()
for coupler, energy in ising.items():
if coupler[0] != coupler[1]:
ig.add_edge(coupler[0], coupler[1], weight=energy)
#plt.ion()
print(qg.number_of_nodes(), qg.number_of_edges())
print(ig.number_of_nodes(), ig.number_of_edges())
target = dnx.chimera_graph(12, 12, 4)
#nx.draw_shell(qg, with_labels=True, node_size=50)
#nx.draw_shell(ig, with_labels=True, node_size=50)
print()
print("wmis:")
qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True)
print(qemb[1])
print("median chain length = {}".format(medianChainLength(qemb[0])))
used_nodes = []
for var, chain in qemb[0].items():
used_nodes.extend(chain)
used_nodes = np.unique(used_nodes)
print("used nodes (embedding) = {}".format(len(used_nodes)))
print()
print("primitves:")
iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True)
print(iemb[1])
print("median chain length = {}".format(medianChainLength(iemb[0])))
used_nodes = []
for var, chain in iemb[0].items():
used_nodes.extend(chain)
used_nodes = np.unique(used_nodes)
print("used nodes (embedding) = {}".format(len(used_nodes)))
#test3_3()
test2()
#test_kv_range()