【MDVRP】基于matlab IWD算法求解多仓库车辆路径规划问题【含Matlab源码 1310期】

741 阅读11分钟

一、VRP简介

1 VRP基本原理 车辆路径规划问题(Vehicle Routing Problem,VRP)是运筹学里重要的研究问题之一。VRP关注有一个供货商与K个销售点的路径规划的情况,可以简述为:对一系列发货点和收货点,组织调用一定的车辆,安排适当的行车路线,使车辆有序地通过它们,在满足指定的约束条件下(例如:货物的需求量与发货量,交发货时间,车辆容量限制,行驶里程限制,行驶时间限制等),力争实现一定的目标(如车辆空驶总里程最短,运输总费用最低,车辆按一定时间到达,使用的车辆数最小等)。 VRP的图例如下所示: 在这里插入图片描述 2 问题属性与常见问题 车辆路径问题的特性比较复杂,总的来说包含四个方面的属性: (1)地址特性包括:车场数目、需求类型、作业要求。 (2)车辆特性包括:车辆数量、载重量约束、可运载品种约束、运行路线约束、工作时间约束。 (3)问题的其他特性。 (4)目标函数可能是总成本极小化,或者极小化最大作业成本,或者最大化准时作业。

3 常见问题有以下几类: (1)旅行商问题 (2)带容量约束的车辆路线问题(CVRP) 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 该模型很难拓展到VRP的其他场景,并且不知道具体车辆的执行路径,因此对其模型继续改进。 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 (3)带时间窗的车辆路线问题 由于VRP问题的持续发展,考虑需求点对于车辆到达的时间有所要求之下,在车辆途程问题之中加入时窗的限制,便成为带时间窗车辆路径问题(VRP with Time Windows, VRPTW)。带时间窗车辆路径问题(VRPTW)是在VRP上加上了客户的被访问的时间窗约束。在VRPTW问题中,除了行驶成本之外, 成本函数还要包括由于早到某个客户而引起的等待时间和客户需要的服务时间。在VRPTW中,车辆除了要满足VRP问题的限制之外,还必须要满足需求点的时窗限制,而需求点的时窗限制可以分为两种,一种是硬时窗(Hard Time Window),硬时窗要求车辆必须要在时窗内到达,早到必须等待,而迟到则拒收;另一种是软时窗(Soft Time Window),不一定要在时窗内到达,但是在时窗之外到达必须要处罚,以处罚替代等待与拒收是软时窗与硬时窗最大的不同。 在这里插入图片描述 在这里插入图片描述 模型2(参考2017 A generalized formulation for vehicle routing problems): 该模型为2维决策变量 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 (4)收集和分发问题 (5)多车场车辆路线问题 参考(2005 lim,多车场车辆路径问题的遗传算法_邹彤, 1996 renaud) 在这里插入图片描述 由于车辆是同质的,这里的建模在变量中没有加入车辆的维度。 在这里插入图片描述 在这里插入图片描述 (6)优先约束车辆路线问题 (7)相容性约束车辆路线问题 (8)随机需求车辆路线问题

4 解决方案 (1)数学解析法 (2)人机交互法 (3)先分组再排路线法 (4)先排路线再分组法 (5)节省或插入法 (6)改善或交换法 (7)数学规划近似法 (8)启发式算法

5 VRP与VRPTW对比 在这里插入图片描述

二、IWD(智能水滴)算法简介

