I'm using the OR-Tools CP-SAT solver on a list of $n$ boolean variables $x_i$. I'm trying to maximize the minimal distance between two true variables in this list, as illustrated by the following figure.
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
<-------------> <---------> <----------------->
4 3 5
(minimum)
In other words, mathematically, I'm trying to maximize the expression : $$\min(j-i \mid 0 < i < j < n, x_i = x_j = 1)$$
At the moment, I'm using this algorithm, basically brute-forcing all the possible intervals:
minimalDistance = model.NewIntVar(0, n);
for (k = 1; k < n; ++k) {
isIntervalAtLeastOfGivenSize[k] = model.NewBoolVar();
model.AddEquivalence(
isIntervalAtLeastOfGivenSize[k],
minimalDistance >= k
);
}
for (i = 0; i < n; ++i) {
for (j = i + 1; j < n; ++j) {
model.AddImplication(
x[i] and isIntervalAtLeastOfGivenSize[j - i + 1],
x[j] = false
)
}
}
model.maximize(minimalDistance)
model.solve()
It works, but I have a feeling that it's not the best approach: it adds a lot of constraints, and it doesn't scale well when $n$ gets bigger. Is there a better way to do it?