1

我正在研究 TSP 的变体,其中每个节点都有一个时间窗口,但我在计算成本函数时遇到了一些问题。我使用的是后继模型,所以我有一个列表,其中每个变量表示下一个目的地,Xi = j 是从节点 i 到节点 j 的链接。

我的代码如下所示:

:-lib(ic).
:-lib(branch_and_bound).
:-lib(propia).
:-[nodes].

tsp(Next, Cost):-
  Cost::1..10000,
  Next::1..10000,

  %Constraints
  alldifferent(Next),
  different_from_index(Next),
  circuit(Next),
  create_objective(Next, Cost),
  minimize(labeling(Next), Cost).

其中different_from_index是 Next 变量的索引与其值之间的约束:Next[i] != i,而create_objective是定义目标函数的谓词。首先 create_objective 谓词创建链接成本列表,因此使用简单的 sumlist 谓词很容易获得成本。但我需要为每个节点定义一个时间窗口,我想是这样的:

time_window([], _, _, 0).
time_window([HCost | TCost], Next, Start, Cost):-
  element(Start, Next, Destination),
  time_window(TCost, Next, Destination, Cost1),
  Cost #= Cost1 + HCost,
  node(Destination, Min, Max) infers most,
  Cost #>= Min, Cost #=< Max.

[H成本| TCost] 是前面提到的成本列表,但已排序和反转(因此我将列表的 n 元素作为第一个链接,将 n-1 作为第二个链接,依此类推)。此外,节点谓词包含在开头加载的 prolog 文件中。不幸的是,这似乎不起作用:它既不返回 false 也不返回错误的解决方案。经过一段时间的计算,我收到此消息:

[eclipse 2]: tsp(Next, Cost).
bb_min: search did not instantiate cost variable
Aborting execution ...
Abort

我理解错误,但我不知道如何解决它。我使用更简单的模型和类似的 time_window 谓词成功地做到了,但在这种情况下似乎不合适。

谁能帮我吗?谢谢指教。

4

1 回答 1

1

让我们从以下基本 TSP 程序开始。它将距离矩阵作为输入Dist,并维护一个后继数组Next,以及一个Legs包含从每个节点到其后继节点的距离的距离数组。我们最小化Cost,这是行驶的总距离。

:- lib(ic).
:- lib(branch_and_bound).

tsp(Dist, Next, Cost) :-
    dim(Dist, [N,N]),       % get distance matrix size

    dim(Next, [N]),         % successor variables
    Next #:: 1..N,
    circuit(Next),          % they must form a circuit

    dim(Legs, [N]),         % Legs[I] is distance I->Next[I]
    ( for(I,1,N), param(Dist,Next,Legs) do
        element(I, Next, J),
        element(J, Dist[I], DistIJ),
        element(I, Legs, DistIJ)
    ),
    Cost #= sum(Legs),

    % search and minimize
    minimize(search(Legs,0,smallest,indomain_min,complete,[]), Cost).

要启用时间窗口处理,请添加一个数组Time,给出每个节点的到达时间,然后可以根据要求对其进行约束。到达节点后继节点的I时间可以计算为到达时间I加上I从其后继节点的旅行时间(为简单起见,假设距离 = 时间,并且我们在时间 0 从节点 1 开始)。这将导致

tsp(Dist, Next, Time, Cost) :-
    dim(Dist, [N,N]),       % get distance matrix size

    dim(Next, [N]),         % successor variables
    Next #:: 1..N,
    circuit(Next),          % they must form a circuit

    dim(Legs, [N]),         % Legs[I] is distance I->Next[I]
    dim(Time, [N]),         % Time[I] is arrival time at I
    ( for(I,1,N), param(Dist,Next,Legs,Time) do
        element(I, Next, J),
        element(J, Dist[I], DistIJ),
        element(I, Legs, DistIJ),

        ( I==1 -> TimeAtI = 0 ; element(I, Time, TimeAtI) ),
        element(J, Time, TimeAtJ),
        TimeAtJ #= TimeAtI + DistIJ
    ),
    Cost #= sum(Legs),  % total distance travelled

    % search and minimize
    minimize(search(Legs,0,smallest,indomain_min,complete,[]), Cost).

样品运行:

?- data(b6, Dist), tsp(Dist, Next, Time, Cost).
Found a solution with cost 2495
Found a solution with cost 2441
Found a solution with cost 2336
Found no solution with cost 1525.0 .. 2335.0

Dist = []([](0, 153, 510, 706, 966, 581),
          [](153, 0, 422, 664, 997, 598),
          [](510, 422, 0, 289, 744, 390),
          [](706, 664, 289, 0, 491, 265),
          [](966, 997, 744, 491, 0, 400),
          [](581, 598, 390, 265, 400, 0))
Next = [](2, 3, 4, 5, 6, 1)
Time = [](2336, 153, 575, 864, 1355, 1755)
Cost = 2336
Yes (0.00s cpu)
于 2021-05-29T02:26:17.517 回答