基于nsga2的多目标柔性车间调度问题matlab[通俗易懂]

基于nsga2的多目标柔性车间调度问题matlab[通俗易懂]主函数:%主函数functionnsga2_schedulingclearall;clc;pop=200;%种群数量gen=10;%迭代次数pop_f=100;%父代种群数量data_mac;%载入车间设备信息data_pro;%载入待加工工件信息pro_matrix=[];%包含工序及目标函数值的决策矩阵mac_matrix=[];%包含设备染色体信息的决策矩阵fori=1:pop_

大家好,又见面了,我是你们的朋友全栈君。

主函数:

%主函数
function nsga2_scheduling
    clear all;
    clc; 
    pop = 200; %种群数量
    gen = 10; %迭代次数
    pop_f=100;%父代种群数量
    data_mac;%载入车间设备信息
    data_pro;%载入待加工工件信息
    pro_matrix=[];%包含工序及目标函数值的决策矩阵
    mac_matrix=[];%包含设备染色体信息的决策矩阵
    for i=1:pop_f%生成初始种群
        [P,M,N]=initPop(J);  
        [part_t,mac_t]=decode(J,P,M,N);
        c_time=cal_comp_time(part_t);  %最大完工时间
        d_time=cal_def_time(J,part_t);   %总延期时长
        t_load=cal_equ_load(part_t);     %设备总负荷
        t_cons=cal_ene_consu(Mac,mac_t,P,M,c_time);  %调度方案的总耗能
        pro_matrix(i,:)=[P,c_time,d_time,t_load,t_cons];
        mac_matrix(i,:)=M;
    end 
   for i = 1 : gen
        pool = round(pop/2);%round() 四舍五入取整 交配池大小
        tour = 2;%竞标赛  参赛选手个数
        [p_matrix,m_matrix]= non_domination_sort_mod(pro_matrix,mac_matrix);%种群进行非支配快速排序和拥挤度计算 
        clear pro_matrix;
        clear mac_matrix;
        [p_parent_chromosome,m_parent_chromosome] = tournament_selection(p_matrix,m_matrix,pool,tour);%竞标赛选择适合繁殖的父代
        %交叉变异生成子代种群
        [p_child_matrix,m_child_matrix]=genetic_operator(J,p_parent_chromosome,m_parent_chromosome);
        %根据父类和子类总种群,进行非支配快速排序,选取出下一代的父代种群
        for j=1:size(p_child_matrix,1)
            P=p_child_matrix(j,:);
            M=m_child_matrix(j,:);
            N=machine_index(J,P,M);
            [part_t,mac_t]=decode(J,P,M,N);
            c_time=cal_comp_time(part_t);
            d_time=cal_def_time(J,part_t);
            t_load=cal_equ_load(part_t);
            t_cons=cal_ene_consu(Mac,mac_t,P,M,c_time);
            pro_matrix(j,:)=[P,c_time,d_time,t_load,t_cons];
            mac_matrix(j,:)=M;
        end
        n_p_m=size(pro_matrix,1);   
        pro_matrix(n_p_m+1:n_p_m+10,:)=p_matrix(1:10,1:size(pro_matrix,2));%保留精英染色体到子代种群中
        mac_matrix(n_p_m+1:n_p_m+10,:)=m_matrix(1:10,:);
   end
   [p_matrix,m_matrix]= non_domination_sort_mod(pro_matrix,mac_matrix);
   num_of_level_1=length(find(p_matrix(:,size(p_matrix,2)-1)==1));
   target_p_matrix=p_matrix(1:num_of_level_1,:);
   target_m_matrix=m_matrix(1:num_of_level_1,:);
   best_p=target_p_matrix(1,:);%选取第一个作为最优解,可根据需求,选择AHP和熵权法或模糊决策法,选出最优解
   best_m=target_m_matrix(1,:);
   P=best_p(1:length(best_p)-6);
   M=best_m;
   N=machine_index(J,P,M);
   [~,mac_t]=decode(J,P,M,N);
   ganttChart1(J,best_p,M,mac_t);
end


导入工件信息data_pro.m

