вот лучшая версия
foreach (var i in Enumerable.Range(0, size))
{
model.AddElement(assignments[i], assignments, reciprocals[i]);
model.Add(reciprocals[i] == i).OnlyEnforceIf(reciprocalBools[i]);
model.Add(reciprocals[i] != i).OnlyEnforceIf(reciprocalBools[i].Not());
}
model.Minimize(999 * LinearExpr.Sum(reciprocalBools));
У нас также есть обратное ограничение (model.AddInverseConstraint(x_array, y_array)
)
что обеспечивает
x_array[i] == j <=> y_array[j] == i
Тем не менее, мне интересно, если вам все это нужно.
Если xi = {xi_1, .., xi_n}
(отображение в массив логических переменных)
reciprocalBools[i] is true
если exists j, such that (xi_j && xj_i) is true
Так что вам просто нужно сосчитать пары (xi_j && xj_i)
обе верные.
Это не просто.
учитывая i и j, i! = J
Literal implied = model.newBoolVar("");
model.addBoolOr(new Literal[] {xi_j.not(), xj_i.not(), implied});
model.addImplication(implied, xi_j);
model.addImplication(implied, xj_i);
Теперь у вас есть implied <=> xi_j && xj_i
. И вы можете сосчитать эти implied
переменные.
если i == j, не создавайте переменную implied
, не добавляйте логическое ограничение 3 и используйте xi_i напрямую.