构造启发式算法:最邻近插入法

来源:互联网 发布:java 验证码识别 库 编辑:程序博客网 时间:2024/06/11 13:42

一、背景

构造启发式算法根据一些准则,每一次将一个不在线路上的点增加进线路,直到所有的点都被安排进线路为止。该类算法的每一步,把当前的线路构形跟另外的构形进行比较并加以改进,后者或是根据某个判别函数(例如总费用)会产生最大限度节约的构形,或是以最小代价把一个不在当前构形上的需求对象插入进来的构形。比较著名的构造启发式算法有:节约法(Saving Algorithm, Clark和Wright ), 插入法(Jameson和Model)等。

二、问题描述

1. 已知一条完整的线路R和一个额外的节点v
2. 将节点v插入到线路R中,要求插入后线路增加的距离最小

三、设计方案

四、算法描述


注释:
  • 寻找局部线路上最近的第一个点v的原理
首先构造线路上所有点(包括原点)到剩余的点之间的距离矩阵 D,然后找到矩阵 D 中的最小值 Dmin,最后找到 D 中第一个等于 Dmin 值得元素的位置,该元素即为离局部线路上最近的点 v。
 
D =    20    10    30    20    11    23    24    15    31    28     9    50K>> [Dmin, index] = min(min(D));K>> DminDmin =     9K>> [row, col] = find(D == Dmin)row =     3col =     3K>> v = indexMat(col(1));
indexMat为索引矩阵,存储着未分配进线路中的节点编号。

  • 寻找待插入的弧(i, j)的原理
利用矩阵运算实现该运算!
  • 注意最后的矩阵要还原回与原来维度相同的矩阵,缺少的维度用0填充

五、MATLAB程序

function [newRoute] = NI(DIST, route, insertPoint)% 最邻近插入法% DIST: 客户及原点之间的距离矩阵% route: 插入操作的目标线路, 行向量% insertPoint:源线路中待操作的客户序号 1 ~ dim% paremetersdim = size(route, 2);newRoute = zeros(1, dim);% 存储新线路的矩阵,dim维矩阵newRouteOnlyCus = [];% 存储新线路的矩阵(只有客户点),从0开始动态添加客户点cusNumInRoute = 0;% 线路中的客户数% 将待插入的点加入插入操作的目标线路for k = 1 : dimif( route(1, k) == 0 )route(1, k) = insertPoint;cusNumInRoute = cusNumInRoute + 1;% 将添加的客户算入总数中break; % 跳出 for k = 1 : dimelsecusNumInRoute = cusNumInRoute + 1;end % ifend % forindexMat = [route(1:cusNumInRoute)];<span style="white-space:pre"></span>% DIST的索引矩阵% 找到点l,构成0-p-0[temp, p] = min(DIST(end, route(1 : cusNumInRoute)));newRouteOnlyCus = route(p);[temp, index] = find(indexMat == route(p));indexMat(index) = [];% 将剩余的客户插入到线路中while( ~isempty(indexMat) )% 搜寻离已形成的局部线路上最近的点v% [temp, index1] = min(DIST(newRouteOnlyCus, indexMat), 2);% [temp, index2] = min(temp);% inserCustomer = indexMat(index1(index2));expandRoute = [newRouteOnlyCus, dim+1];[minDist, index] = min(min(DIST(expandRoute, indexMat)));[minRow, minCol] = find(DIST(expandRoute, indexMat) == minDist);inserCustomer = indexMat(minCol(1));% 离已形成的局部线路上最近的第一个点v% 在局部线路中寻找待插入的弧(i, j)expandRoute = [dim+1, newRouteOnlyCus, dim+1];expandRoutePre = expandRoute(1 : end-1);expandRouteNext = expandRoute(2 : end);insertCost = DIST(expandRoutePre, inserCustomer) + DIST(expandRouteNext, inserCustomer) - DIST(expandRoutePre' + (expandRouteNext'-1)*(dim+1));% insertCost为列向量[temp, index] = min(insertCost);% 找到插入费用最小的线路inserRoute = index;% 将v插入到index中if( inserRoute == 1 )newRouteOnlyCus = [inserCustomer, newRouteOnlyCus];elseif( inserRoute == length(newRouteOnlyCus) + 1 )newRouteOnlyCus = [newRouteOnlyCus, inserCustomer];elsenewRouteOnlyCus = [newRouteOnlyCus(1 : inserRoute-1), inserCustomer, newRouteOnlyCus(inserRoute : end)];end % 结束 if% 更新索引矩阵 indexMat[temp, index] = find(indexMat == inserCustomer);indexMat(index) = [];end% 结束 while% 将 newRouteOnlyCus 还原为dim维矩阵newRoute(1 : length(newRouteOnlyCus)) = newRouteOnlyCus;% keyboard();end


测试NI()函数功能的函数:
function [] = tb_NI()% 测试NI()的函数功能% parametersload('CUSTOMER_INFO.mat');% CUSTOMER_INFO: 客户信息load('DIST.mat');% DIST: 两地之间的距离,原点在最后一维route = [2 1 4 5 0 0 0 0];insertPoint = 7;% NI插入[newRoute] = NI(DIST, route, insertPoint);% 结果比较fprintf('original route:\n');routefprintf('new route:\n');newRoutekeyboard();end



0 0
原创粉丝点击