Working With Different Topologies#
The examples below show how to construct software samplers with the same structure as the QPU, and how to work with embeddings for different topologies.
The code examples below uses the following imports:
>>> import dimod
>>> import dwave_networkx as dnx
>>> import networkx as nx
>>> import dwave.embedding
...
>>> from dwave.samplers import SimulatedAnnealingSampler
>>> from dwave.system import DWaveSampler, EmbeddingComposite
Creating a Pegasus Sampler#
As detailed in the Classical Solvers section, you might want to use a classical solver while developing your code or writing tests. However, it is sometimes useful to work with a software solver that behaves more like a quantum computer.
One of the key features of the quantum computer is its working graph, which defines the connectivity allowed the binary quadratic model.
To create a software solver with the same connectivity as an Advantage quantum
computer you first need a representation of the Pegasus graph which can
be obtained from the dwave_networkx package using the
pegasus_graph()
function.
>>> P16 = dnx.pegasus_graph(16)
Next, you need a software sampler and can use the
SimulatedAnnealingSampler
class
(TabuSampler
works equally well).
>>> classical_sampler = SimulatedAnnealingSampler()
Now, with a classical sampler and the desired graph, you can use the
dimod package’s
StructureComposite
to create a
Pegasus-structured sampler.
>>> sampler = dimod.StructureComposite(classical_sampler, P16.nodes, P16.edges)
This sampler accepts Pegasus-structured problems. For example, create an Ising problem.
>>> h = {v: 0.0 for v in P16.nodes}
>>> J = {(u, v): 1 for u, v in P16.edges}
>>> sampleset = sampler.sample_ising(h, J)
You can even use the sampler with the
EmbeddingComposite
.
>>> embedding_sampler = EmbeddingComposite(sampler)
Finally, you can confirm that the sampler matches the structure of the
DWaveSampler
sampler. Make sure that the
QPU has the same topology you have been simulating. Also note that the
working graph of the QPU is usually a subgraph of the full
hardware graph.
>>> qpu_sampler = DWaveSampler(solver=dict(topology__type='pegasus'))
>>> qpu_graph = qpu_sampler.to_networkx_graph()
>>> qpu_graph.nodes <= P16.nodes
True
>>> qpu_graph.edges <= P16.edges
True
Creating a Zephyr Sampler#
Another topology of interest is the Zephyr topology.
As above, you can use the generator function dwave_networkx.zephyr_graph()
found in dwave_networkx and the
SimulatedAnnealingSampler
to construct a sampler.
>>> Z3 = dnx.zephyr_graph(3)
>>> classical_sampler = SimulatedAnnealingSampler()
>>> sampler = dimod.StructureComposite(classical_sampler, Z3.nodes, Z3.edges)
Working With Embeddings#
The example above using the EmbeddingComposite
hints that you might be interested in trying embedding with different
topologies.
One thing you might be interested in is the chain length when embedding your problem. For example, if you have a fully connected problem with 40 variables and you want to know the chain length needed to embed it on a 5000+ node Pegasus graph.
You can use dwave-system package’s
find_clique_embedding()
function to find the
embedding and determine the maximum chain length.
>>> num_variables = 40
>>> embedding = dwave.embedding.pegasus.find_clique_embedding(num_variables, 16)
>>> max(len(chain) for chain in embedding.values())
5
Similarly you can explore clique embeddings for a 40-variables fully connected
problem with a 300+ node Zephyr graph using
dwave-system package’s
find_clique_embedding()
function.
>>> num_variables = 40
>>> embedding = dwave.embedding.zephyr.find_clique_embedding(num_variables, 3)
>>> max(len(chain) for chain in embedding.values())
4