TSP / CPP变体-子行程约束

时间:2019-05-24 12:00:53

标签: traveling-salesman integer-programming

我正在开发一个优化问题,该问题是Traveling Salesman的变体。在这种情况下,您不必游览所有城市,没有必要的起点和终点,游览长度有一个最小和最大界限,如果需要,您可以遍历每个弧线多次,并且非线性与所遍历的弧相关联的目标函数(以及遍历每个弧的次数)。决策变量是整数,即您遍历每个圆弧的次数。

我已经在Pyomo中开发了一个非线性整数程序,并且正在从NEOS服务器获得结果。但是我没有设置子行程约束,结果是两个断开的子行程。

我可以找到TSP的整数编程公式,该公式说明了如何制定子轮廓约束,但这与标准TSP略有不同,我正在尝试弄清楚如何开始。我们将不胜感激。

编辑:问题表述

50个弧,节点之间不是穷尽的对。 50个决策变量N_ab是> = 0的整数,对应于您从a遍历到b遍的次数。每个N_ab都有一个长度和利润。有两个约束条件,即所有ab的length_ab * N_ab之和在最小和最大距离之间。我有一个约束,即进入每个节点的N_ab的总和等于离开该节点的N_ab的总和,您根本不能访问一个节点,也不能多次访问它。目标函数是非线性的,与弧对之间的相互作用有关(与子行程无关)。

子游览:查看math.uwaterloo.ca/tsp/methods/opt/subtour.htm,该公式不适用,因为我不需要参观所有城市,并且可能无法访问。例如,假设我有20个节点和50个弧(所有弧的长度为10)。距离限制是针对长度恰好为30的漫游,这意味着我最多可以访问三个节点(从A-> B-> C-> A =长度30开始)。因此,我将完全不会访问其他节点。消除TSP子行程将要求我具有从节点子组ABC到未访问节点子组的边缘-这对于我的问题不是必需的

1 个答案:

答案 0 :(得分:1)

这是一种根据奖金收集TSP(例如this paper)进行改编的方法。令V为所有节点的集合。我假设V包含一个 depot 节点(称为节点1),该节点必须在巡视中。 (否则,您可以添加一个充当此角色的虚拟节点。)

如果我们至少访问节点x[i]一次,则让i等于1,否则为0。 (您的模型中可能已经有这样的决策变量。) 添加这些约束,这些约束定义了x[i]

x[i] <= sum {j in V} N[i,j]    for all i in V
M * x[i] >= N[i,j]             for all i, j in V

换句话说:如果没有边缘出节点x[i]i不能等于1,如果有边缘出节点{{,x[i]必须等于1。 1}}。 (在这里,如果我们从iN[i,j]i为1,而j是一个足够大的数字,可能等于您可以遍历的最大次数边缘。)

这是为M的所有子集S定义的子行程消除约束,以使V包括节点1,以及{{1}中的所有节点S }}:

i

换句话说,如果我们访问不在V \ S中的节点sum {j in S} (N[i,j] + N[j,i]) >= 2 * x[i] ,则必须至少有两个边缘进入或离开i。 (对于S而言,子游览违反了此约束,该约束等于子游览中包含1的节点。)

我们还需要一个约束,要求节点1在巡视中:

S

我可能在方向索引上玩得有些松懈,即我不确定您的模型是否设置了S或类似的东西,但希望这个主意很清楚,您可以修改我的必要的方法。