CPMpy constraints are CPMpy Expressions, with the requirement that they are boolean. Each expression can have nested subexpressions. Any operation comparing 2 constraints will return a new constraint. Thus, you can save the first constraint in an object c
and then use a loop to create the disjunction with c | new_constraint
.
In your example, based on the 'this is want I want in the end' lines of code, this can be done as follows:
# Assume we have the following list of lists for mask
foo = [[1,1], [3,2], [5,0]]
c = False # Just to create an expression which won't play a role in the disjunction
for f in foo:
c |= (cp.abs(cp.sum(p[f])) == 3)
m += c
(Notice that I use cp.abs and cp. sum)
A more elegant way to do it would be using the cp.any() expression, which basically is what I understood you want.
m += cp.any(cp.abs(cp.sum(p[f])) == 3 for f in foo)
This creates the following constraint (with the foo list of list I used):
or([abs(sum([puzzle[1,0], puzzle[1,1], puzzle[1,2], puzzle[1,3], puzzle[1,4], puzzle[1,5], puzzle[1,0], puzzle[1,1], puzzle[1,2], puzzle[1,3], puzzle[1,4], puzzle[1,5]])) == 3, abs(sum([puzzle[3,0], puzzle[3,1], puzzle[3,2], puzzle[3,3], puzzle[3,4], puzzle[3,5], puzzle[2,0], puzzle[2,1], puzzle[2,2], puzzle[2,3], puzzle[2,4], puzzle[2,5]])) == 3, abs(sum([puzzle[5,0], puzzle[5,1], puzzle[5,2], puzzle[5,3], puzzle[5,4], puzzle[5,5], puzzle[0,0], puzzle[0,1], puzzle[0,2], puzzle[0,3], puzzle[0,4], puzzle[0,5]])) == 3])]