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

#!/usr/bin/env python3
from util import SAT2QUBO as s2q
from util import randomSAT as rs
from util import queries
from util import graph
from util import script
import networkx as nx
import dwave_networkx as dnx
import minorminer
from dwave_qbsolv import QBSolv
import dimod
from dwave.system.composites import FixedEmbeddingComposite
from neal import SimulatedAnnealingSampler
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import re
from tqdm import tqdm
def frange(start, stop, steps):
while start < stop:
yield start
start += steps
def test_kv_range():
k = 75
v = 40
data = {
"p_node_counts" : [],
"wmis_node_counts" : [],
"p_conn_counts" : [],
"wmis_conn_counts" : [],
"p_avrg_connectivity" : [],
"wmis_avrg_connectivity" : [],
"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(0.5, 8, 0.5):
#v = int(k/4)
#a = k/v
#v = int(k/a)
k = int(a*v)
print("k={} v={} k/v={}".format(k, v, k/v))
ksatInstance = rs.generateRandomKSAT(k, v, 3)
p_qubo = s2q.WMISdictQUBO_2(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)
p_node_count = ig.number_of_nodes();
p_conn_count = ig.number_of_edges();
wmis_node_count = qg.number_of_nodes();
wmis_conn_count = qg.number_of_edges();
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));
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)
print("calculating connectivity...")
data["p_avrg_connectivity"].append(nx.edge_connectivity(ig))
print("calculating connectivity...")
data["wmis_avrg_connectivity"].append(nx.edge_connectivity(qg))
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')
ax = sns.scatterplot(x="a_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo")
plt.show()
ax = sns.scatterplot(x="a_arr", y="p_conn_counts", data=data, label="p_qubo")
ax.set(xlabel='k/v', ylabel='used edges')
ax = sns.scatterplot(x="a_arr", y="wmis_conn_counts", data=data, ax=ax, label="wmis_qubo")
plt.show()
ax = sns.scatterplot(x="a_arr", y="p_avrg_connectivity", data=data, label="p_qubo")
ax.set(xlabel='k/v', ylabel='avrg connectivity')
ax = sns.scatterplot(x="a_arr", y="wmis_avrg_connectivity", data=data, ax=ax, label="wmis_qubo")
plt.show()
def test_kv_range_emb():
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.WMISdictQUBO_2(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 test3_4():
sat_count = 0
steps = 200
for i in tqdm(range(steps)):
sat = rs.generateRandomKSAT(35, 10, 3)
ising = s2q.WMISdictQUBO_2(sat)
res = QBSolv().sample_qubo(ising, find_max=False)
#res = dimod.ExactSolver().sample_qubo(ising)
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
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
if sat.checkAssignment(model):
sat_count += 1
print("sat percentage: {}".format(sat_count / steps))
def test_wmis():
sat_count = 0
#steps = 100
steps = 1
for i in tqdm(range(steps)):
sat = rs.generateRandomKSAT(35, 10, 3)
target = dnx.chimera_graph(16, 16, 4)
qubo = s2q.WMISdictQUBO(sat)
qg = nx.Graph()
for coupler, energy in qubo.items():
if coupler[0] != coupler[1]:
qg.add_edge(coupler[0], coupler[1], weight=energy)
qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True)
chimera_sampler = dimod.StructureComposite(SimulatedAnnealingSampler(),
target.nodes(),
target.edges())
solver = FixedEmbeddingComposite(chimera_sampler, qemb[0])
res = solver.sample_qubo(__negate_qubo(qubo))
#res = solver.sample_qubo(qubo)
#res = dimod.ExactSolver().sample_qubo(ising)
sample = res.first.sample
model = script.majority_vote_sample(sample)
print("energy={}".format(res.first.energy))
if sat.checkAssignment(model):
sat_count += 1
print("sat percentage: {}".format(sat_count / steps))
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)))
def __negate_qubo(qubo):
negative_qubo = {}
for coupler, energy in qubo.items():
negative_qubo[coupler] = -1 * energy
return negative_qubo
#test3_4()
#test2()
#test_kv_range
test_wmis()