大家好,又见面了,我是你们的朋友全栈君。
主函数:
%主函数
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账号...