%初始调度数据
%J(i).a  表示第i个工件的属性, 第一个参数为工序数  第二个参数表示释放时期 第三个参数表示交货期
%J(i).m  表示各道工序所对应的加工设备
%J(i).t  表示各道工序所对应的加工设备所需的加工时间
J(1).num_mac=8;
J(1).a=[3,5,60];
J(1).m={[4,6,7];[1,5,6,8];[2,4,7]};
J(1).t={[12,10,9];[17,17,10,15];[24,11,10]};
%%%%%%%
J(2).a=[6,17,100];
J(2).m={[3,4,5,6,8];[1,2,5,6];[4,6,7];[5,7];[1,2,4,5,7];[2,4,5,6]};
J(2).t={[11,10,21,14,17];[8,12,19,11];[15,21,25];[18,9];[12,15,14,9,10];[9,7,10,8]};
%%%%
J(3).a=[4,16,120];
J(3).m={[2,7];[2,3,4,6];[3,4,5,8];[1,3,5,6,7]};
J(3).t={[14,17];[23,23,17,18];[20,9,22,21];[7,10,8,11,9]};
%%%%%
J(4).a=[3,4,80];
J(4).m={[2,6,7];[4,7];[2,3,4,7,8]};
J(4).t={[18,17,18];[10,12];[8,11,8,9,20]};
%%%%%%%
J(5).a=[2,17,60];
J(5).m={[3,4,5];[4,8]};
J(5).t={[24,10,16];[18,19]};
%%%%%%
J(6).a=[3,10,80];
J(6).m={[2,7];[3,7];[1,3,4,5,8]};
J(6).t={[20,22];[18,19];[19,17,16,16,18]};
%%%%%%
J(7).a=[4,12,inf];
J(7).m={[3,5,6];[1,6,7];[6,7];[6,8]};
J(7).t={[16,17,16];[22,20,22];[18,23];[10,24]};
%%%%%%%%%
J(8).a=[3,0,100];
J(8).m={[1,7,8];[1,2];[1,2,6,8]};
J(8).t={[11,21,21];[25,11];[24,18,25,20]};

导入设备信息data_mac.m

%车间设备信息
%%%%%%%车间属性 Mac(i).a的第一个参数为车间固定功率  第二个参数为零件传输功率
Mac(1).a=[35,2];
%%%%%% Mac(i).e的第一个参数表示设备i的加工功率,第二个参数为固定功率
Mac(1).e=[20,3.45];
Mac(2).e=[15,2.82];
Mac(3).e=[6,0.84];
Mac(4).e=[12,1.58];
Mac(5).e=[10,1.41];
Mac(6).e=[5.5,0.55];
Mac(7).e=[7.5,1.02];
Mac(8).e=[10,1.80];

四个目标函数,均为最小化:

%计算最大完工时间 part_t为调度方案所对应的加工时间信息
function max_comp_time = cal_comp_time(part_t)
    max_time=[];%记录各工件的最大完工时间
    for i=1:size(part_t,2)
        m=size(part_t{i},1);
        max_time=[max_time,part_t{i}(m,2)];
    end
    max_comp_time=max(max_time);
end
%计算总延期时长
function  total_def_time= cal_def_time(J,part_t)
    total_def_time=0;
    for i=1:size(J,2)
        m=size(part_t{i},1);  %第i个工件的工序数
        comp_time=part_t{i}(m,2);  %第i个工件的完工时间
        total_def_time=total_def_time+max(comp_time-J(i).a(3),0);
    end
end


%计算调度方案的总能耗 Time为最大完工时间
function total_energy_cons= cal_ene_consu(Mac,mac_t,P,M,Time)
    total_energy_cons=0;
    i_cons=0;%空转能耗
    m_cons=0;%加工能耗
    t_cons=0;%转移能耗
    j_cons=0;%车间固有能耗
    j_cons=Time*Mac(1).a(1)/60;
    for i=1:size(mac_t,2)          
         for j=1:size(mac_t{i},1)
             %计算空转能耗
             if j>1
                i_cons=i_cons+Mac(i).e(2)*(mac_t{i}(j,1)-mac_t{i}(j-1,2))/60;
             else
                 i_cons=i_cons+Mac(i).e(2)*(mac_t{i}(j,1))/60;
             end
             %计算加工能耗
             m_cons=m_cons+Mac(i).e(1)*(mac_t{i}(j,2)-mac_t{i}(j,1))/60;
         end
         %计算转移能耗
         m_index=find(M==i);
         if size(m_index,2)>0
            if size(m_index,2)>1
                t_cons=t_cons+Mac(1).a(2);
               for j=1:size(m_index,2)-1
         %判断设备的相邻加工工序是否为该零件的相邻工序
                    if P(m_index(j))~=P(m_index(j+1))
                        t_cons=t_cons+Mac(1).a(2);
                     else 
                        p_var=P(m_index(j));%加工工件号
                        p_index=find(P==p_var);
                        k=find(p_index==m_index(j));
                        if p_index(k+1)~=m_index(j+1)
                            t_cons=t_cons+Mac(1).a(2);
                        end
                    end
               end
            else
                t_cons=t_cons+Mac(1).a(2);
            end
         end   
    end
    total_energy_cons=m_cons+i_cons+t_cons+j_cons;
