首页 文章

无法推断出AMPL的上限

提问于
浏览
1

我打算进行优化,我希望在受到一些时间限制的系统中最大化流量,并且一些“必须满足这些路线”的限制 . 第一次约束规定每辆车不得超过24小时的工作量(以分钟表示) . 第二次约束是一个小区消除约束,它还说明在“车辆”有时间行驶之前,“访问”节点的启动时间不能被激活.Custraint3描述了K1和N1之间的道路必须使用不超过9时间,使用任何车辆k . 最后一个约束表明来自特定节点的所有车辆必须在一天结束时返回 .

maximize maxamount: sum{i in V, j in V, k in K} x[i,j,k];

 subject to TimeConstraint {k in K}: 
     sum{i in V, j in V} traveltime[i,j]*x[i,j,k] <= 1440; 

 subject to StartTime{i in V,j in V, k in K}:
     starttime[i] + servicetime[i] +traveltime[i,j] - 1300 * (1 - x[i,j,k]) <= starttime[j];

 subject to Constraint3:
     sum{k in K} x["K1","N1",k] <= 9;

 subject to EndNode{k in K}: 
     sum{i in V}x[i,"K1",k] - sum{j in V} x["K1",j,k]= 0;

Constraint3和EndNode有几个相同类型的约束(只是与其他“预定义位置”,例如K1和N2之间的道路不能超过4次访问等等) .

我的问题是我得到了错误Impossible推导的边界x [K1,K1,1]有下限= 0和上限= -76我已经理解这源于冲突的约束 . 不过我的问题是:怎么样?几乎只使用二进制变量,我不明白为什么上面的代码不起作用 . 我误解了我在模特中实际做了些什么吗?

我注意到编译器只在i = j时抱怨,所以我检查了我的.dat文件并注意到i和j之间的旅行时间,当i = j时非常大(所以程序不会选择那些路线) . 但是,将.dat文件编辑为不再自动超出TimeConstraints限制仍会给出相同的错误(尽管较小,现在上限为-1而不是-76) .

我希望有人可以对此有所了解

在此先感谢Cenderze

1 回答

  • 2

    i和j之间的旅行时间,当i = j非常大时(因此程序不会选择那些路线)

    如果 traveltime[i,j] = M (非常大)那么 StartTime 用于 i=j 读取

    servicetime[i] + M - 1300 * (1 - x[i,j,k]) <= 0     <=>
    1300 * x[i,j,k] <= 1300 - servicetime[i] - M
    

    因此,每当 M > 1300 - servicetime[i] 时,问题都是不可行的 .

    我建议使用 i<>j 为所有对 (i,j) 定义 X 变量,或者(如果问题是对称的)使用 i < j 定义.2424557_ .

    Follow up from the comment

    插入_2424562时,以下代码段效果很好:

    param n := 10;
    set N:= 1..n;
    set V := {i in N, j in N: i <> j};
    display V;
    

    输出:

    set V :=
    (1,2)    (2,3)    (3,4)    (4,5)    (5,6)    (6,7)    (7,8)    (8,9)    (9,10)
    (1,3)    (2,4)    (3,5)    (4,6)    (5,7)    (6,8)    (7,9)    (8,10)   (10,1)
    (1,4)    (2,5)    (3,6)    (4,7)    (5,8)    (6,9)    (7,10)   (9,1)    (10,2)
    (1,5)    (2,6)    (3,7)    (4,8)    (5,9)    (6,10)   (8,1)    (9,2)    (10,3)
    (1,6)    (2,7)    (3,8)    (4,9)    (5,10)   (7,1)    (8,2)    (9,3)    (10,4)
    (1,7)    (2,8)    (3,9)    (4,10)   (6,1)    (7,2)    (8,3)    (9,4)    (10,5)
    (1,8)    (2,9)    (3,10)   (5,1)    (6,2)    (7,3)    (8,4)    (9,5)    (10,6)
    (1,9)    (2,10)   (4,1)    (5,2)    (6,3)    (7,4)    (8,5)    (9,6)    (10,7)
    (1,10)   (3,1)    (4,2)    (5,3)    (6,4)    (7,5)    (8,6)    (9,7)    (10,8)
    (2,1)    (3,2)    (4,3)    (5,4)    (6,5)    (7,6)    (8,7)    (9,8)    (10,9);
    == 1 ==========================
    

    将您的代码段更改为

    set N = {'K1', 'K2','K3','K4'};
    set V := {i in N, j in N: i != j};
    display V
    

    并试一试 . 我明白了:

    set V :=
    (K1,K2)   (K1,K4)   (K2,K3)   (K3,K1)   (K3,K4)   (K4,K2)
    (K1,K3)   (K2,K1)   (K2,K4)   (K3,K2)   (K4,K1)   (K4,K3);
    == 1 ==========================
    

    我希望这有帮助!

相关问题