【组合优化】旅行商问题Traveling Salesman Problem(TSP)-约束定义

朴素约束

最朴素的约束为:每个节点有且仅有两条边。

constr2trips = optimconstr(nStops,1);
for stop = 1:nStops
    whichIdxs = outedges(G,stop); % Identify trips associated with the stop
    constr2trips(stop) = sum(trips(whichIdxs)) == 2;
end
tsp.Constraints.constr2trips = constr2trips;

这样得到的结果大概率如下图所示,会有许多子回路

 子回路的个数通过如下进行计算:

tspsol = solve(tsp,'options',options)
tspsol.trips = logical(round(tspsol.trips))
Gsol = graph(idxs(tspsol.trips,1),idxs(tspsol.trips,2),[],numnodes(G));
tourIdxs = conncomp(Gsol)
numtours = max(tourIdxs); % Number of subtours
fprintf('# of subtours: %d\n',numtours);

如何消除子回路成为定义约束的关键问题。

额外的约束称为子回路消除约束。

子回路消除约束

由于无法在问题求解的一开始就找到子回路,子回路只能在通过上述朴素约束求解的基础上进行。

基本的思路是,找到上述基本解中的子回路,通过增加约束消除子回路。

如何消除子回路?举一个例子。如果一个子回路是5个节点组成的,这个子回路就有5条互联的边,增加的一个不等式约束为:这五个节点之间的边不能多于5.

推广得到:任意小于nSteps的集合若包含N个节点,则这N个节点包含的边不能多于N。

在迭代的过程中遇到一个子回路则添加上述的一个约束,直到最终只剩下1个子回路。代码如下所示。

figure
hGraph = plot(G,'XData',stopsLon,'YData',stopsLat,'LineStyle','none','NodeLabel',{});
hold on
% Draw the outside border
plot(x,y,'r-')
hold on
% Index of added constraints for subtours
k = 1;
while numtours > 1 % Repeat until there is just one subtour
    % Add the subtour constraints
    for ii = 1:numtours
        inSubTour = (tourIdxs == ii); % Edges in current subtour
        a = all(inSubTour(idxs),2); % Complete graph indices with both ends in subtour
        constrname = "subtourconstr" + num2str(k);
        tsp.Constraints.(constrname) = sum(trips(a)) <= (nnz(inSubTour) - 1);
        k = k + 1;        
    end
    
    % Try to optimize again
    [tspsol,fval,exitflag,output] = solve(tsp,'options',options);
    tspsol.trips = logical(round(tspsol.trips));
    Gsol = graph(idxs(tspsol.trips,1),idxs(tspsol.trips,2),[],numnodes(G));
    % Gsol = graph(idxs(tspsol.trips,1),idxs(tspsol.trips,2)); % Also works in most cases
    
    % Plot new solution
    hGraph.LineStyle = 'none'; % Remove the previous highlighted path
    highlight(hGraph,Gsol,'LineStyle','-')
    drawnow

    % How many subtours this time?
    tourIdxs = conncomp(Gsol);
    numtours = max(tourIdxs); % Number of subtours
    fprintf('# of subtours: %d\n',numtours)
    fprintf('# total trip length: %f\n',fval)   
end
title('Solution with Subtours Eliminated');

迭代过程如下图所示:

最终的约束如下所示。其中包含了41个消除子回路约束。

 

最终得到的结果如下图所示:

解的最优性说明见下节。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值