end


%计算设备总负荷
function total_load = cal_equ_load(part_t)
    total_load=0;
    for i=1:size(part_t,2)
        for j=1:size(part_t{i},1)
            total_load=total_load+part_t{i}(j,2)-part_t{i}(j,1);
        end
    end
end

产生初始种群

%初始调度种群生成 J工件相关信息,p为基于工序的编码 
% m为对应的机器编码  n为所选设备在对应可选设备集中的序列号
function [p,m,n]= initPop(J)
    p=[];%基于工序的编码
%     m(1:size(p,2))=0;%基于机器编码的染色体
    m=[];
    n=[];
    for i=1:size(J,2)%参与调度的工件数
        for j=1:J(i).a(1)%该工序的工序
            p(size(p,2)+1)=i;
        end
    end
    r=randperm(size(p,2));
    p=p(1,r);%生产有效的随机的基于工序编码
%-------------基于工序编码生成对应的基于机器的编码-------------%
    for i=1:size(J,2)
        f{i}=find(p==i);%找出工件i在工序染色体中所对应的序号
        for j=1:J(i).a(1)   %第i个工件的工序数
            k=f{i}(j);
            s=size(J(i).m{j},2);  %第i个工件第j道工序的可选机器数
            num=randperm(s,1);   %从1—s中随机选择一个数
            n(k)=num;   
            m(k)=J(i).m{j}(num);
%             m(f{i}(j))=J(i).m{j}(randperm(size(J(i).m{j},2),1));
        end
    end
end

计算工件的设备的加工时间信息

%贪婪解码算法  J为参与调度的工件的所有信息  P为调度方案的基于工序编码的染色体 
% M为调度方案的基于机器编码的染色体  N为所选设备在对应可选设备集中的序列号
%part_t为对应工件各工序加工时间信息  mac_t为对应设备各工序加工时间信息
function [part_t,mac_t,span]= decode(J,P,M,N)
    part_t=cell(size(J,2));%加工零件的加工时间
    mac_t=cell(J(1).num_mac);%对应设备加工时间
    [~,total_n]=size(P);%total_n为总工序数
    part_n=size(J,2);
    k_part=zeros(1,part_n);%记录当前解码过程中工件的工序号(一行工件数的全0数组)
    k_mac=zeros(1,J(1).num_mac);%记录当前解码过程中该到工序在该设备中待加工序号
    t_span=cell(1);%记录该所有设备加工间隙
    tete=zeros(J(1).num_mac,300);
%     k_N=zeros(1,part_n);
    for i=1:total_n
        p_var=P(i);%染色体中第i个基因所对应的工件
        m_var=M(i);%染色体中第i个基因所对应的加工设备
        n_var=N(i);%该基因所选设备在可选设备集中的序号
        k_part(p_var)=k_part(p_var)+1;  %在加工工件0变1、2、3
        k_mac(m_var)=k_mac(m_var)+1;    %在使用机器0变1、2、3
