General and Effective BQM code - please review

I wrote the following code after missing a useful template to generate a full BQM problem, and I suspect I still miss a fault somewhere. Can you check? Hope it is also useful for you.

import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
import dimod
import csv
from helpers.draw import plot_bqm 
from dwave.system import EmbeddingComposite
from dwave.system.samplers import DWaveSampler
from dwave.system import LeapHybridSampler
from dwave.cloud.exceptions import *
G=nx.Graph()
nodes = range(1, 1 + 29567)
G.add_nodes_from(nodes)
G.add_edges_from([(1,38,{"obj":4.474273e-03}),(1,135,{"obj":4.474273e-03}),(1,139,{"obj":4.474273e-03}),(1,136,{"obj":4.474273e-03}),(1,137,{"obj":4.474273e-03}),(1,140,{"obj":4.474273e-03}),(1,787,{"obj":4.474273e-03}),(1,788,{"obj":-4.474273e-03}),(1,45,{"obj":4.474273e-03}),(1,245,{"obj":8.948545e-06}),(1,426,{"obj":8.948545e-06}), ])
G.add_edges_from([(2,38,{"obj":4.474273e-03}),(2,135,{"obj":4.474273e-03}),(2,139,{"obj":4.474273e-03}),(2,136,{"obj":4.474273e-03}),(2,137,{"obj":4.474273e-03}),(2,140,{"obj":4.474273e-03}),(2,787,{"obj":-4.474273e-03}),(2,788,{"obj":4.474273e-03}),(2,45,{"obj":4.474273e-03}),(2,168,{"obj":8.948545e-06}),(2,281,{"obj":8.948545e-06}), ])
#Many more such lines
# ...
magnetic_field=np.zeros(29567)
magnetic_field[0:2]=4.456376e-03
magnetic_field[2:131]=6
magnetic_field[131:133]=4.456376e-03
#Many more such lines
#...
h = {i+1: magnetic_field[i] for i in range(len(magnetic_field))}
bqm = dimod.BinaryQuadraticModel(h,{},0.0,'SPIN')
for u, v, data in G.edges(data=True):
bqm.add_interaction(u, v, data['obj'])
try:
    sampler_qpu = LeapHybridSampler(solver='hybrid_binary_quadratic_model_version2p')
    print("Connected to QPU {} .".format(sampler_qpu.solver.id))
except SolverNotFoundError:
    print("The solver is not available.")
    exit()
result = sampler_qpu.sample(bqm,time_limit=1.975360e+02)
data=result.first.sample
print("Best solution found: {}".format(data))
for key in range(1,29568):
     data.setdefault(key, 0)
data_sorted=dict(sorted(data.items()))
array = np.array(list(data_sorted.values()))
filename='d_wave_answer.csv'
np.savetxt(filename, array,fmt='%d',  delimiter=',')

 

0

Comments

3 comments
  • Hello,

    Thank you for your patience while we looked at your code example. 

    Here are a few tips that will help to simplify things:

    You can create a BQM using a dictionary in QUBO format:

    from dwave.system import LeapHybridBQMSampler
    ...
    Q = {('x1', 'x2'): 1, ('x1', 'z'): -2, ('x2', 'z'): -2, ('z', 'z'): 3}
    bqm = dimod.BQM.from_qubo(Q)
    sampleset = LeapHybridBQMSampler().sample(bqm, time_limit=time_limit)  

    The dictionary elements where the labels are the same (e.g. ('z', 'z'): 3) represent the linear terms (i.e. h values), and those where the labels are different (e.g. ('x1', 'x2'): 1) represent quadratic terms (i.e. J values).

    This allows you to skip creating the networkx Graph and copying the values over to the BQM, allows you to create the BQM with the values directly, and allows you needing to define the h values separately. 

    When printing out the results, you can remove a few lines of code:

    data = sampleset.first.sample
    data_sorted = dict(sorted(data.items()))
    array = np.array(data_sorted.values())

    or alternatively:

    data = sampleset.first.sample
    keys_sorted = sorted(sampleset.first.sample.keys())
    array = np.array([data[k] for k in keys_sorted])

    The setdefault call can be skipped and we can skip converting to a dictionary in the second example.

    Hopefully this helps simplify the code example. 
    Please let us know if you have any questions.

    0
    Comment actions Permalink
  • Thanks David for your comment.

    My mind is set on the Ising model so I did not convert it to Qubo to avoid confusion. It seems your way is elegant, but does it allow splitting to many lines of code for adding more elements? I am looking for a case of a huge array. The sorting and default values at the end were a solution to a case that not all the keys were returned and not in orderly manner, which was caused by incomplete array in my input. I think of it as protection against my own fault in the input preparation. Such a huge program is generated automatically.

    I hoped for more insight about any possibility of failure in the code as it is. After debugging it seems the code works but I suspect I push the system beyond its limit. For example, in a huge network some of the coupling coefficients become quite small, on the order of 0.001 or below after scaling. Can the hybrid solver handle with such resolution? Also, there is no mention about the limit of coupling terms in the hybrid solver. Does it take the same time to solve a problem with 24 couplers and 1000 couplers per qubit?  

    0
    Comment actions Permalink
  • Hello,

    You can also add biases for an ising model as well:

    from dwave.system import LeapHybridBQMSampler
    h = {'a': 1, 'b': -1}
    J = {('a', 'b'): -1}
    sampleset = LeapHybridBQMSampler().sample_ising(h, J)   

    It's also possible to add them one at a time:

    bqm.add_linear('a', 1)
    bqm.add_quadratic('a', 'b', -1)

    See the documentation for BQM methods for more functions.

    You can use the LeapHybridSampler.min_time_limit function to estimate a starting time_limit value for each of the problems with 24 and 1000 couplers respectively that you had mentioned. You might need to increase this value to improve results.


    The Hybrid solvers do not have precision limitations in the same way as the QPU solvers do, however there is information about the QPU solver precision.

    0
    Comment actions Permalink

Please sign in to leave a comment.

Didn't find what you were looking for?

New post