如何只在同一节点开始和结束一条路径?

时间:2013-12-25 20:25:44

标签: linear-programming cplex ilog

我正在尝试在Cplex / OPL中运行此模型,以找到商店距离的最佳路径,以及每个商店中不同产品的数量+价格。 问题是我得到了脱节的路径 - “岛屿”。 我需要添加什么约束才能获得一个在节点1开始和结束的闭合路径? 这是模型:

 dvar float+ x[products,stores];
 dvar boolean y[stores,stores];


 minimize ((sum(i in products, j in stores) prices[i,j]*x[i,j]) + (sum(j in stores, k     
 in stores) gas*distance[j,k]*y[j,k]));

  subject to {
    sum(k in stores) y[1,k] == 1;
    sum(j in stores) y[j,1] == 1;
    forall(j in stores) 
        sum(i in products) x[i,j] <= M*sum(k in stores) y[j,k];
    forall(j in stores)
        sum(i in products) x[i,j] <= M*sum(k in stores) y[k,j];
    forall(i in products) sum(j in stores) x[i,j] == demand[i];
    forall(i in products, j in stores) x[i,j] <= quantity[i,j];
    forall(j in stores, k in stores) y[j,k] + y[k,j] <= 1;
    forall(j in stores) sum(k in stores) y[j,k] == sum(k in stores) y[k,j];

}

谢谢!

1 个答案:

答案 0 :(得分:2)

你要解决的是 traveling salesman problem的变体。具体来说,你得到的是 subours,,这是一个涉及更少的封闭路径比所有节点(你的情况下的商店)。

给定的一组节点有一个指数的子层。围绕 subour elimination 约束存在大量文献。幸运的是,对于实际中的小问题,我们可以根据需要添加减少消耗的约束。

Subtour Elimination

以下是如何消除涉及 s 商店(s&lt; num_stores)的 S 的想法:

英文:我们从节点(商店)集合开始分为两组S和T.让S成为子集中的商店集合。设T为S的外部商店,即所有其他商店。我们希望打破单循环路径,只涉及S的商店。

伪代码

Do while:
    Solve the current problem 
    If you don't find any subtours, you are done. Exit.
    If there are subtours, add the subtour elimination constraints (see details below)
    Continue

实施一组约束来消除当前的气流

对于每个子句(“岛屿”),您必须先创建一组shops_in_subtour。所有其他节点(商店)进入另一组(T)shops_not_in_subtour

将以下内容添加到约束集:

forall(s in shops_in_subtour)
  forall(t in shops_not_in_subtour)
    sum y[s,t] > = 1; // at least one edge must leave S and go to T
    sum y[t,s] > = 1; // at least one edge must enter the set S from T

如果您的问题很小,您会发现添加一些这些约束就足够了。希望能帮助你前进。

根据OP的后续问题进行更新

如何检测小部件

您将检查CPLEX / Solver 外的

>

英语理念:您从原点商店开始并遍历路径,跟踪每个visited商店。如果你回到原点,并且仍然有一些二进制Y变量,你有一个或多个子。 (从技术上讲,你可以从任何商店开始,但从一个商店开始更容易理解。)

Initialize visited_shop = NULL; 
Find the Yij that is 1. (Starting edge for the path)
Do while (There are more Y variables = 1 remaining)
  Add the destination of the new binary variable to list of visited_shops
  Check if you are done (are you back at shop 1):
    if Yes: 
       If no more binary variables left, you are done. Exit.
       If there are some more non-zero binary variables, subtour detected
    if No: 
       pick the next Y variable whose origin is current Y_variable's destination
  Continue