%       m_span{m_var}  %第m_var台设备当前所存在的加工间隙
        pro_time=J(p_var).t{k_part(p_var)}(n_var);%该道工序所需加工时间
        %确定该工序开始的加工时间
        %基于工件的约束
        if k_part(p_var)>1
            start_t_p=part_t{p_var}(k_part(p_var)-1,2);
        else
            start_t_p=0;
        end
        %基于加工设备的约束
        if k_mac(m_var)>1
            start_t_m=max(mac_t{m_var}(:,2));
        else
            start_t_m=0;
        end
        %判断最终约束
        if start_t_p>=start_t_m
            start_t=start_t_p;
            %不发生前插时的,设备间隙矩阵
            if k_mac(m_var)>1
                t_span{m_var}(k_mac(m_var),:)=[mac_t{m_var}(k_mac(m_var)-1,2),start_t];%第m_var个元胞
            else
                t_span{m_var}(k_mac(m_var),:)=[0,start_t];
            end
        else 
              span=t_span{m_var}(:,2)-t_span{m_var}(:,1);%元胞数组对应机器集的2列-1列
            req_span=intersect(find(span>=pro_time),find(t_span{m_var}(:,2)>=start_t_p+pro_time)); %可以进行插入的位置
              if size(req_span,1)>=1&&size(req_span,2)
                var=req_span(1); 
                midd=max(start_t_p,t_span{m_var}(var,1));
                if (tete(m_var,midd+1:midd+1+pro_time)==0)%判断机器加工状态是否
                   start_t=midd;
                   t_span{m_var}(k_mac(m_var),:)=[start_t+pro_time,t_span{m_var}(var,2)];%更新插入产生的新间隙
                   t_span{m_var}(var,2)=start_t;%更新插入后对已有间隙的影响
                   t_span{m_var}=sortrows(t_span{m_var},1);
                else
                     start_t=start_t_m;
                end
             else
                start_t=start_t_m;
                t_span{m_var}(k_mac(m_var),:)=[start_t,start_t];
             end
        end  
        stop_t=start_t+pro_time;
        tete(m_var,start_t+1:stop_t+1)=1;%更新机器上加工状态为1
        part_t{p_var}(k_part(p_var),:)=[start_t,stop_t];
        mac_t{m_var}(k_mac(m_var),:)=[start_t,stop_t];
       % mac_t{m_var}=sortrows(mac_t{m_var},2);%更新机器时间,以机器完工时间升序排列
    end
end



基于P,M生成N

%基于P,M,生成N
function N = machine_index(J,P,M)
    N=zeros(1,size(P,2));
    for i=1:size(J,2)
        pi_index=find(P==i);
        for j=1:size(pi_index,2)
             var=find(J(i).m{j}==M(pi_index(j)));
             N(pi_index(j))=var;
        end
    end
end

基于pareto的快速非支配排序

%% 对初始种群开始排序 快速非支配排序
% 使用非支配排序对种群进行排序。该函数返回每个个体对应的排序值和拥挤距离,是一个两列的矩阵。  
% 并将排序值和拥挤距离添加到染色体矩阵中 
%x:决策矩阵  M:优化目标数量 V:决策变量个数
function [p_matrix,m_matrix] = non_domination_sort_mod(pro_matrix,mac_matrix)
    [N, ~] = size(pro_matrix);% N为矩阵x的行数,也是种群的数量
    M=4;%优化目标数量
    V=size(pro_matrix,2)-M;%决策变量个数
    front = 1;
    F(front).f = [];%记录paret  o解集等级为front级的个体集合
    individual = [];%用于存放被某个个体支配的个体集合

    for i = 1 : N
        individual(i).n = 0;%n是个体i被支配的个体数量
        individual(i).p = [];%p是被个体i支配的个体集合
        for j = 1 : N
            dom_less = 0;
            dom_equal = 0;
            dom_more = 0;
            for k = 1 : M        %判断个体i和个体j的支配关系
                if (pro_matrix(i,V + k) < pro_matrix(j,V + k))  
                    dom_less = dom_less + 1;
                elseif (pro_matrix(i,V + k) == pro_matrix(j,V + k))
                    dom_equal = dom_equal + 1;
                else
                    dom_more = dom_more + 1;
                end
            end
            if dom_less == 0 && dom_equal ~= M % 说明i受j支配,相应的n加1
                individual(i).n = individual(i).n + 1;
            elseif dom_more == 0 && dom_equal ~= M % 说明i支配j,把j加入i的支配合集中
                individual(i).p = [individual(i).p j];
            end
        end   
        if individual(i).n == 0 %个体i非支配等级排序最高,属于当前最优解集,相应的染色体中携带代表排序数的信息
            pro_matrix(i,M + V + 1) = 1;
            F(front).f = [F(front).f i];%等级为1的非支配解集
        end
    end