1 概述 在大自然中,河道是由流动的水滴组成的巨大群体移动创造的,相对于水滴群体本身来说,它们流经的河道周围就是它们所处在的环境,而这个环境正在被水滴群体的流动方向剧烈的改变着,同时周围的环境也在影响着水滴群体的流向。例如,环境当中的坚便的巨石泥土阳碍水滴的流动,而柔软松弛的泥土对于河水的流动的阻力就要小得多,实际上,大自然中的河流样貌就是由丁水滴群体和周围环境长期相互作用的结果而形成的。 依据人们的常识,大自然当中大部分的河流水道都是曲曲折折的,然而河流中的水清并不是像人类一样依靠视觉才到湖中或是海里的,而是,水滴在地球重力的作用下不断向前流动的。我们都知道,地球重力的方向指向地心,所以如果周围环境当中没有障碍物的话,水滴应该会沿着重力的方向向地心运动:由于在地球重力的作用下的,水滴在流动的过程当中会获得一定的加速度,因此随着运动其速度也会慢慢地不断增大。但是,在现实情况下,并不存在这样理想的状态也不存在从水清源头到地心的理想直线路径,甚至由于障砖物的影响,水消运动的实际路径与理想路径是远远不同的,因此才会有今天我们看到的河流样貌.而经研究发现,水滴在移动情况下建立起米的河道是最优的。河流当中的水滴具有两种属性:其本身具有一定的速度和携带一定量的泥土。在这样的情况下,水滴在运动时,就能够将泥上从一个地方向搬运到另一个地方。据我们所知,泥土会被水流从速度较高的地方携带到水流速度较低的地方,原因是当水滴速度较高时其具有的动能较大,能够克服地球重力对其所抛带泥土的作用,当水流具有的速度较低时,水滴携带的泥土会在地球重力的作用在水滴行进的路径中沉积下来。由于这个原因,泥土就会在水流速度较高的区域被搬移的越来越多,河道相应变得越来越深,也就吸引了越来越多的水流流向此处,进而可以容纳更多的水,同时水滴携带的泥土会在水流速度变慢时由于地球重力的作用 卸下来并沉积在河床上。 当一个水滴在河流中从一个地方流动另一个地方时,水滴具有的速度、水滴携带的泥土量、两个地方之间的泥土量三者都会发生明显的变化: 1)水滴流动时具有的速度会越来越大; 2)水滴携带的泥土量会越来越多: 3)位于这两点之间的河床上的泥土量会越来越少。

事实上,正如前文所描述,水清在从一个地方移动另一个地方的过程中会从河床上携带走一定量的泥土,河道上的泥土量会越来越少相应地水滴木身携带的泥土量会越来越多。在这个移动的过程中,水滴流动时具有的速度也会不断的变化。速度较大的水滴在流动时会从河床上携带走更多的泥上,除此之外,由于水滴流动时具有速度的快慢还和它周用所处的环境有关,周围的环境对水滴的移动起着阻碍的作用,所以当周围的泥土量较大时,水清在此段路径上流动时速度增长的就会越慢,当周围环境的泥土最较少时,水滴在此段路径上获得的速度就相应的会越来越快,向前流动就会更加容易:内此我们得到自然界中移动时的水滴具备以下属性: 1)流动速度高的水滴比流动速度低的水滴在路径中移动时能够携带走更多的泥土: 2)水滴能够在泥土量较小的路径中获取的速度增量大于比在泥土最较多的路径中获取的速度增量: 3)水滴在选择路径流动时会以较大的可能性朝着泥土量较少的路径移动. 3 智能水滴算法的基本原理 前文已经介绍了大自然中水滴具有某些典型的特点,根据上文中描述的这些特性, 根据人们的想象, 可以虚拟建立人工模型, 称为智能水滴(IWD) , 它具备两个重要的属性:我们一般用soil(IWD) 表示水滴木身携带的泥土量, 用veloci tv(/WD) 表示水清向前流动时本身具有的速度口,在工程问题巾,智能水滴流动时周围的环境就代表着我们需要解决的工程问题,而由于相互作用智能水滴寻找的最短路径就是我们解决工程问题找到的最优路径, 在子找最优路径的过程中, 智能水滴具有的两项重要属性即soil(JWD) 和 velocity(IWD) 是不断变化的。 我们假设某些智能水滴在某种环境下流动,从始点流向某个终点,在这种情况下,从始点到达终点的路径可能不止一条.这里所指的环境就是实践当中我们需要解决的工程类问题,可以分为两种问题: 其一:在终点已知的情况下,解决此类问题需要按照某个标准(一般情况下是距离)从始点到终点找到最佳路径. 其二:在终点的位置事先不知道的情况下,解决此类问题需要按照代价或者其他标准找到终点最优的位置。

