dwavesystems / dwave-system

An API for easily incorporating the D-Wave system as a sampler, either directly or through Leap's cloud-based hybrid samplers
https://docs.ocean.dwavesys.com/
Apache License 2.0
90 stars 64 forks source link

Inconsistent `SampleSet` interface across Leap hybrid samplers #540

Closed randomir closed 4 weeks ago

randomir commented 1 month ago

BQM sampler, CQM sampler, as well as the sample_* methods on dwave.cloud.Solvers return a SampleSet with wait_id():

>>> import dimod
>>> from dwave.system import LeapHybridBQMSampler
>>> 
>>> bqm = dimod.BQM.from_qubo({})
>>> 
>>> sampler = LeapHybridBQMSampler()
>>> ss = sampler.sample(bqm)
>>> 
>>> ss.wait_id()
'a59...dc95'
>>> import dimod
>>> from dwave.system import LeapHybridCQMSampler
>>> 
>>> cqm = dimod.CQM.from_bqm(dimod.BQM.from_qubo({'ab': 1}))
>>> 
>>> sampler = LeapHybridCQMSampler()
>>> ss = sampler.sample_cqm(cqm)
>>> 
>>> ss.wait_id()
'54b...3b1'

But the DQM sampler doesn't:

>>> import dimod
>>> from dwave.system import LeapHybridDQMSampler
>>> 
>>> dqm = dimod.DQM()
>>> dqm.add_variable(1)
0
>>> 
>>> sampler = LeapHybridDQMSampler()
>>> ss = sampler.sample_dqm(dqm)
>>> 
>>> ss.wait_id()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'SampleSet' object has no attribute 'wait_id'

Root cause: .wait_id is set in the Future.sampleset property (cloud-client), and since both BQM and CQM samplers defer sampleset contruction to the cloud-client, wait_id is available. DQM sampler, on the other hand strips and re-attaches labels, so it constructs the sampleset via @dimod.decorators.nonblocking_sample_method (that doesn't add the wait_id method).

Proposed solution:

It's backwards-compatible, fixes the issue at hand, and will even work with older clients.

arcondello commented 1 month ago

extend dimod.SampleSet with wait_id during construction in SampleSet.from_future()

At least in principal, SampleSet.from_future() is meant to use with any Future-like object, the notion of an id is specific to the cloud-client. On the other hand, this is the only place we use from_future() so far as I know after years of being more general in principal. So probably not too much of a restriction.