Я использую Google.OrTools
версия 7.0.
Я создал небольшой интерфейс, чтобы добавить ограничения к CpModel
:
public interface ISatConstraintWrapper
{
IEnumerable<BoundIntegerExpression> GenerateConstraints();
void BindToModel(CpModel model);
}
Шаблон проектирования довольно прост, вот фиктивный пример, который устанавливает равенство для всех IntVar
s в списке:
class MakeAllVarsEqual : ISatConstraintWrapper
{
public MakeAllVarsEqual(List<IntVar> vars)
{
_vars = vars;
}
public IEnumerable<BoundIntegerExpression> GenerateConstraints()
{
for (var i = 0; i < _vars.Count - 1; i++)
{
yield return _vars[i] == _vars[i+1];
}
}
public void BindToModel(CpModel model)
{
foreach (var constraint in GenerateConstraints())
{
model.Add(constraint);
}
}
private readonly List<IntVar> _vars;
}
Далее, я хотел бы использовать мой ISatConstraintWrapper
, но для минимизации / максимизации ограничений.
Вот пример того, что я собираюсь сделать:
class MinimizeIntExpression : ISatConstraintWrapper
{
public MinimizeIntExpression(List<IntVar> vars, List<int> coeffs)
{
_vars = vars;
_coeffs = coeffs;
}
public IEnumerable<BoundIntegerExpression> GenerateConstraints()
{
for (var i = 0; i < _vars.Count; i++)
{
yield return _vars[i]*_coeffs[i];
}
}
public void BindToModel(CpModel model)
{
model.Minimize(new SumArray(GenerateConstraints()));
}
private readonly List<IntVar> _vars;
private readonly List<int> _coeffs;
}
Но я не могу, поскольку _vars[i]*_coeffs[i]
возвращает IntegerExpression
, но не BoundIntegerExpression
.
Однако, даже если последний представляет IntegerExpression
в домене, эти два класса кажутся несвязанными, и я не нашел способа снизить BoundIntegerExpression
до IntegerExpression
.
Конечно, я мог бы создать два разных интерфейса, но это не очень удобно, например, если я хочу сохранить свои обертки ограничений в списке.
Можно ли преобразовать BoundIntegerExpression
в IntegerExpression
? Если нет, как я могу изменить свою оболочку для обработки обоих типов ограничений?