Skip to content

Commit

Permalink
Merge pull request #1152 from arcondello/fix/overlapping-discrete-fro…
Browse files Browse the repository at this point in the history
…m-QM

Fix exceptions in `CQM.add_discrete_from_model()`
  • Loading branch information
arcondello authored Mar 15, 2022
2 parents 9fba14a + 4f8f0d7 commit c9a9f28
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
8 changes: 7 additions & 1 deletion dimod/constrained.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,13 @@ def add_discrete_from_model(self,
raise ValueError("discrete constraints must have at least two variables")

for v, bias in qm.iter_linear():
if not vartype(v) is Vartype.BINARY:
if v in self.variables:
# it already exists, let's make sure it's not already used
if any(v in self.constraints[label].lhs.variables for label in self.discrete):
raise ValueError(f"variable {v!r} is already used in a discrete variable")
if self.vartype(v) is not Vartype.BINARY:
raise ValueError(f"variable {v!r} has already been added but is not BINARY")
elif not vartype(v) is Vartype.BINARY:
raise ValueError("all variables in a discrete constraint must be binary, "
f"{v!r} is {vartype(v).name!r}")
# we could maybe do a scaling, but let's just keep it simple for now
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
fixes:
- |
``ConstrainedQuadraticModel.add_discrete()``,
``ConstrainedQuadraticModel.add_constraint_from_iterable()``, and
``ConstrainedQuadraticModel.add_discrete_from_model()``
now correctly raise an error when given a binary variable that overlaps with an existing
discrete constraint.
See `#1149 <https://github.com/dwavesystems/dimod/issues/1149>`_.
23 changes: 23 additions & 0 deletions tests/test_constrained.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,29 @@ def test_qm(self):
self.assertIn(c, cqm.discrete)
self.assertTrue(cqm.constraints[c].lhs.is_equal(qm))

def test_qm_overlap(self):
b1 = dimod.Binary('b1')
b2 = dimod.Binary('b2')
b3 = dimod.Binary('b3')

cqm = dimod.CQM()
cqm.add_discrete(dimod.quicksum([b1, b2]))
with self.assertRaises(ValueError):
cqm.add_discrete(dimod.quicksum([b1, b3]))

def test_qm_not_binary(self):
x, y = dimod.Binaries('xy')
i, j = dimod.Integers('ij')
ii = dimod.Binary('i')

cqm = dimod.CQM()
cqm.add_constraint(i <= 5)
with self.assertRaises(ValueError):
cqm.add_discrete(x + y + ii)

with self.assertRaises(ValueError):
cqm.add_discrete(x + j)

def test_simple(self):
cqm = CQM()
cqm.add_discrete('abc')
Expand Down

0 comments on commit c9a9f28

Please sign in to comment.