遗传算法改进
交叉
交叉算子是遗传算法中最为重要的部分。
POX交叉
第一步,现任意在DNA上取到需要交叉工序基因的片段,然后父代P1,取到的片段复制给C1,同理P2也是一样的操作
第二步:在P1中取出包含J2中的工件,将剩余的工件安原来的顺序复制给C2;在P2中去掉包含J1中的工件,将剩余工件安原顺序复制给C1
如下图所示:
def POX_improve(self, Father_1, Father_2):
"""先选折一部分种群进行pox交叉操作,看看结果
Father_1,Father_2父代的DNA序列
"""
Father_1 = Father_1[0:self.WNumber].copy()
Father_2 = Father_2[0:self.WNumber].copy()
children_1= np.zeros(self.WNumber, dtype=int)
children_2 = np.zeros(self.WNumber, dtype=int)
#建立工件集合
Job_set = [i_+1 for i_ in range(10)]#有10个工件
J_set_1 = np.random.choice(Job_set, 2, replace=False)
J_set_2 = np.random.choice(Job_set, 2, replace=False)
index_J2_of_F1_set=[]
index_J1_of_F2_set=[]
for i in range(len(J_set_1)):
index_J1_of_F1 = np.where(Father_1 == J_set_1[i])[0]
index_J1_of_F2 = np.where(Father_2 == J_set_1[i])[0]
index_J2_of_F1 = np.where(Father_1 == J_set_2[i])[0]
index_J2_of_F2 = np.where(Father_2 == J_set_2[i])[0]
index_J2_of_F1_set.append(index_J2_of_F1)
index_J1_of_F2_set.append(index_J1_of_F2)
for i_1 in range(np.size(index_J1_of_F1)):
a_1 = index_J1_of_F1[i_1]
a_2 = index_J2_of_F2[i_1]
children_1[a_1] = Father_1[a_1]
children_2[a_2] = Father_2[a_2]
#第二部将F1的转接到C2
#将二维数组转化为一维数组
index_delet_1 = list(chain.from_iterable(index_J2_of_F1_set))
index_delet_2 = list(chain.from_iterable(index_J1_of_F2_set))
Father_1_deleted = np.delete(Father_1, index_delet_1)
Father_2_deleted = np.delete(Father_2, index_delet_2)
index_0_insert_1 = np.where(children_2 == 0)[0]
index_0_insert_2 = np.where(children_1 == 0)[0]
for j in range(np.size(Father_1_deleted)):
a_3 = index_0_insert_1[j]
a_4 = index_0_insert_2[j]
children_2[a_3] = Father_1_deleted[j]
children_1[a_4] = Father_2_deleted[j]
children_1 = CODE.en_code_3(children_1)
children_2 = CODE.en_code_3(children_2)
return children_1, children_2
均匀交叉
Step 1:随机生成长度为L的二进制编码串R
Step 2:将父代染色体中Pi中所有对应R中值为1的基因复制给子代C1,在P2中去掉复制给C1的基因后将剩余基因按顺序复制给C1
Step 3:将父代染色体中几中所有对应R中为1的基因赋值给子代C2,在P1中将复制给Cz的基因去掉后将剩余基因按顺序复制给C2
如图所示:
def Cross_evenly(self, DNA_1, DNA_2):
"""第二组采用均匀交叉的方式,通过加入二进制码进行交叉"""
F_1 = DNA_1[0:self.WNumber].copy()
F_2 = DNA_2[0:self.WNumber].copy()
#第一步随机生成二进制编码
R = np.random.randint(2, size=self.WNumber)#产生二进制码
c_1 = F_1*R
c_2 = F_2*R
for i in range(self.WNumber):#这里要将c_2在p_1中的值赋值为0
a_1 = c_2[i]
b_1 = c_1[i]
if a_1 > 0:
index_of_f_1_of_c_2 = np.where(F_1 == a_1)[0]
F_1[index_of_f_1_of_c_2[0]] = 0
if b_1 > 0:
index_of_f_2_of_c_1 = np.where(F_2 == b_1)[0]
F_2[index_of_f_2_of_c_1[0]] = 0
index_of_f_1 = np.where(F_1 > 0)[0]
index_of_c_2 = np.where(c_2 == 0)[0]
index_of_f_2 = np.where(F_2 > 0)[0]
index_of_c_1 = np.where(c_1 == 0)[0]
for j in range(np.size(index_of_f_1)):
a_2 = index_of_f_1[j]
a_3 = index_of_c_2[j]
b_2 = index_of_f_2[j]
b_3 = index_of_c_1[j]
c_2[a_3] = F_1[a_2]
c_1[b_3] = F_2[b_2]
c_1 = CODE.en_code_3(c_1)
c_2 = CODE.en_code_3(c_2)
return c_1, c_2
变异
变异是为了保证让遗传算法在进行搜素时,避免陷入局部最优解的情况。
机器号变异
按照变异概率Pm选定一个父代染色体进行变异操作,选择其中一个加工工序口,由于每道工序可以在多台机器上加工完成,所以每一工序都有其可选的加工机器集,在可以的加工机器集中随机选择一个机器完成变异操作。
def mut_mechine(self,DNA):
"""通过对DNA的工序重新解码,得到机器,这样就产生了机器变异"""
DNA = DNA[:self.WNumber]
mut_mechine_DNA = CODE.en_code_3(DNA)
return mut_mechine_DNA
工序变异
在工序基因段中随机选一个基因,然后再随机插入到这个DNA的工序基因片段中。
如图所示:
def mut_job(self, DNA):
"""这个变异是基于工件层面的变异,相当于单点自交叉"""
DNA = DNA[:self.WNumber]
DNA_1 = DNA[:self.WNumber].copy()
mut_two_of_position = np.random.choice([i_ for i_ in range(self.WNumber)], 2, replace=False)
a = mut_two_of_position[0]
b = mut_two_of_position[1]
DNA[b] = DNA_1[a]
DNA[a] = DNA_1[b]
mut_job_DNA = CODE.en_code_3(DNA)
return mut_job_DNA
局部邻域搜素
本遗传算法采用的邻域搜索,是通过选择加工时间最小的机器号,来进行邻域搜索
def Local_search_1(self, DNA):
"""第一中局部搜索,改变机器的选择"""
job_position_mechine = np.random.choice([i_ for i_ in range(self.WNumber)], 3, replace=False)
P = CODE.en_code_4(DNA)
for i in range(np.size(job_position_mechine)):
a = job_position_mechine[i]
b_m = a + self.WNumber
if P[a] == 206 and 306 and 406 and 706 and 806:
continue
M_num = []
T_M = []
for i_1 in range(self.MNumber):
Time = Jm_T.loc[P[a]][i_1]
if np.isnan(Time):
pass
else:
M_num.append(i_1 + 1)
T_M.append(Time)
if np.size(T_M) == 0:
continue
M_num_np = np.array(M_num)#这个位置是有问题的哈
T_M_np = np.array(T_M)
index_older = np.where(DNA[b_m] == M_num_np)[0]
min_t_index = np.argmin(T_M_np)
if T_M_np[index_older] > T_M_np[min_t_index]:
DNA[b_m] = M_num_np[min_t_index].copy()
return DNA
遗传算法的整体结构,流程图
实验结果