Consider filtering functionality in `ConstrainedQuadraticModel.iter_constraint_data()`
Currently ConstrainedQuadraticModel.iter_constraint_data() always iterates over every constraint in the model.
We should consider adding some keyword arguments to make that a bit easier when handling constraints in bulk. I am imagining something like
def iter_constraint_data(sample_like, *, filter_function=None):
if callable(filter_function):
yield from filter(filter_function, self.iter_constraint_data(sample_like))
return
...
and/or
def iter_constraint_data(sample_like, *, labels=None):
...
if labels is None:
labels = self.constraint_labels
for label in labels:
constraint = self.constraint(label)
lhs = constraint.lhs.energy((sample, labels))
rhs = constraint.rhs
sense = constraint.sense
...
Hi @arcondello,
I am interested in this feature. I have some pre-processing and post-processing steps which start from a feasible solution and then make changes to it by changing the values of a few variables. Every time I make such a change I use the iter_constraint_data method to check if the change violates any constraints. When doing this it would save computation time if I could check only those constraints which involve the variables that are about to be changed.
The second approach that you outlined above (passing a labels argument) looks to me like it would be suitable for saving computation time. The first approach (passing a filter_function) looks like it still iterates over all the constraints because the filter_function needs to be applied to each constraint. Is my understanding correct?
The second approach that you outlined above (passing a labels argument) looks to me like it would be suitable for saving computation time. The first approach (passing a filter_function) looks like it still iterates over all the constraints because the filter_function needs to be applied to each constraint. Is my understanding correct?
Yes exactly. If you know what specific constraints you're looking for by label, we can easily fetch those and only those. But if you want to filter by some other property, or by say a regex of the label, we need to iterate over all constraints.
That said, there may be some performance benefit even in the latter case because you can bypass the energy calculation which is where most of the time is spent.
If either/both would be a useful feature for you, we can look into making the change(s) soon.
Both approaches seem useful, but the potential speedup of the second approach (passing a labels argument) would be especially useful in my case. I think that if the second approach is implemented I can always combine it with filter_function by doing something like this.
labels = [lbl for lbl in cqm.constraint_labels if filter_function(lbl)]
cqm.iter_constraint_data(sample, labels=labels)
That would only allow me to filter based on the constraint label and not based on any other property.
https://github.com/dwavesystems/dimod/pull/1382 implements the labels approach.
@mirko-sof , https://github.com/dwavesystems/dimod/pull/1382 has been merged with the labels approach. Are you comfortable testing by installing from source or do you need/want a deploy with the change?
I'll try installing from source. Thanks for the quick turnaround.