%上面的代码是为了找出等级最高的非支配解集
%下面的代码是为了给其他个体进行分级
    while ~isempty(F(front).f)
       Q = []; %存放下一个front集合
       for i = 1 : length(F(front).f)%循环当前支配解集中的个体
           if ~isempty(individual(F(front).f(i)).p)%个体i有自己所支配的解集
                for j = 1 : length(individual(F(front).f(i)).p)%循环个体i所支配解集中的个体
                    individual(individual(F(front).f(i)).p(j)).n = ...%...表示的是与下一行代码是相连的,这里表示个体j的被支配个数减1
                        individual(individual(F(front).f(i)).p(j)).n - 1;
                     if individual(individual(F(front).f(i)).p(j)).n == 0% 如果q是非支配解集,则放入集合Q中
                        pro_matrix(individual(F(front).f(i)).p(j),M + V + 1) = ...%个体染色体中加入分级信息
                            front + 1;
                        Q = [Q individual(F(front).f(i)).p(j)];
                    end
                end
           end
       end
       front =  front + 1;
       F(front).f = Q;
    end

    [~,index_of_fronts] = sort(pro_matrix(:,M + V + 1));%对个体的代表排序等级的列向量进行升序排序 temp为排序完成的列 index_of_fronts表示排序后的值对应原来的索引
    for i = 1 : length(index_of_fronts)
        sorted_based_on_front(i,:) = pro_matrix(index_of_fronts(i),:);%sorted_based_on_front中存放的是x矩阵按照排序等级升序排序后的矩阵
        m_matrix(i,:)=mac_matrix(index_of_fronts(i),:);
    end
    current_index = 0;

    %% Crowding distance 计算每个个体的拥挤度

    for front = 1:(length(F) - 1)%这里减1是因为代码55行这里,F的最后一个元素为空,这样才能跳出循环。所以一共有length-1个排序等级
        distance = 0;
        y = [];
        previous_index = current_index + 1;
        for i = 1 : length(F(front).f)
            y(i,:) = sorted_based_on_front(current_index + i,:);%y中存放的是排序等级为front的集合矩阵
%           z(i,:) = mac_sorted_based(current_index+i,:);%z中存放是等级为front的对应的加工设备集合矩阵
        end
        current_index = current_index + i;%current_index =i
        sorted_based_on_objective = [];%存放基于拥挤距离排序的矩阵
        for i = 1 : M
            [sorted_based_on_objective, index_of_objectives] = ...
                sort(y(:,V + i));%按照目标函数值排序
            sorted_based_on_objective = [];
            for j = 1 : length(index_of_objectives)
                sorted_based_on_objective(j,:) = y(index_of_objectives(j),:);% sorted_based_on_objective存放按照目标函数值排序后的x矩阵
%                 mac_sorted_matrix(j,:)=z(index_of_objectives(j),:)
            end
            f_max = ...
                sorted_based_on_objective(length(index_of_objectives), V + i);%fmax为目标函数最大值 fmin为目标函数最小值
            f_min = sorted_based_on_objective(1, V + i);
            y(index_of_objectives(length(index_of_objectives)),M + V + 1 + i)...%对排序后的第一个个体和最后一个个体的距离设为无穷大
                = inf;
            y(index_of_objectives(1),M + V + 1 + i) = inf;
             for j = 2 : length(index_of_objectives) - 1%循环集合中除了第一个和最后一个的个体
                next_obj  = sorted_based_on_objective(j + 1,V + i);
                previous_obj  = sorted_based_on_objective(j - 1,V + i);
                if (f_max - f_min == 0)
                    y(index_of_objectives(j),M + V + 1 + i) = inf;
                else
                    y(index_of_objectives(j),M + V + 1 + i) = ...
                         (next_obj - previous_obj)/(f_max - f_min);
                end
             end
        end
        distance = [];
        distance(:,1) = zeros(length(F(front).f),1);
        for i = 1 : M
            distance(:,1) = distance(:,1) + y(:,M + V + 1 + i);
        end
        y(:,M + V + 2) = distance;
        y = y(:,1 : M + V + 2);
        p_matrix(previous_index:current_index,:) = y;
    end
end

竞标赛选择交叉变异种群

