2021数学建模国赛C题程序 跑通版 程序开源

原文链接:

2021数学建模国赛C题思路 生产企业原材料的订购与运输 第一版思路 思路开源 已修订 程序_您好啊数模君的博客-CSDN博客这里有百种算法出处整理,本题算法可从上面找取:给裸赛的家人们整理了百种算法出处https://mp.weixin.qq.com/s/OhWRCeep885MuyhMhvdiOw这道题是优化问题,先看看题目,以下为题目告知的条件和目标函数条件:48周;24周的原材料订购和转运计划,就需要达到48周的用料企业每周的产能为2.82万立方米,每立方米产品需消耗A类原材料0.6立方米,或B类原材料0.66立方米,或C类原材料0.72立方米;企业对供应商实际提供的原材料总是全部收购;https://blog.csdn.net/qq_39899679/article/details/120212554

程序文件版下载链接

链接:https://pan.baidu.com/s/13aSy2-hlkLa7Ps8wknYY1Q 
提取码:gap4 

第一问

clear
X1=xlsread('附件1 近5年402家供应商的相关数据.xlsx','企业的订货量(m³)');
X2=xlsread('附件1 近5年402家供应商的相关数据.xlsx','供应商的供货量(m³)');
[~,X3,~]=xlsread('附件1 近5年402家供应商的相关数据.xlsx','企业的订货量(m³)');
X3=string(X3);
X3=X3(2:end,2);
X3(find(X3=="A"))=1.3889;
X3(find(X3=="B"))=1.3774;
X3(find(X3=="C"))=1.3889;
%从供应角度看供应商的供应情况