三、部分源代码

clc; close all; clear all;

%% Variable initialization
iterations = 60;
pIter = 3; % # of parallel sol'ns calculated to find totalbest

stats = zeros(iterations, 2); % rows are iteration number, columns are best/worst

% Initial variables
tempInit = 150; % initial temperature for SA
temp = tempInit;
tempDec = 0.95; % temperature decrease rate
tempIter = 1;    % number of iterations at each step
soilInit = 1000;
velocityInit = 100;
a_v = 1000; a_s = 1000;
b_v = 0.01; b_s = 0.01;
c_v = 1; c_s = 1;

vel_params = [a_v b_v c_v];
soil_params = [a_s b_s c_s];

% Soil updating params
rho_o = 0.9;
rho_n = 1 - rho_o;
% Global soil updating params
rho_s = 0.8;
rho_iwd = -1.5;

% Data sets
pind = 1; % problem index
problempath = './../data/problems/';
problemfiles = { 'p01', 'p02', 'p03', 'p04', 'p05' };

solutionpath = './../data/solutions/';
solutionfiles = { 'p01.res', 'p02.res', 'p03.res', 'p04.res', 'p05.res' };

%% Load and format data
% Grab the first fileset
[desc, depot_desc, cust, depot] = parseProblemSet(strcat(problempath, problemfiles{pind}));
num_customers = desc(3);
num_depots = desc(4);
num_vehicles = desc(2);
all_coords = [cust(:,2:3); depot(:,2:3)];

% Build adjacency matrix row is source, col is dest
[ distMat globalSoilMat ] = prepareBoard(desc, depot_desc, cust, depot, soilInit);
soilMat = globalSoilMat;
% Soil weightings based on edge length
soilMat = log(distMat+1).*globalSoilMat; %logarithmic
%soilMat = distMat.*globalSoilMat; %linear
%soilMat = exp(distMat).*globalSoilMat; %exponential
soilMat = normalizeSoilMat(soilMat, soilInit);
globalSoilMat = soilMat; % globalSoilMat contains the soil going forward


%% Initialize agents
for i = 1:pIter
    dropstemp = [];
    for d = 1:num_depots % for each depot
        for v = 1:num_vehicles % populate vehicles
            dep = depot(d,1);
            capacity = depot_desc(d,2);
            dropstemp =  [ dropstemp; WaterDrop(dep,capacity,velocityInit, ...
                vel_params, soil_params) ];
        end
    end
    drops(:, 1, i) = dropstemp;
end

clear dropstemp;

% Best solution
best_sol = 0;
best_cost = 0;
temp_counter = 0;

