From 2f11020bab3cc9dad44133a3a2b973025e3ecd1f Mon Sep 17 00:00:00 2001 From: Tim Doyle Date: Tue, 31 May 2022 12:03:42 -0700 Subject: [PATCH 1/6] Support all structured samplers in SubproblemCliqueEmbedder Fixes #264 --- hybrid/samplers.py | 26 ++++++-------------------- tests/test_samplers.py | 17 +++++++++++------ 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/hybrid/samplers.py b/hybrid/samplers.py index 1df775c..e4677cb 100644 --- a/hybrid/samplers.py +++ b/hybrid/samplers.py @@ -26,12 +26,11 @@ import dimod from dwave.system.samplers import DWaveSampler from dwave.system.composites import AutoEmbeddingComposite, FixedEmbeddingComposite -from dwave.embedding.chimera import find_clique_embedding as find_chimera_clique_embedding -from dwave.embedding.pegasus import find_clique_embedding as find_pegasus_clique_embedding from tabu import TabuSampler from neal import SimulatedAnnealingSampler from greedy import SteepestDescentSolver +from minorminer.busclique import busgraph_cache from hybrid.core import Runnable, SampleSet from hybrid.flow import Loop @@ -114,8 +113,7 @@ class SubproblemCliqueEmbedder(traits.SubproblemIntaking, Args: sampler (:class:`dimod.Structured`): Structured :class:`dimod.Sampler` such as a - :class:`~dwave.system.samplers.DWaveSampler`. The sampler has to - have a Chimera or Pegasus topology. + :class:`~dwave.system.samplers.DWaveSampler`. Example: To replace :class:`.QPUSubproblemAutoEmbeddingSampler` with a sampler @@ -141,29 +139,17 @@ def __repr__(self): @staticmethod def find_clique_embedding(variables, sampler): - """Given a Chimera- or Pegasus-based ``sampler``, and a list of + """Given a :class:`dimod.Structured` ``sampler``, and a list of variable labels, return a clique embedding. Returns: dict: Clique embedding map with source variables from ``variables`` - and target edges taken from ``sampler``. + and target graph taken from ``sampler``. """ - topology_type = sampler.properties['topology']['type'] - topology_shape = sampler.properties['topology']['shape'] - - clique_embedders = dict(chimera=find_chimera_clique_embedding, - pegasus=find_pegasus_clique_embedding) - try: - find_clique_embedding = clique_embedders[topology_type] - except KeyError: - raise ValueError('unknown sampler topology') - - embedding = find_clique_embedding( - variables, m=topology_shape[0], target_edges=sampler.edgelist) - - return embedding + g = sampler.to_networkx_graph() + return busgraph_cache(g).find_clique_embedding(variables) def next(self, state, **runopts): embedding = self.find_clique_embedding( diff --git a/tests/test_samplers.py b/tests/test_samplers.py index 22777da..b3373d3 100644 --- a/tests/test_samplers.py +++ b/tests/test_samplers.py @@ -17,10 +17,11 @@ from operator import attrgetter import numpy as np -from parameterized import parameterized_class +from parameterized import parameterized, parameterized_class import dimod from neal import SimulatedAnnealingSampler +from dwave.system import DWaveSampler from dwave.system.testing import MockDWaveSampler from hybrid.samplers import * @@ -28,6 +29,8 @@ from hybrid.testing import mock from hybrid.utils import random_sample +MockDWaveSampler.to_networkx_graph = DWaveSampler.to_networkx_graph + class MockDWaveReverseAnnealingSampler(MockDWaveSampler): """Extend the `dwave.system.testing.MockDWaveSampler` with mock support for @@ -109,12 +112,12 @@ def test_external_embedding_sampler(self): # verify mock sampler received custom kwargs self.assertEqual(res.subsamples.first.energy, -1) - def test_clique_embedder(self): + @parameterized.expand([['chimera', 2], ['pegasus', 1]]) + def test_clique_embedder(self, topology_type, expected_chain_length): bqm = dimod.BinaryQuadraticModel.from_ising({}, {'ab': 1, 'bc': 1, 'ca': 1}) init = State.from_subproblem(bqm) - sampler = MockDWaveSampler() - + sampler = MockDWaveSampler(topology_type=topology_type) workflow = SubproblemCliqueEmbedder(sampler=sampler) # run embedding @@ -123,8 +126,10 @@ def test_clique_embedder(self): # verify mock sampler received custom kwargs self.assertIn('embedding', res) self.assertEqual(len(res.embedding.keys()), 3) - # embedding a triangle onto a chimera produces 3 x 2-qubit chains - self.assertTrue(all(len(e) == 2 for e in res.embedding.values())) + + # embedding a triangle onto a chimera produces 3 x 2-qubit chains; + # if embedding onto pegasus the chains have length 1. + self.assertTrue(all(len(e) == expected_chain_length for e in res.embedding.values())) def test_reverse_annealing_sampler(self): sampler = MockDWaveReverseAnnealingSampler() From 59e81e2f4343ee4a93d56ce9d375ffb0e4e385f4 Mon Sep 17 00:00:00 2001 From: Tim Doyle Date: Tue, 31 May 2022 13:43:23 -0700 Subject: [PATCH 2/6] Add unit test for Zephyr --- tests/requirements.txt | 1 + tests/test_samplers.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index b2bd102..5b66072 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,3 +1,4 @@ coverage codecov parameterized +dwave-system>=1.13.0 diff --git a/tests/test_samplers.py b/tests/test_samplers.py index b3373d3..35efad5 100644 --- a/tests/test_samplers.py +++ b/tests/test_samplers.py @@ -112,7 +112,7 @@ def test_external_embedding_sampler(self): # verify mock sampler received custom kwargs self.assertEqual(res.subsamples.first.energy, -1) - @parameterized.expand([['chimera', 2], ['pegasus', 1]]) + @parameterized.expand([['chimera', 2], ['pegasus', 1], ['zephyr', 1]]) def test_clique_embedder(self, topology_type, expected_chain_length): bqm = dimod.BinaryQuadraticModel.from_ising({}, {'ab': 1, 'bc': 1, 'ca': 1}) init = State.from_subproblem(bqm) From 70056dc28446daa8cc9874c46f650cf8d72e6348 Mon Sep 17 00:00:00 2001 From: Tim Doyle Date: Tue, 31 May 2022 14:15:45 -0700 Subject: [PATCH 3/6] Update dwave-system dependency --- requirements.txt | 2 +- tests/requirements.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 1b1fc32..d00fdf4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ dimod==0.10.13 numpy>=1.19.1 minorminer==0.2.7 -dwave-system==1.11.0 +dwave-system==1.13.0 dwave-neal==0.5.9 dwave-tabu==0.4.3 dwave-greedy==0.2.3 diff --git a/tests/requirements.txt b/tests/requirements.txt index 5b66072..b2bd102 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,3 @@ coverage codecov parameterized -dwave-system>=1.13.0 From 1779e3f7de5ee04c24d9db5ba9eb044196f1583d Mon Sep 17 00:00:00 2001 From: Tim Doyle Date: Wed, 1 Jun 2022 08:27:23 -0700 Subject: [PATCH 4/6] Revert "Update dwave-system dependency" This reverts commit 70056dc28446daa8cc9874c46f650cf8d72e6348. --- requirements.txt | 2 +- tests/requirements.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d00fdf4..1b1fc32 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ dimod==0.10.13 numpy>=1.19.1 minorminer==0.2.7 -dwave-system==1.13.0 +dwave-system==1.11.0 dwave-neal==0.5.9 dwave-tabu==0.4.3 dwave-greedy==0.2.3 diff --git a/tests/requirements.txt b/tests/requirements.txt index b2bd102..5b66072 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,3 +1,4 @@ coverage codecov parameterized +dwave-system>=1.13.0 From 3af76179019ed0a44ae2912c572ee889bb7ea6b5 Mon Sep 17 00:00:00 2001 From: Tim Doyle Date: Wed, 1 Jun 2022 08:27:57 -0700 Subject: [PATCH 5/6] Run "pip install -r" commands sequentially in CI --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ba4d4ad..611a603 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,7 +27,8 @@ jobs: command: | . env/bin/activate pip install -U pip - pip install -r requirements.txt -r tests/requirements.txt + pip install -r requirements.txt + pip install -r tests/requirements.txt pip install wheel twine - save_cache: &save-cache-env From a6c2437da77ec1e42ed47d7f5cf54d0ed1cac268 Mon Sep 17 00:00:00 2001 From: Tim Doyle Date: Wed, 1 Jun 2022 08:35:15 -0700 Subject: [PATCH 6/6] Run "pip install -r" commands sequentially in AppVeyor CI --- .appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 8d9a3ff..dc59ebd 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -13,7 +13,8 @@ cache: - '%AppData%\pip-cache' build_script: - - "%PYTHON%\\python.exe -m pip install -r requirements.txt -r tests\\requirements.txt --cache-dir %AppData%\\pip-cache" + - "%PYTHON%\\python.exe -m pip install -r requirements.txt --cache-dir %AppData%\\pip-cache" + - "%PYTHON%\\python.exe -m pip install -r tests\\requirements.txt --cache-dir %AppData%\\pip-cache" before_test: - "%PYTHON%\\python.exe -m pip install ."