%竞标赛选择法,每次随机选择两个个体,优先选择排序等级高的个体,如果排序等级一样,优选选择拥挤度大的个体,如果拥挤度相同则选序号小的那一个
%
%p_chromosome,m_chromosome 为根据patro解集排好序的种群编码   pool_size 竞标赛比赛的场次  tour_size 每场竞标赛的参赛选手个数 
function [p_parent_chromosome,m_parent_chromosome] = tournament_selection(p_chromosome,m_chromosome ,pool_size, tour_size)
    [pop, variables] = size(p_chromosome);%获得种群的个体数量和决策变量数量 pop种群数量 
    rank = variables - 1;%个体向量中排序值所在位置
    distance = variables;%个体向量中拥挤度所在位置
    for i = 1 : pool_size
        for j = 1 : tour_size
            candidate(j) = round(pop*rand(1));%随机选择参赛个体
            if candidate(j) == 0
                candidate(j) = 1;
            end
            if j > 1
                while ~isempty(find(candidate(1 : j - 1) == candidate(j)))%防止两个参赛个体是同一个
                    candidate(j) = round(pop*rand(1));
                    if candidate(j) == 0
                        candidate(j) = 1;
                    end
                end
            end
        end
        for j = 1 : tour_size   % 记录每个参赛者的排序等级 拥挤度
            c_obj_rank(j) = p_chromosome(candidate(j),rank);
            c_obj_distance(j) = p_chromosome(candidate(j),distance);
        end
        min_candidate = ...
            find(c_obj_rank == min(c_obj_rank));%选择排序等级较小的参赛者,find返回该参赛者的索引
        if length(min_candidate) ~= 1%如果两个参赛者的排序等级相等 则继续比较拥挤度 优先选择拥挤度大的个体
            max_candidate = ...
            find(c_obj_distance(min_candidate) == max(c_obj_distance(min_candidate)));
            if length(max_candidate) ~= 1
                max_candidate = max_candidate(1);
            end
            p_parent_chromosome(i,:) =p_chromosome(candidate(min_candidate(max_candidate)),:);
            m_parent_chromosome(i,:)=m_chromosome(candidate(min_candidate(max_candidate)),:);   
        else
            p_parent_chromosome(i,:) =p_chromosome(candidate(min_candidate(1)),:);
            m_parent_chromosome(i,:)=m_chromosome(candidate(min_candidate(1)),:);
        end
end

执行交叉变异操作

%交叉变异 M 优化目标数量 V优化目标数目 
%交叉为模拟二进制交叉
%变异为多项式变异
function[p_child_matrix,m_child_matrix] = genetic_operator(J,p_parent_chromosome,m_parent_chromosome)
    [N,M] = size(p_parent_chromosome);%N是交配池中的个体数量
    V=4;%优化目标数量
    across=0.8;
    mutation=0.1;
    p_child_matrix=[];
    m_child_matrix=[];
    k=1;%k记录生成的子代种群的数量,达到pop_size时,跳出循环
    for i = 1 : N%这里虽然循环N次,但是每次循环都会有概率产生2个或者1个子代,所以最终产生的子代个体数量大约是2N个
        if rand(1) < across%交叉概率0.8
            parent_1 =randperm(N,1);
            parent_2 =randperm(N,1);
        while isequal(p_parent_chromosome(parent_1,:),p_parent_chromosome(parent_2,:))%选择参与交叉操作的父代种群
            parent_2 = randperm(N,1);
        end
        p_parent_1 = p_parent_chromosome(parent_1,1:M-V-2);  
        m_parent_1=m_parent_chromosome(parent_1,:);
        p_parent_2 = p_parent_chromosome(parent_2,1:M-V-2);
        m_parent_2=m_parent_chromosome(parent_2,:);
        if mod(i,2)==1%进行工序交叉
            J1=[];
            c1_p=zeros(1,M-V-2);%子代染色体
            c1_m=zeros(1,M-V-2);
            c2_p=zeros(1,M-V-2);
            c2_m=zeros(1,M-V-2);
            while size(J1,1)==0&&size(J1,2)==0
                J1=find(round(rand(1,size(J,2)))==1);
            end
            for j=1:size(p_parent_1,2)
                %将属于第一个父代染色体中属于J1的工序位置保留下来
                if ismember(p_parent_1(j),J1)
                    c1_p(j)=p_parent_1(j);
                    c1_m(j)=m_parent_1(j);
                end
                %将第二个父代染色体中不属于J1的工序位置保留下来
                if ~ismember(p_parent_2(j),J1)
                    c2_p(j)=p_parent_2(j);
                    c2_m(j)=m_parent_2(j);
                end 
            end
            index_1_1=find(c1_p==0);
            index_1_2=find(c2_p~=0);
            index_2_2=find(c2_p==0);
            index_2_1=find(c1_p~=0);
            for j=1:size(index_1_1,2)
                c1_p(index_1_1(j))=p_parent_2(index_1_2(j));
                c1_m(index_1_1(j))=m_parent_2(index_1_2(j));
            end
            for j=1:size(index_2_2,2)
                c2_p(index_2_2(j))=p_parent_1(index_2_1(j));
                c2_m(index_2_2(j))=m_parent_1(index_2_1(j));
            end
        else   %进行设备交叉
            c1_p=p_parent_1;
            c1_m=m_parent_1;
            c2_p=p_parent_2;
            c2_m=m_parent_2;
            m_cross_index=find(round(rand(1,M-V-2))==0);%确定需要进行设备交叉的工序
            for j=1:size(m_cross_index,2)
                p_var=p_parent_1(m_cross_index(j));  %被选中的工件
                p_var_index=find(p_parent_1==p_var);   
                p_number=find(p_var_index==m_cross_index(j));%确定出该交叉点为哪个工件的第几道工序
                %确定出该工件的该道工序在第二个父代中的位置
                c2_across_index=find(p_parent_2==p_var);
                c1_m(m_cross_index(j))=m_parent_2(c2_across_index(p_number));
                c2_m(c2_across_index(p_number))=m_parent_1(m_cross_index(j));
            end      
        end
            p_child_matrix(k,:)=c1_p;
            m_child_matrix(k,:)=c1_m;
            k=k+1;
            p_child_matrix(k,:)=c2_p;
            m_child_matrix(k,:)=c2_m;
            k=k+1;
        end
        %基于工序和设备变异
        if rand(1)<mutation%变异概率
            parent_3 = randperm(N,1);
            parent_4 = randperm(N,1);
            p_parent_3 = p_parent_chromosome(parent_3,1:M-V-2);%参与工序变异的染色体
            m_parent_3 = m_parent_chromosome(parent_3,:);
            p_parent_4 = p_parent_chromosome(parent_4,1:M-V-2);%参与机器变异的染色体
            m_parent_4 = m_parent_chromosome(parent_4,:);
            c3_p=p_parent_3;
            c3_m=m_parent_3;
            c4_p=p_parent_4;
            c4_m=m_parent_4;
            rand_num_1=randperm(M-V-2,1);%基于工序变异的,参与变异的第一个位置
            rand_num_2=randperm(M-V-2,1);%基于工序变异的,参与变异的第二个位置
            while isequal(rand_num_1,rand_num_2)
                rand_num_2=randperm(M-V-2,1);
            end
