From 5b9abb908a2b984b34764eb019d81538216cb4dc Mon Sep 17 00:00:00 2001 From: pfarre Date: Tue, 8 Mar 2022 16:16:07 -0800 Subject: [PATCH 1/3] expose innermost_child sampler --- dimod/core/composite.py | 8 +++++++- dimod/core/sampler.py | 4 ++++ tests/test_composite.py | 31 +++++++++++++++++++++++++++++++ tests/test_sampler.py | 17 +++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/dimod/core/composite.py b/dimod/core/composite.py index af5532e71..2bdefaf9c 100644 --- a/dimod/core/composite.py +++ b/dimod/core/composite.py @@ -45,6 +45,8 @@ For more examples, see the source code for the composed documented in :ref:`quadratic_composites`. """ +from __future__ import annotations + import abc from dimod.core.sampler import Sampler @@ -75,10 +77,14 @@ def child(self): raise RuntimeError("A Composite must have at least one child Sampler") + class ComposedSampler(Sampler, Composite): """Abstract base class for dimod composed samplers. Inherits from :class:`.Sampler` and :class:`.Composite`. """ - pass + + def innermost_child(self) -> Sampler: + """Returns the inner-most child sampler""" + return self.child.innermost_child() diff --git a/dimod/core/sampler.py b/dimod/core/sampler.py index 932911f14..b866ffd0c 100644 --- a/dimod/core/sampler.py +++ b/dimod/core/sampler.py @@ -105,6 +105,7 @@ def parameters(self): return self._parameters """ +from __future__ import annotations import abc import typing @@ -317,3 +318,6 @@ def remove_unknown_kwargs(self, **kwargs) -> typing.Dict[str, typing.Any]: kwargs.pop(kw) return kwargs + + def innermost_child(self) -> Sampler: + return self diff --git a/tests/test_composite.py b/tests/test_composite.py index cdf8b65e0..e4c871af8 100644 --- a/tests/test_composite.py +++ b/tests/test_composite.py @@ -39,3 +39,34 @@ def children(self): sampler = Dummy() with self.assertRaises(RuntimeError): sampler.child + + +class TestInnermostChildProperties(unittest.TestCase): + + class Dummy(dimod.Sampler): + def __init__(self, annealing_time_range): + self.annealing_time_range = annealing_time_range + @property + def properties(self): + return {"annealing_time_range": self.annealing_time_range} + @property + def parameters(self): + pass + def sample(**kwargs): + pass + sample_ising = sample_qubo = sample + + def test_sampler(self): + # not a composed sampler + annealing_time_range = [1, 1000] + sampler = self.Dummy(annealing_time_range) + innermost_child = sampler.innermost_child() + self.assertEqual(innermost_child.properties["annealing_time_range"], annealing_time_range) + + def test_composed_sampler(self): + annealing_time_range = [1, 1000] + sampler = dimod.ClipComposite(dimod.ScaleComposite(self.Dummy(annealing_time_range))) + innermost_child = sampler.innermost_child() + print(innermost_child.properties) + self.assertEqual(innermost_child.properties["annealing_time_range"], annealing_time_range) + diff --git a/tests/test_sampler.py b/tests/test_sampler.py index 3906bf806..a0d1bb715 100644 --- a/tests/test_sampler.py +++ b/tests/test_sampler.py @@ -362,3 +362,20 @@ def properties(self): # Check that known kwargs are kept and unknown kwargs are removed self.assertDictEqual(kwargs, {'a': 1}) + + def test_innermost_child(self): + class Dummy(dimod.Sampler): + def sample(self, **kwargs): + kwargs = self.remove_unknown_kwargs(**kwargs) + return kwargs + + @property + def parameters(self): + return {'a':[]} + + @property + def properties(self): + return {'b':[]} + + sampler = Dummy() + self.assertDictEqual(sampler.innermost_child().properties, {'b':[]}) \ No newline at end of file From fad6dc9afa8538e3effb467f028a7cffcfb054a9 Mon Sep 17 00:00:00 2001 From: pfarre Date: Tue, 8 Mar 2022 16:37:04 -0800 Subject: [PATCH 2/3] swap inheritance scheme --- dimod/core/composite.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dimod/core/composite.py b/dimod/core/composite.py index 2bdefaf9c..5dfd7a0c2 100644 --- a/dimod/core/composite.py +++ b/dimod/core/composite.py @@ -45,7 +45,6 @@ For more examples, see the source code for the composed documented in :ref:`quadratic_composites`. """ -from __future__ import annotations import abc @@ -76,15 +75,15 @@ def child(self): except IndexError: raise RuntimeError("A Composite must have at least one child Sampler") + def innermost_child(self) -> Sampler: + """Returns the inner-most child sampler""" + return self.child.innermost_child() -class ComposedSampler(Sampler, Composite): +class ComposedSampler(Composite, Sampler): """Abstract base class for dimod composed samplers. Inherits from :class:`.Sampler` and :class:`.Composite`. """ - - def innermost_child(self) -> Sampler: - """Returns the inner-most child sampler""" - return self.child.innermost_child() + pass From 4ac9fa456195f964803ee590d81a2a57d7f9214e Mon Sep 17 00:00:00 2001 From: pfarre Date: Tue, 8 Mar 2022 16:37:33 -0800 Subject: [PATCH 3/3] make test not be specific to properties --- tests/test_composite.py | 30 ++++-------------------------- tests/test_sampler.py | 17 ++--------------- 2 files changed, 6 insertions(+), 41 deletions(-) diff --git a/tests/test_composite.py b/tests/test_composite.py index e4c871af8..5c40cbf94 100644 --- a/tests/test_composite.py +++ b/tests/test_composite.py @@ -41,32 +41,10 @@ def children(self): sampler.child -class TestInnermostChildProperties(unittest.TestCase): - - class Dummy(dimod.Sampler): - def __init__(self, annealing_time_range): - self.annealing_time_range = annealing_time_range - @property - def properties(self): - return {"annealing_time_range": self.annealing_time_range} - @property - def parameters(self): - pass - def sample(**kwargs): - pass - sample_ising = sample_qubo = sample - - def test_sampler(self): - # not a composed sampler - annealing_time_range = [1, 1000] - sampler = self.Dummy(annealing_time_range) - innermost_child = sampler.innermost_child() - self.assertEqual(innermost_child.properties["annealing_time_range"], annealing_time_range) +class TestInnermostChild(unittest.TestCase): def test_composed_sampler(self): - annealing_time_range = [1, 1000] - sampler = dimod.ClipComposite(dimod.ScaleComposite(self.Dummy(annealing_time_range))) - innermost_child = sampler.innermost_child() - print(innermost_child.properties) - self.assertEqual(innermost_child.properties["annealing_time_range"], annealing_time_range) + innermost_child = dimod.ExactSolver() + sampler = dimod.ClipComposite(dimod.ScaleComposite(innermost_child)) + self.assertTrue(sampler.innermost_child() is innermost_child) diff --git a/tests/test_sampler.py b/tests/test_sampler.py index a0d1bb715..33c5d1467 100644 --- a/tests/test_sampler.py +++ b/tests/test_sampler.py @@ -364,18 +364,5 @@ def properties(self): self.assertDictEqual(kwargs, {'a': 1}) def test_innermost_child(self): - class Dummy(dimod.Sampler): - def sample(self, **kwargs): - kwargs = self.remove_unknown_kwargs(**kwargs) - return kwargs - - @property - def parameters(self): - return {'a':[]} - - @property - def properties(self): - return {'b':[]} - - sampler = Dummy() - self.assertDictEqual(sampler.innermost_child().properties, {'b':[]}) \ No newline at end of file + sampler = dimod.ExactSolver() + self.assertTrue(sampler.innermost_child() is sampler) \ No newline at end of file