Google ORTools - 不能共享相同路由的节点(再次)

Posted

技术标签:

【中文标题】Google ORTools - 不能共享相同路由的节点(再次)【英文标题】:Google ORTools - Nodes that can't share the same route (again) 【发布时间】:2020-06-26 07:12:31 【问题描述】:

参考我之前的请求prievousRequest,我需要帮助解决另一个问题:一条路线不能同时具有两个以上的工作类别。

条件如下:

节点 A:工作类别 1 和工作类别 2

节点 B:工作类别 3

节点 C:工作类别 1

节点 D:工作类别 2

解决方案:

Depot > A > C > Depot,是一条有效路线

Depot > B > D > Depot,是一条有效路线

Depot > A > B > Depot,不是有效路线

Depot > A > D > Depot,是一条有效的路线

Depot > B > C > D > Depot,不是有效路线

因此,车辆上的前两个工作类别必须排除添加任何其他具有不同工作类别的节点。

感谢您的建议。

最好的,法比奥

#########################编辑#################### ##

... 尝试使用动态工作类型的旧代码...

#########################编辑2#################### ###

为了理解一些事情,我简化了上下文:那么只有 3 种工作类型

//work types for each nodes
long[][] worksMatrix = new long[5][];
worksMatrix[0] = new long[]  0 ;
worksMatrix[1] = new long[]  1, 2 ;
worksMatrix[2] = new long[]  3 ;
worksMatrix[3] = new long[]  1 ;
worksMatrix[4] = new long[]  2 ;

//1: meccanica (car mechanics work), 2: gomme (tires change\repair), 3: cristalli (car glass repair)

int meccanicaCallBack = routing.RegisterUnaryTransitCallback((long fromIndex) =>

    var fromNode = manager.IndexToNode(fromIndex);
    var nodeWorkTypes = model.WorksMatrix[fromNode];

    if (nodeWorkTypes.Contains(1))
        return 1;
    return 0;
);

routing.AddDimension(meccanicaCallBack, 0, 100, true, "meccanica");

int gommeCallBack = routing.RegisterUnaryTransitCallback((long fromIndex) =>

    var fromNode = manager.IndexToNode(fromIndex);
    var nodeWorkTypes = model.WorksMatrix[fromNode];

    if (nodeWorkTypes.Contains(2))
        return 1;
    return 0;
);

routing.AddDimension(gommeCallBack, 0, 100, true, "gomme");

int cristalliCallBack = routing.RegisterUnaryTransitCallback((long fromIndex) =>

    var fromNode = manager.IndexToNode(fromIndex);
    var nodeWorkTypes = model.WorksMatrix[fromNode];

    if (nodeWorkTypes.Contains(3))
        return 1;
    return 0;
);

routing.AddDimension(cristalliCallBack, 0, 100, true, "cristalli");

######################### 编辑 3 #################### ###

这样的?它似乎工作,

for (int i = 0; i < model.MaxStops.Length; i++)

    var a = solver.MakeIsGreaterCstVar(meccanicaDim.CumulVar(routing.End(i)), 0);
    var b = solver.MakeIsGreaterCstVar(gommeDim.CumulVar(routing.End(i)), 0);
    var c = solver.MakeIsGreaterCstVar(cristalliDim.CumulVar(routing.End(i)), 0);

    IntVarVector abc = new IntVarVector();
    abc.Add(a);
    abc.Add(b);
    abc.Add(c);

    solver.Add(solver.MakeSumLessOrEqual(abc, 2));

【问题讨论】:

【参考方案1】:

我能想到的最好的:

为每个工作类型创建一个维度。 在每个节点上相应地增加它 在车辆路线的尽头: 在每个维度上使用 Solver.MakeIsGreaterCstVar(cumul_var_for_worker_type_n, 0) 为每个工作人员类型创建一个布尔变量,指示该工作人员类型是否在路线上使用。 Solver.Add(solver.MakeSumLessOrEqual(bool_var_array, 2));

【讨论】:

感谢@laurent 的回答,我已经编辑了我的问题以获得进一步的帮助。 您需要工人 n 的路线末端的 cumul var。 @laurent 我也有类似的问题,可以看一下代码示例吗?很遗憾,我无法实施您的建议

以上是关于Google ORTools - 不能共享相同路由的节点(再次)的主要内容,如果未能解决你的问题,请参考以下文章

在 google ortools 中添加析取约束

线性规划 - Google ortools - 不正确的决策变量最终值

我如何向 Google ortools 添加一组值而不是下限和上限?

Ortools 在求解时设置约束

ortools:如何使用搜索策略sweep和best insert?

ORTools 任务分配优化与持续时间