or-tools - 从 SumArray() 计算标准偏差

or-tools - Compute the stdev from a SumArray()

我需要使用 Google 的优化工具为员工制定计划。 限制之一是每个员工的工作时间大致相同。

因此,我想在一个列表中汇总每个员工的工作小时数,然后最小化此列表的标准差。

var workingTimes = new List<SumArray>();
foreach (var employee in employees) {
    // Gather the duration of each task the employee is
    // assigned to in a list
    // o.IsAssign is an IntVar and task.Duration is an int
    var allDurations = shifts.Where(o => o.Employee == employee.Name)
                .Select(o => o.IsAssigned * task[o.Task].Duration);

    // Total time the employee is working
    var workTime = new SumArray(allDurations);
    workingTimes.Add(workTime);
}

现在我想最小化 workingTimes 的标准偏差。我尝试了以下方法:

IntegerExpression workingTimesMean = new SumArray(workingTimes) * (1/workingTimes.Count);    
var gaps = workingTimes.Select(o => (o - workingTimesMean)*(o - workingTimesMean));
var stdev = new SumArray(gaps) * (1/gaps.Count());
model.Minimize(stdev);

但是最后一个代码片段第 2 行的 LINQ 查询向我抛出一个错误:

Can't apply operator * to IntegerExpression and IntegerExpression

如何计算 Google.OrTools.Sat.SumArray 的标准偏差?

'natural'API只支持线性表达式。 您需要使用 AddProductEquality() API.

请注意 1 / Gaps.Count() 将始终 return 0(我们在进行整数运算)。 所以你需要扩大一切。

就个人而言,我只会最小化 abs(val - average) 的未缩放总和。无需除以元素个数。 只需检查平均值的计算是否具有正确的精度(再一次,我们处于整数运算中)。

您也可以考虑将 max(abs(val - average)) 最小化。这更简单,可能就足够了。