基于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)


相关推荐

  • CSS中 RGB颜色查询对照表

    CSS中 RGB颜色查询对照表颜色代码表Ⅰ #000000 #2F0000 #600030 #460046 #28004D #272727 #4D0000 #820041 #5E005E #3A006F #3C3C3C #600000 #9F0050 #750075 #4B0091

  • SpringBoot +DynamicDataSource切换多数据源记录方法

    SpringBoot +DynamicDataSource切换多数据源记录方法

  • CSDN 2018博客之星评选,感谢大家的投票

    那些曾走过的路,看过的风景!2018博客之星评选,我在CSDN三年了,虽然没成为大神,大佬,但是这一路上一直在坚持,在进步, 感谢大家一路对我的支持和鼓励,虽然2018年这一年过的比较压抑,但是我期待2019。2019我会好好调整自己,输出更多好的内容!谢谢你为我投票! 2019祝你我 有酒,有肉 ,有故事! 我的投票专属地址 : 点我投票 #70 ,谢谢感谢 2018 那些走…

  • apache2虚拟主机实现一个服务器绑定多个域名[通俗易懂]

    apache2虚拟主机实现一个服务器绑定多个域名[通俗易懂]1.apache2的配置首先要配置好apache2,如果未配置,请参考我之前的博文:lamp的配置2.域名的解析将全部域名的www和@的A记录解析到云服务器的IP3.虚拟主机的配置1.配置httpd.conf如果etc/httpd/conf/httpd.conf存在,则配置此httpd.conf如果etc/httpd/conf/httpd.conf不存在,此时需要我们在/etc/apache2下

  • pytest-allure_苹果11验机报告

    pytest-allure_苹果11验机报告前言allure是一个report框架,支持java的Junit/testng等框架,当然也可以支持python的pytest框架,也可以集成到Jenkins上展示高大上的报告界面。mac环境:

  • 三菱PLC FB块的创建与使用

    三菱PLC FB块的创建与使用三菱PLCFB块的创建与使用在PLC编写程序过程中经常遇到一些重复逻辑控制的梯形图,比如流水线控制,气缸报警等等,这时候可以使用FB块来便捷编程,减少工作量与出错率。本例创建一个简单的单控气缸异常报警的FB块。所需输入有:气缸输出,气缸工作位,气缸原位,复位。所需输出有:工作位异常,原位异常。1,创建FB块:鼠标右击FB管理:选择新建数据:填写数据名并确认:2,编辑局部标签:其中INPUT为输入,OUTPUT为输出。3,编辑F…

发表回复

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

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