MATLAB+YALMIP+CPLEX求解小规模CVRP问题

Shuanglin Li
2021-12-06 / 0 评论 / 1,030 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年01月14日,已超过685天没有更新,若内容或图片失效,请留言反馈。

本文摘抄自公众号:优化算法交流地
MATLAB调用CPLEX的方法来自:http://blog.sina.com.cn/s/blog_b041fdcb0102ydsq.htm。该篇博文中附有相应的安装文件,除了需要安装CPLEX以外,还需要安装YALMIP建模软件包,这是一个在MATLAB上进行数学建模超级方便的工具包,有了YALMIP可以大大降低建模的难度。具体如何操作?该怎么样进行联合开发呢?本文以CVRP问题为例进行展示。

值得注意的是:只有按照步骤安装好YALMIP和CPLEX,并且在MATLAB中配置好相应的路径后,才能正确运行程序。

因此,本文以求解CVRP标准算例问题为例,来演示MATLAB+YALMIP+CPLEX的求解效果,具体代码如下。

clear
clc
vNum=5;  %车数量
cusNum=13; %总节点数量
C=6; %单车容量
demands=[0,1.2,1.7,1.5,1.4,1.7,1.4,1.2,1.9,1.8,1.6,1.7,1.1]; %需求量
x=[81.5,87,75,85,89,77,76,87,73,77,73,91,92];
y=[41.5,37,53,52,41,58,45,53,38,38,31,47,44];
axis=[x' y']; %城市坐标
% Dij = zeros(cusNum);%计算城市之间的距离
D=pdist(axis);
Dij=squareform(D); %距离矩阵,满足三角关系,暂用距离表示花费c[i][j]=dist[i][j]
%% 决策变量
Xijk=binvar(cusNum,cusNum,vNum,'full');%i、j节点之间是否由第k辆车进行配送
Yik=binvar(cusNum,vNum,'full'); %k辆车是否经过i节点
Uik=sdpvar(cusNum,vNum,'full'); %Uik表示车辆k在访问i节点后,车子的剩余容量
%% 目标函数
obj=0;
for i=1:cusNum
    for j=1:cusNum
        for k=1:vNum
            obj=obj+Dij(i,j)*Xijk(i,j,k);
        end
    end
end
f=obj;
%% 约束条件
F=[];
for i=2:cusNum
    F=[F;sum(Yik(i,:))==1]; %每个需求点i都会被一辆车经过
end

for i=1
    F=[F;sum(Yik(i,:))<=vNum];%配送中心则会被所有用到的小车经过
end

for k=1:vNum
    F=[F;sum(demands(:).*Yik(:,k))<=C]; %每个回路上的需求量之和小于车的容量
end

for i=1:cusNum
    for j=1:cusNum
        for k=1:vNum
            if i==j
                F=[F;Xijk(i,j,k)==0]; %不可能存在从该点出发又回到该点的情况
            end
        end
    end
end

for i=1:cusNum
    for k=1:vNum
        F=[F;sum(Xijk(i,:,k))==sum(Xijk(:,i,k))];%流量平衡
    end
end

% for j=2:cusNum
for j=1:cusNum
    for k=1:vNum
        F=[F;sum(Xijk(:,j,k))==Yik(j,k)];%Xijk和Yik的关系
    end
end

for i=1:cusNum
    for k=1:vNum
        F=[F;sum(Xijk(i,:,k))==Yik(i,k)];%Xijk和Yik的关系
    end
end

for i=2:cusNum
    for j=2:cusNum
        for k=1:vNum
            if i~=j
                if demands(i)+demands(j)<=C
                    F=[F;Uik(i,k)-Uik(j,k)+C*Xijk(i,j,k)<=C-demands(i)];%Xijk和Ui
                end
            end
        end
    end
end

for i=2:cusNum
    for k=1:vNum
        F=[F;Uik(i,k)<=C];
        F=[F;Uik(i,k)>=demands(i)];
    end
end
%% 求解
ops = sdpsettings( 'solver','cplex');
sol=solvesdp(F,f,ops);
f=double(f);
Xijk=double(Xijk);
Yik=double(Yik);
Uik=double(Uik);
%% 画图
plot(axis(2:cusNum,1),axis(2:cusNum,2),'ro');hold on;
plot(axis(1,1),axis(1,2),'pm');hold on;
for i=1:cusNum
    for j=1:cusNum
        for k=1:vNum
            if Xijk(i,j,k)==1
                plot([axis(i,1),axis(j,1)],[axis(i,2),axis(j,2)],'-');
            end
        end
    end
end
for k=1:vNum
    [a,b]=find(Xijk(:,:,k));
    sqe=[a,b];
    sqe1=zeros(1,0);
    sqe1(1)=1;
    [a,b]=find(sqe(:,1)==1);
    for i=2:length(sqe)+1
        [a,b]=find(sqe(:,1)==sqe1(i-1));
        sqe1(i)=sqe(a,b+1);
    end
    disp(['车辆',num2str(k),'的路径如下:']);
    disp(sqe1)
end

routing.jpg
routing_pic.jpg

本文共 366 个字数,平均阅读时长 ≈ 1分钟
1

打赏

海报

正在生成.....

评论 (0)

取消