Repository: dwavesystems/dwave-system

Issue:
dwave.system.warnings not compatible with iterable as chain strength parameter
Newer versions of the code allow the user to specify an individual value of chain strength for each chain by passing a dictionary to the sample function.

However, calling `sample_qubo` with `chain_strength = dict_of_chain_strengths`, `warnings.py` throws an error because it expects a scalar value as the chain strength parameter. Setting `warnings = "ignore"` bypasses the warnings function call and the system produces the desired behavior.

Obviously ignoring warnings is not desirable, so the warnings code should be updated to the new flexibility in chain strength input.

Discussion:

Patch:
diff --git a/dwave/system/warnings.py b/dwave/system/warnings.py
index e646ce3..3dc5d51 100644
--- a/dwave/system/warnings.py
+++ b/dwave/system/warnings.py
@@ -19,6 +19,7 @@ import logging
 import dimod
 import numpy as np
 import six
+import collections.abc as abc
 
 from dwave.embedding import broken_chains
 
@@ -186,8 +187,12 @@ class WarningHandler(object):
                 # strength
                 return
 
-        interactions = [uv for uv, bias in bqm.quadratic.items()
-                        if abs(bias) >= chain_strength]
+        if isinstance(chain_strength, abc.Mapping):
+            interactions = [(u, v) for (u, v), bias in bqm.quadratic.items()
+                            if abs(bias) >= min(chain_strength[u], chain_strength[v])]
+        else:
+            interactions = [uv for uv, bias in bqm.quadratic.items()
+                            if abs(bias) >= chain_strength]
 
         if interactions:
             self.issue("Some quadratic biases are stronger than the given "


Test patch:
diff --git a/tests/test_embedding_composite.py b/tests/test_embedding_composite.py
index 7fec85d..fe7139c 100644
--- a/tests/test_embedding_composite.py
+++ b/tests/test_embedding_composite.py
@@ -332,6 +332,26 @@ class TestEmbeddingComposite(unittest.TestCase):
                 count += 1
         self.assertEqual(count, 0)
 
+    def test_warnings_chain_strength_dict(self):
+        sampler = EmbeddingComposite(MockDWaveSampler())
+
+        linear = {'a': -1, 'b': -2, 'c': -3}
+        quadratic = {('a', 'b'): 1, ('a', 'c'): -1, ('b', 'c'): 2}
+        bqm = dimod.BQM(linear, quadratic, 0, dimod.SPIN)
+
+        chain_strength = {'a': 10, 'b': 20, 'c': 1.5}   
+        ss = sampler.sample(bqm, chain_strength=chain_strength, warnings='SAVE')
+
+        self.assertIn('warnings', ss.info)
+        self.assertEqual(len(ss.info['warnings']), 1)
+
+        warning = ss.info['warnings'][0]
+        self.assertEqual(warning['type'], ChainStrengthWarning)
+
+        interactions = warning['data']['source_interactions']
+        self.assertEqual(len(interactions), 1)
+        self.assertCountEqual(interactions[0], ('b','c'))
+
     def test_warnings_as_class_variable(self):
         G = dnx.chimera_graph(12)