Y(:,1)=1./std(X2')';%供应商供应的稳定性,对历史供应数据,做方差,负向指标,可以做个倒数
Y(:,2)=double(X3);%供应商材料经济效益,正向指标
Y(:,3)=sum(X2,2)./sum(X1,2);%历史供应量/历史订单量比,正向指标
%从企业角度看对供应商的认可情况
Y(:,4)=max(X1')';%供应商最大订单量,正向指标
Y(:,5)=mean(X1,2);%供应商平均订单量,正向指标
Y(:,6)=1./std(X1')';%供应商订单量的稳定性,对历史供应数据,做方差,负向指标,可以做个倒数
%还有其他指标可自加
Y=log(1+Y);%对指标ln函数映射,以减少数据本身差距,将评分重心转移至权重
Y(:,1)=log(100+Y(:,1));%对指标ln函数映射,以减少数据本身差距,将评分重心转移至权重
Y=mapminmax(Y',0.1,1)';
%% 熵权法
[n,m]=size(Y);
for i=1:n
    for j=1:m
        p(i,j)=Y(i,j)/sum(Y(:,j));
    end
end
%% 计算第 j 个指标的熵值 e(j)
k=1/log(n);
for j=1:m
    e(j)=-k*sum(p(:,j).*log(p(:,j)));
end
d=ones(1,m)-e; % 计算信息熵冗余度
w=d./sum(d); % 求权值 w
f=Y*w';
[f,paixu]=sort(f,'descend');
aa=paixu(1:50);
save aa aa

第二问

2021数学建模国赛C题程序 跑通版 程序开源_第1张图片

clear
%% 第一部分请自行修改为第一问的Top50供应商
%直接运行程序十有八九会报错,因为是随机选的50,请将aa矩阵更改为你们第一问的结果Top50的编号
[~,X1,~]=xlsread('附件1 近5年402家供应商的相关数据.xlsx','企业的订货量(m³)');
X1=string(X1);
X1=X1(2:end,2);
X2=xlsread('附件1 近5年402家供应商的相关数据.xlsx','供应商的供货量(m³)');
X3=xlsread('附件2 近5年8家转运商的相关数据.xlsx');
X3=mean(X3,2);%这里我直接取平均损耗了
XXX3=X3;
[X3,x3]=sort(X3);
X3=[X3,6000.*ones(8,1)];%加上最大转运量,方便调用
Y=zeros(size(X1,1),3);%记录单价、单位原料转化为产能的比例、供应商最大供应能力
Y(find(X1=="A"),1)=1.2;
Y(find(X1=="B"),1)=1.1;
Y(find(X1=="C"),1)=1;
Y(find(X1=="A"),2)=1/0.6;
Y(find(X1=="B"),2)=1/0.66;
Y(find(X1=="C"),2)=1/0.72;
Y(:,3)=max(X2')';%供应商最大供应能力,正向指标
%我这里随机选择50个,你们的话就用第一问结果
clear X2
load aa
X1=X1(aa,:);Y=Y(aa,:);

%% 寻优部分
num=100;%个体数
T0=100;%初始温度
q=0.95;%降温系数
Tmin=1;%最低温度
 
%初始化种群
x=[];
T=[];
F=[];
for i=1:num
 
    YL=48*28200; %总产能
    tt1=[];
    tt2=[];
    while YL>0 %直到满足产能为止
 
    if YL>56400
        z=56400;
    else
        z=YL;
    end
    t1=zeros(50,1);
    %这里是随机给个初始值,方便直接进入while循环
    k=[];k=randi([3,50]);%最多选择50个供应商
    a=[];a=randperm(50);a=a(1:k);%随机选取供应商
    a=sort(a);
    while sum(Y(a,2).*Y(a,3).*(1-max(X3(:,1))/100))48000
        d=round((c+(1-c).*rand(k,1)).*Y(a,3));%由于从不同供应商那里订购同一材料价格相同,实则最后就是ABC原料的订购比
    end
    t1(a,1)=d;%订单
    %转运,根据思路将A优先安排给损耗最小的转运商
    bb=[];[~,bb]=sort(X1(a));bb=a(bb);
    XX3=X3(:,2);
    t2=zeros(50,8);
    for j=1:length(bb)
        f=[];f=t1(bb(j));
        while f>0
            e=[];e=find(XX3>0);
            if XX3(e(1))>=f
                t2(bb(j),x3(e(1)))=f;
                XX3(e(1))=XX3(e(1))-f;
                f=0;
            else
                t2(bb(j),x3(e(1)))=XX3(e(1));
                f=f-XX3(e(1));
                XX3(e(1))=0;
            end
        end
    end
    YL=YL-sum(t2.*Y(:,2)*(1-XXX3./100)); %将一周的供应量换算为产能
    tt1=[tt1,t1];%格式按订购方案表格排列
    tt2=[tt2,t2];%格式按转运方案表格排列
    end
    %记录变量及目标函数
    x(i,1)=k;
    T{i,1}=tt1;
    T{i,2}=tt2;
    F(i,1)=k;%供应商数
    F(i,2)=2*sum(sum(tt2));%总费用
end
[TT,x,T]=ns2_1(x,T,F(:,1),F(:,2));
bestf=TT(1,:);
bestx=x(1,:);
bestT=T(1,:);
figure
plot(TT(:,1),TT(:,2),'b*')
 
while T0>Tmin
    %初始化种群
    xt=[];
    Tt=[];
    Ft=[];
    for i=1:num
        
        YL=48*28200;
        tt1=[];
        tt2=[];
        while YL>0
        if YL>56400
            z=56400;
        else
            z=YL;
        end
        t1=zeros(50,1);
        k=[];k=randi([3,50]);%这里是随机给个初始值,方便直接进入while循环
        a=[];a=randperm(50);a=a(1:k);
        a=sort(a);
        while sum(Y(a,2).*Y(a,3).*(1-max(X3(:,1))/100))48000
            d=round((c+(1-c).*rand(k,1)).*Y(a,3));%由于从不同供应商那里订购同一材料价格相同,实则最后就是ABC原料的订购比
        end
        t1(a,1)=d;%订单
        %转运
        bb=[];[~,bb]=sort(X1(a));bb=a(bb);
        XX3=X3(:,2);
        t2=zeros(50,8);
        for j=1:length(bb)
            f=[];f=t1(bb(j));
            while f>0
                e=[];e=find(XX3>0);
                if XX3(e(1))>=f
                    t2(bb(j),x3(e(1)))=f;
                    XX3(e(1))=XX3(e(1))-f;
                    f=0;
                else
                    t2(bb(j),x3(e(1)))=XX3(e(1));
                    f=f-XX3(e(1));
                    XX3(e(1))=0;
                end
            end
        end
        YL=YL-sum(t2.*Y(:,2)*(1-XXX3./100));
        tt1=[tt1,t1];
        tt2=[tt2,t2];
        end
        %记录变量及目标函数
        xt(i,1)=k;
        Tt{i,1}=tt1;
        Tt{i,2}=tt2;
        Ft(i,1)=k;%供应商数
        Ft(i,2)=2*sum(sum(tt2));
    end
    [TTt,xt,Tt]=ns2_1([x;xt],[T;Tt],[F(:,1);Ft(:,1)],[F(:,2);Ft(:,2)]);
    TTt=TTt(1:num,:);
    xt=xt(1:num,:);
    Tt=Tt(1:num,:);
    for kk=1:num
        delta=TTt(kk,1)*TTt(kk,2)-TT(kk,1)*TT(kk,2);
        if delta<0
            TT(kk,:)=TTt(kk,:);
            x(kk,:)=xt(kk,:);
            T(kk,:)=Tt(kk,:);
        else
            P=exp(-delta/T0);
            if P>rand
                TT(kk,:)=TTt(kk,:);
                x(kk,:)=xt(kk,:);
                T(kk,:)=Tt(kk,:);
            end
        end
    end
    bestf=TT(1,:);
    bestx=x(1,:);
    bestT=T(1,:);
    T0=T0*q;
end
hold on
plot(TT(:,1),TT(:,2),'r*')
legend('初始分布','最优分布')
title('模拟退火寻优-解分布')
xlabel('F1 供应商数')
ylabel('F2 总费用')
%% 最后的结果bestf为最优方案的目标函数,bestx为最少供应商数,bestT中有两个矩阵,均以按附件AB表格排好格式,直接复制过去即可

第三问

2021数学建模国赛C题程序 跑通版 程序开源_第2张图片

clear
%% 第一部分请自行修改为第一问的Top50供应商
%直接运行程序十有八九会报错,因为是随机选的50,请将aa矩阵更改为你们第一问的结果Top50的编号
[~,X1,~]=xlsread('附件1 近5年402家供应商的相关数据.xlsx','企业的订货量(m³)');
X1=string(X1);
X1=X1(2:end,2);
X2=xlsread('附件1 近5年402家供应商的相关数据.xlsx','供应商的供货量(m³)');
X3=xlsread('附件2 近5年8家转运商的相关数据.xlsx');
X3=mean(X3,2);%这里我直接取平均损耗了
XXX3=X3;
[X3,x3]=sort(X3);
X3=[X3,6000.*ones(8,1)];%加上最大转运量,方便调用
Y=zeros(size(X1,1),3);%记录单价、单位原料转化为产能的比例、供应商最大供应能力
Y(find(X1=="A"),1)=1.2;
Y(find(X1=="B"),1)=1.1;
Y(find(X1=="C"),1)=1;
Y(find(X1=="A"),2)=1/0.6;
Y(find(X1=="B"),2)=1/0.66;
Y(find(X1=="C"),2)=1/0.72;
Y(:,3)=max(X2')';%供应商最大供应能力,正向指标
%我这里随机选择50个,你们的话就用第一问结果
clear X2
load aa
X1=X1(aa,:);Y=Y(aa,:);

%% 寻优部分
num=300;%个体数
T0=100;%初始温度
q=0.95;%降温系数
Tmin=1;%最低温度

%初始化种群
x=[];
T=[];
F=[];
for i=1:num

    YL=48*28200; %总产能
    tt1=[];
    tt2=[];
    while YL>0 %直到满足产能为止

    if YL>56400
        z=56400;
    else
        z=YL;
    end
    t1=zeros(50,1);
    %这里是随机给个初始值,方便直接进入while循环
    k=[];k=randi([3,50]);%最多选择50个供应商
    a=[];a=randperm(50);a=a(1:k);%随机选取供应商
    a=sort(a);
    while sum(Y(a,2).*Y(a,3).*(1-max(X3(:,1))/100))48000
        d=round((c+(1-c).*rand(k,1)).*Y(a,3));%由于从不同供应商那里订购同一材料价格相同,实则最后就是ABC原料的订购比
    end
    t1(a,1)=d;%订单
    %转运,根据思路将A优先安排给损耗最小的转运商
    bb=[];[~,bb]=sort(X1(a));bb=a(bb);
    XX3=X3(:,2);
    t2=zeros(50,8);
    for j=1:length(bb)
        f=[];f=t1(bb(j));
        while f>0
            e=[];e=find(XX3>0);
            if XX3(e(1))>=f
                t2(bb(j),x3(e(1)))=f;
                XX3(e(1))=XX3(e(1))-f;
                f=0;
            else
                t2(bb(j),x3(e(1)))=XX3(e(1));
                f=f-XX3(e(1));
                XX3(e(1))=0;
            end
        end
    end
    YL=YL-sum(t2.*Y(:,2)*(1-XXX3./100)); %将一周的供应量换算为产能
    tt1=[tt1,t1];%格式按订购方案表格排列
    tt2=[tt2,t2];%格式按转运方案表格排列
    end
    %记录变量及目标函数
    x(i,1)=k;
    T{i,1}=tt1;
    T{i,2}=tt2;
    F(i,1)=k;%供应商数
    F(i,2)=2*sum(sum(tt2));%总费用
    F(i,3)=sum(sum(tt1(find(X1=="A"),:)));%A材料
    F(i,4)=sum(sum(tt1(find(X1=="C"),:)));%C材料
end
[TT,x,T]=ns2_2(x,T,F(:,1),F(:,2),F(:,3),F(:,4));
bestf=TT(1,:);
bestx=x(1,:);
bestT=T(1,:);
figure
plot3(TT(:,1),TT(:,2),TT(:,3),'b*')

while T0>Tmin
    %初始化种群
    xt=[];
    Tt=[];
    Ft=[];
    for i=1:num
        
        YL=48*28200;
        tt1=[];
        tt2=[];
        while YL>0
        if YL>56400
            z=56400;
        else
            z=YL;
        end
        t1=zeros(50,1);
        k=[];k=randi([3,50]);
        a=[];a=randperm(50);a=a(1:k);
        a=sort(a);%这里是随机给个初始值,方便直接进入while循环
        while sum(Y(a,2).*Y(a,3).*(1-max(X3(:,1))/100))48000
            d=round((c+(1-c).*rand(k,1)).*Y(a,3));%由于从不同供应商那里订购同一材料价格相同,实则最后就是ABC原料的订购比
        end
        t1(a,1)=d;%订单
        %转运
        bb=[];[~,bb]=sort(X1(a));bb=a(bb);
        XX3=X3(:,2);
        t2=zeros(50,8);
        for j=1:length(bb)
            f=[];f=t1(bb(j));
            while f>0
                e=[];e=find(XX3>0);
                if XX3(e(1))>=f
                    t2(bb(j),x3(e(1)))=f;
                    XX3(e(1))=XX3(e(1))-f;
                    f=0;
                else
                    t2(bb(j),x3(e(1)))=XX3(e(1));
                    f=f-XX3(e(1));
                    XX3(e(1))=0;
                end
            end
        end
        YL=YL-sum(t2.*Y(:,2)*(1-XXX3./100));
        tt1=[tt1,t1];
        tt2=[tt2,t2];
        end
        %记录变量及目标函数
        xt(i,1)=k;
        Tt{i,1}=tt1;
        Tt{i,2}=tt2;
        Ft(i,1)=k;%供应商数
        Ft(i,2)=2*sum(sum(tt2));%总费用
        Ft(i,3)=sum(sum(tt1(find(X1=="A"),:)));%A材料
        Ft(i,4)=sum(sum(tt1(find(X1=="C"),:)));%C材料
    end
    [TTt,xt,Tt]=ns2_2([x;xt],[T;Tt],[F(:,1);Ft(:,1)],[F(:,2);Ft(:,2)],[F(:,3);Ft(:,3)],[F(:,4);Ft(:,4)]);
    TTt=TTt(1:num,:);
    xt=xt(1:num,:);
    Tt=Tt(1:num,:);
    for kk=1:num
        delta=TTt(kk,3)/(TTt(kk,1)*TTt(kk,2)*TTt(kk,4))-TT(kk,3)/(TT(kk,1)*TT(kk,2)*TT(kk,4));
        if delta<0
            TT(kk,:)=TTt(kk,:);
            x(kk,:)=xt(kk,:);
            T(kk,:)=Tt(kk,:);
        else
            P=exp(-delta/T0);
            if P>rand
                TT(kk,:)=TTt(kk,:);
                x(kk,:)=xt(kk,:);
                T(kk,:)=Tt(kk,:);
            end
        end
    end
    bestf=TT(1,:);
    bestx=x(1,:);
    bestT=T(1,:);
    T0=T0*q;
end
hold on
plot3(TT(:,1),TT(:,2),TT(:,3),'r*')
legend('初始分布','最优分布')
title('模拟退火寻优-解分布')
xlabel('F1 供应商数')
ylabel('F2 总费用')
zlabel('F3 A材料供应数')
%% 最后的结果bestf为最优方案的目标函数,bestx为最少供应商数,bestT中有两个矩阵,均以按附件AB表格排好格式,直接复制过去即可

其他自定义函数,需创建调用

function [TT,chrom,cchrom]=ns2(x,T,F1,F2)
% 快速非支配排序
a = 0;
T1 = [];
T2 = [];
chrom=x;
cchrom=T;
chrom1 = [];
chrom2 = [];
cchrom1 = [];
cchrom2 = [];
while a == 0 %根据被支配数进行分级和排序
    M = [];
    for i = 1:length(F1)
        M(i,1) = length(find(F1
    end
    b1 = [];
    b2 = [];
    [b1,b2] = sort(M); %b1返回从小到大排序,b2返回原始序号
    if  length(chrom)>0 && b1(1) == 0   %无被支配数进入一级用T1矩阵保存
        T1 = [T1;F1(b2(1)),F2(b2(1))];
        chrom1 = [chrom1;chrom(b2(1),:)];
        cchrom1 = [cchrom1;cchrom(b2(1),:)];
        F1(b2(1)) = [];
        F2(b2(1)) = [];
        chrom(b2(1),:) = [];
        cchrom(b2(1),:) = [];
    else  %有被支配数进入二级用T2矩阵保存
        a = 1;
        T2 = [F1,F2];
        chrom2 = chrom;
        cchrom2 = cchrom;
    end
end
T2 = T2(b2,:);
chrom2 = chrom2(b2,:);
cchrom2 = cchrom2(b2,:);
if size(T1,1) > 2  %T1矩阵不用进行拥挤度调整排序,直接对T2进行排序调整即可
    y = yongji(T1);%拥挤度
    for i = 2:size(T1,1)
            if y(i-1) > y(i)
                T1(i-1:1:i,:) = T1(i:-1:i-1,:); %根据拥挤度调整排序,如果后者优于前者则反转顺序
                chrom1(i-1:1:i,:) = chrom1(i:-1:i-1,:);
                cchrom1(i-1:1:i,:) = cchrom1(i:-1:i-1,:);
            end
    end
end

if length(T2) > 0  %T1矩阵不用进行拥挤度调整排序,直接对T2进行排序调整即可
    y = yongji(T2);%拥挤度
    for i = 2:size(T2,1)
        if b1(i) == b1(i-1)
            if y(i-1) > y(i)
                T2(i-1:1:i,:) = T2(i:-1:i-1,:); %根据拥挤度调整排序,如果后者优于前者则反转顺序
                chrom2(i-1:1:i,:) = chrom2(i:-1:i-1,:);
                cchrom2(i-1:1:i,:) = cchrom2(i:-1:i-1,:);
            end
        end
    end
end
%排序重组
TT = [T1;T2];
chrom = [chrom1;chrom2];
cchrom = [cchrom1;cchrom2];
function [TT,chrom,cchrom]=ns2(x,T,F1,F2,F3,F4)
% 快速非支配排序
a = 0;
T1 = [];
T2 = [];
chrom=x;
cchrom=T;
chrom1 = [];
chrom2 = [];
cchrom1 = [];
cchrom2 = [];
while a == 0 %根据被支配数进行分级和排序
    M = [];
    for i = 1:length(F1)
        M(i,1) = length(find(F1F3(i,1)))+length(find(F4
    end
    b1 = [];
    b2 = [];
    [b1,b2] = sort(M); %b1返回从小到大排序,b2返回原始序号
    if  length(chrom)>0 && b1(1) == 0   %无被支配数进入一级用T1矩阵保存
        T1 = [T1;F1(b2(1)),F2(b2(1)),F3(b2(1)),F4(b2(1))];
        chrom1 = [chrom1;chrom(b2(1),:)];
        cchrom1 = [cchrom1;cchrom(b2(1),:)];
        F1(b2(1)) = [];
        F2(b2(1)) = [];
        F3(b2(1)) = [];
        F4(b2(1)) = [];
        chrom(b2(1),:) = [];
        cchrom(b2(1),:) = [];
    else  %有被支配数进入二级用T2矩阵保存
        a = 1;
        T2 = [F1,F2,F3,F4];
        chrom2 = chrom;
        cchrom2 = cchrom;
    end
end
T2 = T2(b2,:);
chrom2 = chrom2(b2,:);
cchrom2 = cchrom2(b2,:);
if size(T1,1) > 2  %T1矩阵不用进行拥挤度调整排序,直接对T2进行排序调整即可
    y = yongji(T1);%拥挤度
    for i = 2:size(T1,1)
            if y(i-1) > y(i)
                T1(i-1:1:i,:) = T1(i:-1:i-1,:); %根据拥挤度调整排序,如果后者优于前者则反转顺序
                chrom1(i-1:1:i,:) = chrom1(i:-1:i-1,:);
                cchrom1(i-1:1:i,:) = cchrom1(i:-1:i-1,:);
            end
    end
end

if length(T2) > 0  %T1矩阵不用进行拥挤度调整排序,直接对T2进行排序调整即可
    y = yongji(T2);%拥挤度
    for i = 2:size(T2,1)
        if b1(i) == b1(i-1)
            if y(i-1) > y(i)
                T2(i-1:1:i,:) = T2(i:-1:i-1,:); %根据拥挤度调整排序,如果后者优于前者则反转顺序
                chrom2(i-1:1:i,:) = chrom2(i:-1:i-1,:);
                cchrom2(i-1:1:i,:) = cchrom2(i:-1:i-1,:);
            end
        end
    end
end
%排序重组
TT = [T1;T2];
chrom = [chrom1;chrom2];
cchrom = [cchrom1;cchrom2];

function y=yongji(H)
%计算拥挤度
y1=H(:,1);
y2=H(:,2);

[yy1,a1]=sort(y1);
[yy2,a2]=sort(y2);

L=[];
L=[1 1];
for i=2:length(yy1)-1
    L=[L;(yy1(i+1,1)-yy1(i-1,1))/(max(yy1)-min(yy1)),(yy2(i+1,1)-yy2(i-1,1))/(max(yy2)-min(yy2))];
end
L=[L;1 1];
L=[L(a1,1),L(a2,2)];
y=sum(L,2);
end

你可能感兴趣的:(数学建模,2021数学建模国赛,2021数学建模国赛C题程序,2021数学建模国赛C题思路)