%基于工序变异方法有误,请自行编写
%             c3_p(rand_num_1)=p_parent_3(rand_num_2);
%             c3_m(rand_num_1)=m_parent_3(rand_num_2);
%             c3_p(rand_num_2)=p_parent_3(rand_num_1);
%             c3_m(rand_num_2)=m_parent_3(rand_num_1);
%             p_child_matrix(k,:)=c3_p;
%             m_child_matrix(k,:)=c3_m;
%             k=k+1;
% 基于设备的变异
            rand_num_3=randperm(M-V-2,1);%参与变异的第一个位置
            rand_num_4=randperm(M-V-2,1);%参与变异的第二个位置
            while isequal(rand_num_3,rand_num_4)
                 rand_num_4=randperm(M-V-2,1);
            end
            p_var_3=p_parent_4(rand_num_3);
            p_var_4=p_parent_4(rand_num_4);
            muta_index_1=find(p_parent_4==p_var_3);
            num_of_p_1=find(muta_index_1==rand_num_3);%工件p_var的第num_of_1道工序
            muta_index_2=find(p_parent_4==p_var_4);
            num_of_p_2=find(muta_index_2==rand_num_4);
            m1=randperm(size(J(p_var_3).m{num_of_p_1},2),1);
            m2=randperm(size(J(p_var_4).m{num_of_p_2},2),1);
            c4_m(rand_num_3)=J(p_var_3).m{num_of_p_1}(m1);
            c4_m(rand_num_4)=J(p_var_4).m{num_of_p_2}(m2);
            p_child_matrix(k,:)=c4_p;
            m_child_matrix(k,:)=c4_m;
            k=k+1;
        end
    end 
end

绘制甘特图

