├── .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 |
11 |
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 |
5 |
6 |
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 |
--------------------------------------------------------------------------------