├── .idea ├── .gitignore ├── AI_lesson.iml ├── misc.xml ├── modules.xml ├── other.xml └── vcs.xml ├── README.md └── src └── com.upclzy └── hfsp ├── matlab ├── U1.m ├── calfitness.m ├── calobjvalue.m ├── crossover.m ├── initpop.m ├── makegantt.m ├── makerlru.m ├── mutation.m └── selection.m └── py ├── data.txt └── flowshop.py /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # 基于编辑器的 HTTP 客户端请求 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/AI_lesson.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/other.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # README 2 | hfsp文件夹中用两种方式完成了混合流水车间调度问题 -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/matlab/U1.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuzengyun/AI_lesson/2d6a4069c021ef9df0206c1a8935fc246a5d5590/src/com.upclzy/hfsp/matlab/U1.m -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/matlab/calfitness.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuzengyun/AI_lesson/2d6a4069c021ef9df0206c1a8935fc246a5d5590/src/com.upclzy/hfsp/matlab/calfitness.m -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/matlab/calobjvalue.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuzengyun/AI_lesson/2d6a4069c021ef9df0206c1a8935fc246a5d5590/src/com.upclzy/hfsp/matlab/calobjvalue.m -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/matlab/crossover.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuzengyun/AI_lesson/2d6a4069c021ef9df0206c1a8935fc246a5d5590/src/com.upclzy/hfsp/matlab/crossover.m -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/matlab/initpop.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuzengyun/AI_lesson/2d6a4069c021ef9df0206c1a8935fc246a5d5590/src/com.upclzy/hfsp/matlab/initpop.m -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/matlab/makegantt.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuzengyun/AI_lesson/2d6a4069c021ef9df0206c1a8935fc246a5d5590/src/com.upclzy/hfsp/matlab/makegantt.m -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/matlab/makerlru.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuzengyun/AI_lesson/2d6a4069c021ef9df0206c1a8935fc246a5d5590/src/com.upclzy/hfsp/matlab/makerlru.m -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/matlab/mutation.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuzengyun/AI_lesson/2d6a4069c021ef9df0206c1a8935fc246a5d5590/src/com.upclzy/hfsp/matlab/mutation.m -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/matlab/selection.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuzengyun/AI_lesson/2d6a4069c021ef9df0206c1a8935fc246a5d5590/src/com.upclzy/hfsp/matlab/selection.m -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/py/data.txt: -------------------------------------------------------------------------------- 1 | ++++++++++++++ 2 | instance 1 3 | 6 3 4 | 2 4 6 5 | 4 9 2 6 | 4 2 8 7 | 9 5 6 8 | 5 2 7 9 | 9 4 3 10 | -------------------------------------------------------------------------------- /src/com.upclzy/hfsp/py/flowshop.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import numpy as np, pandas as pd 3 | import time 4 | import copy 5 | import os 6 | import pandas as pd 7 | 8 | # 设置超参 9 | parser = argparse.ArgumentParser() 10 | parser.add_argument('--file', default='data.txt', type=str) 11 | parser.add_argument('--population', default=200, type=int) 12 | parser.add_argument('--machine', default=2, type=int) 13 | parser.add_argument('--crossover_rate', default=0.6, type=float) 14 | parser.add_argument('--mutation_rate', default=0.05, type=float) 15 | parser.add_argument('--num_mutation_jobs', default=2, type=float) 16 | parser.add_argument('--iteration', default=100, type=int) 17 | 18 | 19 | 20 | 21 | def read_file(file_name): 22 | data_csv = pd.read_csv(file_name, header=None) # 假设没有标题行 23 | rows = data_csv.values.tolist() 24 | 25 | gl = -1 # 初始化,未找到实例行 26 | num_process = 0 27 | num_job = 0 28 | data_new = None 29 | 30 | for i, row in enumerate(rows): 31 | row_str = ' '.join(map(str, row)) # 将行转换为字符串,方便分割 32 | data = row_str.split() 33 | 34 | if data[0] == "instance" and int(data[1]) == 1: 35 | gl = i 36 | elif i == gl + 1: 37 | num_job = int(data[0]) 38 | num_process = int(data[1]) 39 | data_new = [[0] * num_process for _ in range(num_job)] # 使用列表推导式创建二维列表 40 | elif gl != -1 and i > gl + 1 and i < gl + num_job + 2: 41 | for j in range(num_process): 42 | data_new[i - gl - 2][j] = int(data[j]) 43 | 44 | return data_new, num_process, num_job 45 | 46 | #交叉 返回变换结束和变换之前的 47 | def crossover(population_list, population, crossover_rate, num_job): 48 | parent_list = copy.deepcopy(population_list) 49 | offspring_list = copy.deepcopy(population_list) 50 | 51 | # 生成一个随机序列,选择要交叉的父染色体 52 | S = list(np.random.permutation(population)) 53 | 54 | for m in range(int(population / 2)): 55 | crossover_prob = np.random.rand() #0~1随机数 56 | if crossover_rate >= crossover_prob: #crossover_rate交叉概率 57 | parent_1 = population_list[S[2 * m]][:] 58 | parent_2 = population_list[S[2 * m + 1]][:] 59 | child_1 = ['na' for i in range(num_job)] 60 | child_2 = ['na' for i in range(num_job)] 61 | fix_num = round(num_job / 2) 62 | g_fix = list(np.random.choice(num_job, fix_num, replace=False)) #从num_job里取出fix_num个 63 | 64 | # 单点交叉,以fix_num为Cutting Point,为避免非法重复,子代在Cutting Point之后的顺序由另一父辈对应顺序决定。 65 | for g in range(fix_num): 66 | child_1[g_fix[g]] = parent_2[g_fix[g]] 67 | child_2[g_fix[g]] = parent_1[g_fix[g]] 68 | c1 = [parent_1[i] for i in range(num_job) if parent_1[i] not in child_1] 69 | c2 = [parent_2[i] for i in range(num_job) if parent_2[i] not in child_2] 70 | for i in range(num_job - fix_num): #把剩余的放进去 71 | child_1[child_1.index('na')] = c1[i] 72 | child_2[child_2.index('na')] = c2[i] 73 | offspring_list[S[2 * m]] = child_1[:] 74 | offspring_list[S[2 * m + 1]] = child_2[:] 75 | 76 | return offspring_list, parent_list 77 | 78 | 79 | def mutation(offspring_list, mutation_rate, num_job, num_mutation_jobs): 80 | # 突变job数量 81 | for m in range(len(offspring_list)): 82 | mutation_prob = np.random.rand() 83 | if mutation_rate >= mutation_prob: 84 | # 随机选出要变异的任务 85 | m_chg = list(np.random.choice(num_job, num_mutation_jobs, replace=False)) 86 | 87 | # 随机修改两位的基因值 88 | i = np.random.randint(0, num_mutation_jobs) 89 | t_value = offspring_list[m][m_chg[i]] 90 | offspring_list[m][m_chg[i]] = offspring_list[m][m_chg[num_mutation_jobs - 1 - i]] 91 | offspring_list[m][m_chg[num_mutation_jobs - 1 - i]] = t_value 92 | 93 | return offspring_list 94 | 95 | 96 | def cost_time(parent_list, offspring_list, data, num_process, num_job, machine, population): 97 | total_chromosome = copy.deepcopy(parent_list) + copy.deepcopy( 98 | offspring_list) # 将父基因与子基因合在一起 99 | chrom_fit = [] 100 | for c in range(population * 2): 101 | wait_time=[0 for _ in range(num_job)] 102 | gene = copy.deepcopy(total_chromosome[c]) 103 | for j in range(num_process): 104 | machine_time=[0 for _ in range(machine)] #记录每个machine结束的时间 105 | for i in range(num_job): 106 | index=machine_time.index(min(machine_time)) # 找到最空闲的machine 107 | # 在这个machine上做工件i 的 工序J 108 | machine_time[index]= max(machine_time[index], wait_time[gene[i]]) + data[gene[i]][j] 109 | # 记录这个工件i 的完成时间 110 | wait_time[ gene[i]]=machine_time[index] 111 | # 每次工序都要重新排序记录优先处理排列顺序 112 | gene=[idx for idx,value in sorted(enumerate(wait_time), key=lambda x:x[1])] 113 | total_time=max(machine_time) 114 | #total_time表示最终的时间消耗 115 | chrom_fit.append(total_time) 116 | return chrom_fit, total_chromosome 117 | 118 | 119 | def selection(population, population_list, chrom_fit, total_chromosome): 120 | pk, qk = [], [] 121 | # 轮盘赌选择 122 | chrom_fitness = 1. / np.array(chrom_fit) 123 | total_fitness = np.sum(chrom_fitness) 124 | for i in range(population * 2): 125 | pk.append(chrom_fitness[i] / total_fitness) 126 | for i in range(population * 2): 127 | cumulative = 0 128 | for j in range(0, i + 1): 129 | cumulative = cumulative + pk[j] 130 | qk.append(cumulative) #前i个pk求和 131 | 132 | selection_rand = [np.random.rand() for _ in range(population)] #200个0~1的随机数 133 | 134 | for i in range(population): 135 | if selection_rand[i] <= qk[0]: 136 | population_list[i] = copy.deepcopy(total_chromosome[0]) 137 | break 138 | else: 139 | for j in range(0, population * 2 - 1): 140 | if selection_rand[i] > qk[j] and selection_rand[i] <= qk[j + 1]: 141 | population_list[i] = copy.deepcopy(total_chromosome[j + 1]) 142 | return population_list 143 | 144 | 145 | def comparison(population, chrom_fit, total_chromosome, Tbest, Tbest_now, sequence_best): 146 | for i in range(population * 2): 147 | if chrom_fit[i] < Tbest_now: 148 | Tbest_now = chrom_fit[i] 149 | sequence_now = copy.deepcopy(total_chromosome[i]) 150 | 151 | if Tbest_now <= Tbest: 152 | Tbest = Tbest_now 153 | sequence_best = copy.deepcopy(sequence_now) 154 | return sequence_best, Tbest 155 | 156 | 157 | def main(args): 158 | if os.path.isfile(args.file): #判断是否为文件 159 | 160 | # 读取实例数据,机器数量,任务数量 161 | data, num_process, num_job = read_file(args.file) #读取文件例子,返回数据,行数列数 162 | # GA算法 163 | Tbest = 2 ** 20 164 | population_list, sequence_best = [], [] #分别赋值 165 | # 初始化population个随机job序列,实数编码 166 | for i in range(args.population): #添加200个乱序的原始job序列 167 | nxm_random_num = list(np.random.permutation(num_job)) #0~num_job-1的乱序 168 | population_list.append(nxm_random_num) #添加到list中 169 | # 迭代寻找最优解 170 | for n in range(args.iteration): #200 171 | Tbest_now = 2 ** 20 172 | offspring_list, parent_list = crossover(population_list, args.population, args.crossover_rate, num_job) 173 | offspring_list = mutation(offspring_list, args.mutation_rate, num_job, args.num_mutation_jobs) 174 | chrom_fit, total_chromosome = cost_time(parent_list, offspring_list, data, num_process, num_job, args.machine, args.population) 175 | population_list = selection(args.population, population_list, chrom_fit, total_chromosome) 176 | # 找到最好的job序列以及消耗的最短时间 177 | sequence_best, Tbest = comparison(args.population, chrom_fit, total_chromosome, Tbest, Tbest_now, 178 | sequence_best) 179 | 180 | # 显示结果 181 | print("optimal sequence", sequence_best) 182 | print("optimal value:%f" % Tbest) 183 | else: 184 | raise (ValueError, "Uknown document") 185 | 186 | 187 | if __name__ == '__main__': 188 | args = parser.parse_args() 189 | main(args) 190 | --------------------------------------------------------------------------------