-
Notifications
You must be signed in to change notification settings - Fork 84
Description
When one calls CQM.add_discrete() we check that the given constraint is a valid discrete constraint - that is that it doesn't overlap with any other discrete constraint. The check happens in one of two places:
dimod/dimod/constrained/constrained.py
Lines 607 to 613 in e7bc4d5
| for v in variables: | |
| 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") |
dimod/dimod/constrained/constrained.py
Lines 671 to 683 in e7bc4d5
| for v, bias in qm.iter_linear(): | |
| 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 | |
| if bias != 1: | |
| raise ValueError("all linear biases in a discrete constraint must be 1") |
This is quite a slow check, and many users therefore bypass it by adding the discrete constraint as a constraint and then marking it as discrete.
label = cqm.add_constraint(x + y + z == 1)
cqm.constraints[label].lhs.mark_discrete()This bypasses the check. Luckily, dwave-preprocessing handles fixing overlapping discrete constraints, so I think it's fairly safe to make the bypass more "legal", albeit with caveats explained clearly in the docs.
Therefore, we should/could consider adding a keyword argument skip_check defaulting to False that would allow users to bypass the check. If they then create overlapping discrete constraints they will be removed by presolve later.
cqm.add_discrete(["a", "b", "c"], skip_check=True)
For experience users who promise to construct the model without overlapping discrete constraints by default this is likely to be useful.