# Solutions#

samplers sample from low-energy states of a problem’s objective function—BQM samplers sample from low-energy states in models such as those defined by an Ising equation or a QUBO problem—and return an iterable of samples, in order of increasing energy.

When a D‑Wave quantum computer solves a problem, it uses quantum phenomena such as superposition and tunneling to explore all possible solutions simultaneously and find a set of the best ones. At the end of the computation (anneal), a single solution is sampled from a set of good solutions, with some probability, and returned. Because the sampled solution is probabilistic, different solutions may be returned in different runs. The standard way of submitting a problem to the system requests many samples, not just one. This not only returns multiple “best” answers but also reduces the probability of settling on a suboptimal answer.

Some classical samplers might return non-probabilistic solutions; for example,
the dimod `ExactSolver`

deterministically returns the best solution or solutions to small problems by
calculating the result for every configuration of variable values. Such samplers
are called solvers.

Some Ocean functions might return a single best solution; for example, some dwave-networkx graph algorithms return only the lowest-energy sample.

## SampleSets#

Ocean uses the dimod `SampleSet`

class to hold samples and some additional information (e.g., timing and
minor-embedding information from some samplers).

As a simple example, this three-variable BQM,

might be solved directly on a D-Wave quantum computer by sampling 1000 times.
Here, the `EmbeddingComposite`

composite maps the symbolic BQM
to qubits on the quantum processor, which is called by the
`DWaveSampler`

sampler:

```
>>> import dimod
>>> from dwave.system import DWaveSampler, EmbeddingComposite
...
>>> s0, s1, s2 = dimod.Spins(['s0', 's1', 's2'])
>>> bqm = s1*s2 - s0*s1 - s0*s2
>>> sampler = EmbeddingComposite(DWaveSampler())
>>> sampleset = sampler.sample(bqm, num_reads=1000)
>>> print(sampleset)
s0 s1 s2 energy num_oc. chain_.
0 -1 +1 -1 -1.0 183 0.0
1 -1 -1 +1 -1.0 141 0.0
2 -1 -1 -1 -1.0 206 0.0
3 +1 -1 +1 -1.0 162 0.0
4 +1 +1 +1 -1.0 123 0.0
5 +1 +1 -1 -1.0 185 0.0
['SPIN', 6 rows, 1000 samples, 3 variables]
```

The returned `SampleSet`

, in this case, shows six solutions of
equal energy \(-1.0\). Solution \(s_0=-1, s_1=+1, s_2=-1\) on the first
line occurred in 183 of the 1000 samples.

For this submission, the sampleset also contained the following additional information:

```
>>> print(sampleset.info.keys())
dict_keys(['timing', 'problem_id', 'embedding_context', 'warnings'])
```

For example, the timing information for the problem might look something like:

```
>>> print(sampleset.info["timing"])
{'qpu_sampling_time': 85860.0,
'qpu_anneal_time_per_sample': 20.0,
'qpu_readout_time_per_sample': 45.32,
'qpu_access_time': 101619.97,
'qpu_access_overhead_time': 2259.03,
'qpu_programming_time': 15759.97,
'qpu_delay_time_per_sample': 20.54,
'total_post_processing_time': 2277.0,
'post_processing_overhead_time': 2277.0}
```