.. _topology_samplers: ================================= Working With Different Topologies ================================= The examples below show how to construct software samplers with the same structure as the :term:`QPU`, and how to work with :term:`embedding`\s with 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 :ref:`using_cpu`, 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 :term:`working graph`, which defines the connectivity allowed by the :term:`binary quadratic model`. To create a software solver with the same connectivity as an Advantage quantum computer you first need a representation of the :term:`Pegasus` graph which can be obtained from the :doc:`dwave_networkx ` project using the :func:`~dwave_networkx.pegasus_graph` function. >>> P16 = dnx.pegasus_graph(16) Next, you need a software sampler and can use the :class:`~dwave.samplers.SimulatedAnnealingSampler` (:class:`~dwave.samplers.TabuSampler` works equally well). .. dev note: we should maybe add a link to somewhere explaining the difference .. between tabu/neal >>> classical_sampler = SimulatedAnnealingSampler() Now, with a classical sampler and the desired graph, you can use :doc:`dimod `'s :class:`~dimod.reference.composites.structure.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 :term:`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 :class:`~dwave.system.composites.EmbeddingComposite`. >>> embedding_sampler = EmbeddingComposite(sampler) Finally, you can confirm that the sampler matches the :class:`~dwave.system.samplers.DWaveSampler`\ 's structure. Make sure that the :term:`QPU` has the same topology you have been simulating. Also note that the :term:`working graph` of the QPU is usually a :term:`subgraph` of the full :term:`hardware graph`. .. dev note: maybe in the future we want to talk about different topologies >>> qpu_sampler = DWaveSampler(solver=dict(topology__type='pegasus')) >>> qpu_graph = qpu_sampler.to_networkx_graph() >>> qpu_graph.nodes <= P16.nodes # doctest: +SKIP True >>> qpu_graph.edges <= P16.edges # doctest: +SKIP True Creating a Zephyr Sampler ------------------------- Another topology of interest is the :term:`Zephyr` topology. As above, you can use the generator function :func:`dwave_networkx.zephyr_graph` found in :doc:`dwave_networkx ` and the :class:`~dwave.samplers.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 :class:`~dwave.system.composites.EmbeddingComposite` hints that you might be interested in trying :term:`embedding` with different topologies. One thing you might be interested in is the :term:`chain length` when embedding your problem. For example, if you have a :term:`fully connected` problem with 40 variables and you want to know the chain length needed to embed it on a 5000+ node :term:`Pegasus` graph. You can use :doc:`dwave-system `'s :func:`~dwave.embedding.pegasus.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 :doc:`dwave-system `'s :func:`~dwave.embedding.zephyr.find_clique_embedding` function .. dev note: skip doctest until SDK has https://github.com/dwavesystems/dwave-system/pull/490 >>> num_variables = 40 >>> embedding = dwave.embedding.zephyr.find_clique_embedding(num_variables, 3) # doctest: +SKIP >>> max(len(chain) for chain in embedding.values()) # doctest: +SKIP 4