%% Simulate water drops
for it = 1:iterations
    % reset calcualtion variables
    soilMat = globalSoilMat;
    for i = 1:pIter
        
        % reset droplets
        for dr = 1:length(drops)
            drops(dr, 1, i) = drops(dr, 1, i).reset(velocityInit);
        end
    end

    for s = 1:pIter % iterate to get parallel solutions and then will compare 
        % Build a full route set with multiple agents
        % Reset the parameters of each water drop on init

        customers = cust(:,1);
        demand = [cust(:,1) cust(:, 5)];
        while ~isempty(customers)

            for i = 1:length(drops)
                if isempty(customers)
                    break; % stop processing this loop since allocation complete
                end

                % Simulate water drop flow for one agent
                iwd = drops(i, 1, s);
                iwd = iwd.flow(soilMat,customers, demand);
                customers(customers == iwd.route(end)) = [];

                % Update water drop
                iwd = iwd.updateVelocity(soilMat);
                iwd = iwd.updateSoil(distMat);
                drops(i, 1, s) = iwd;

                % Update soil on edges
                dsoil = iwd.deltaSoil(distMat);
                n = length(iwd.route);
                soilMat(iwd.route(n - 1), iwd.route(n)) = ...
                    rho_o * soilMat(iwd.route(n - 1), iwd.route(n)) ...
                    - rho_n * dsoil;
                soilMat(iwd.route(n), iwd.route(n - 1)) = ...
                    rho_o * soilMat(iwd.route(n), iwd.route(n - 1)) ...
                    - rho_n * dsoil;
            end% end of looping over agents for allocation

        end % end of customer allocation
        
        % send agents home
        for i = 1:length(drops)
            drops(i, 1, s) = drops(i, 1, s).returnHome();
        end
    
    end % parallel solution construction
    
    parallelCost = zeros(pIter, 1);
    parallelBestCost = 0;
    
    % Calculate total solution cost (Euclidean distance; sum of routes)
    for s = 1:pIter
        dropcost = 0;
        for i = 1:length(drops)
            dropcost = drops(i, 1, s).calcRouteCost(distMat);
            parallelCost(s) = parallelCost(s) + dropcost;
        end
    end
    
    % Get index of the best solution
    bestIndex = 0;
    for s = 1:pIter
        if parallelCost(s) == min(parallelCost)
            bestIndex = s;
            parallelBestCost = parallelCost(s);
            break;
        end
    end
    
    % Stat updating
    stats(it, :) = [min(parallelCost) max(parallelCost)];
    
    % Update the best solution
    if (parallelBestCost < best_cost) || (best_cost == 0)
        best_cost = parallelBestCost
        best_sol = drops(:, :, bestIndex);
    end
    
    % Update the global soil
    probability = exp(-(parallelBestCost - best_cost)/temp);
    temp_counter = temp_counter + 1;
    if (temp_counter > tempIter)
        temp_counter = 0;
        temp = temp*tempDec; %reduce it
    end
    function [desc, depot_desc, cust, depot] = parseProblemSet(filename)
    % Summary:  Function for parsing Cordeau problem sets and returning 
    %           arrays containing the data.
    % 
    % desc:         Prob descr (type, # vehicles, # cust, # dep)
    % depot_desc:   Descr of depots (max dur of route, max vehicle load)
    % cust:         Customers (id, x,y, serv dur, demand, visit freq, 
    %                           # visit combs, list visit combs)
    % depot:        Depots (same as customers, but list is not present)
    
    f = fopen(filename); % Open for read
    
    % Description of problem set
    desc = str2double(strsplit(strtrim(fgets(f)), ' '));
    if length(desc) ~= 4
        error('File not correct format')
    end
    
    % Pull out variables
    desc_cell = num2cell(desc);
    [ptype m n t] = desc_cell{:};
    
    % Depot descriptions
    depot_desc = zeros(t,2);
    for i = 1:t
        depot_desc(i,:) = str2double(strsplit(strtrim(fgets(f)), ' '));
    end
    
    % Customers
    first_cust = str2double(strsplit(strtrim(fgets(f)), ' '));
    cust = zeros(n,length(first_cust));
    cust(1,:) = first_cust;
    for i = 2:n
        cust(i,:) = str2double(strsplit(strtrim(fgets(f)), ' '));
    end
    
    % Depots
    first_depot = str2double(strsplit(strtrim(fgets(f)), ' '));
    depot = zeros(t,length(first_depot));
    depot(1,:) = first_depot;
    for i = 2:t
        depot(i,:) = str2double(strsplit(strtrim(fgets(f)), ' '));
    end
    
    fclose(f); % Close it up
    return
end

四、运行结果

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

五、matlab版本及参考文献

1 matlab版本 2014a

2 参考文献 [1] 包子阳,余继周,杨杉.智能优化算法及其MATLAB实例(第2版)[M].电子工业出版社,2016. [2]张岩,吴水根.MATLAB优化算法源代码[M].清华大学出版社,2017.