%绘制甘特图
function f = ganttChart1(J,P_chromosome,M,mac_t)
    P=P_chromosome(1,1:size(P_chromosome,2)-6);
    p_text=[];%记录工件的工序信息
    m_info=[];%记录设备的加工信息
    p_color=[];%颜色信息
    color=['r','g','b','c','m','y'];
    for i=1:size(J,2)
        p_index=find(P==i);
        color_i=mod(i,6)+1;
        for j=1:size(p_index,2)
            p_var=p_index(j);
            p_text(p_var)=j;
            p_color(p_var)=color_i;
        end
    end
    for i=1:J(1).num_mac
        m_index=find(M==i);
        if size(m_index,1)>=1 && size(m_index,2)>=1
            for j=1:size(m_index,2)
                m_var=m_index(j);
                m_info(m_var)=j;
            end
        end
    end
    n_bay_nb=J(1).num_mac;%total bays  //机器数目
    n_task_nb=length(P);
    c_time=P_chromosome(size(P,2)+1);%所需的消耗时间
    d_time=P_chromosome(size(P,2)+2);%延期时间
    e_load=P_chromosome(size(P,2)+3);%设备负荷
    e_cons=P_chromosome(size(P,2)+4);%能量消耗
    axis([0,P_chromosome(size(P,2)+1)+2,0,n_bay_nb+0.5]);%x轴 y轴的范围
    set(gca,'xtick',0:2:c_time) ;%x轴的增长幅度
    set(gca,'ytick',0:1:n_bay_nb+0.5) ;%y轴的增长幅度
    xlabel('加工时间'),ylabel('机器号');%x轴 y轴的名称
    sche_info=sprintf('最大完工时间:%d  总延期:%d 设备总负载:%d 能耗总量:%.2fKw/h',c_time,d_time,e_load,e_cons)
    title(sche_info);%图形的标题
    rec=[0,0,0,0];
    for i =1:n_task_nb  
        rec(1) = mac_t{M(i)}(m_info(i),1);%矩形的横坐标
        rec(2) = M(i)-0.3;%矩形的纵坐标
        rec(3) = mac_t{M(i)}(m_info(i),2)-mac_t{M(i)}(m_info(i),1);%矩形的x轴方向的长度
        rec(4) = 0.6; 
        txt=sprintf('p(%d,%d)=%d',P(i),p_text(i),mac_t{M(i)}(m_info(i),2)-mac_t{M(i)}(m_info(i),1));%将机器号,工序号,加工时间连城字符串
        rectangle('Position',rec,'LineWidth',0.5,'LineStyle','-','FaceColor',color(p_color(i)));%draw every rectangle  
        text(mac_t{M(i)}(m_info(i),1)+0.2,M(i),txt,'FontWeight','Bold','FontSize',14);%label the id of every task  ,字体的坐标和其它特性
    end
end
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/144856.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • python图像识别与提取_图像分类python

    python图像识别与提取_图像分类python前面一篇文章介绍了图像增强知识,从而改善图像质量,增强图像识别效果,核心内容分为直方图均衡化、局部直方图均衡化和自动色彩均衡三部分。这篇文章将详细讲解图像分类知识,包括常见的图像分类算法,并介绍Python环境下的贝叶斯图像分类算法、基于KNN算法的图像分类和基于神经网络算法的图像分类等案例。万字长文整理,希望对您有所帮助。同时,该部分知识均为作者查阅资料撰写总结,并且开设成了收费专栏,为小宝赚点奶粉钱,感谢您的抬爱。当然如果您是在读学生或经济拮据,可以私聊我给你每篇文章开白名单,或者转发原文给你,更希望

    2022年10月14日
  • 实用cmd指令(1)

    实用cmd指令(1)

  • node require的用法_await与wait的区别

    node require的用法_await与wait的区别作为一个前端的新手,总是诧异于js的模块载入方式,看到了通过requireJs提供的require()命令之后,发现node也是通过类似的方法加载模块,我就好奇,这两个是一个东西吗?用electron写了一个webdeskapp,想通过CI上建一个job刷新repository,然后通过网页可以在team里面随时share软件的进度和功能,发现通过浏览器直接打开的这个app没法加载其他的库:

  • 如何查看某个端口被谁占用

    如何查看某个端口被谁占用

  • select top语句 mysql_SQL SELECT TOP 语句[通俗易懂]

    select top语句 mysql_SQL SELECT TOP 语句[通俗易懂]SELECTTOP子句用于规定要返回的记录的数目。SELECTTOP子句对于拥有数千条记录的大型表来说,是非常有用的。注释:并非所有的数据库系统都支持SELECTTOP子句。SQLServer/MSAccess语法SELECTTOPnumber|percentcolumn_name(s)FROMtable_name;MySQL和Oracle中的SQLSEL…

  • 什么是重载什么是覆盖_java覆盖和重载的关系

    什么是重载什么是覆盖_java覆盖和重载的关系java中的方法重载发生在同一个类里面两个或者多个方法的方法名相同但是参数不同的情况。与此相对,方法覆盖是说子类重新定义了父类的方法。方法覆盖必须有相同的方法名,参数列表和返回类型。覆盖者可能不会限

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号