在柔性作业车间调度问题中,使用nsga-Ⅱ对加工机器和加工时间编码并给出完整代码
时间: 2024-02-18 09:05:07 浏览: 85
以下是使用NSGA-II算法解决柔性作业车间调度问题的完整代码,其中使用了Python中的DEAP库:
```python
import random
import numpy as np
from deap import algorithms, base, creator, tools
# 定义问题类
class JobShopProblem(object):
def __init__(self, n_jobs, n_machines, jobs_data):
self.n_jobs = n_jobs # 作业数量
self.n_machines = n_machines # 机器数量
self.jobs_data = jobs_data # 作业数据
def makespan(self, perm):
# 初始化机器时间表
machine_time = np.zeros(self.n_machines)
# 初始化作业时间表
job_time = np.zeros(self.n_jobs)
for job_index in perm:
for machine_index, time in enumerate(self.jobs_data[job_index]):
# 计算机器时间表
start_time = max(machine_time[machine_index], job_time[job_index])
end_time = start_time + time
machine_time[machine_index] = end_time
# 计算作业时间表
job_time[job_index] = end_time
return job_time.max()
def random_permutation(n):
# 生成随机排列
array = np.arange(n)
np.random.shuffle(array)
return list(array)
def cx_partialy_matched(ind1, ind2):
# 部分匹配交叉算子
size = min(len(ind1), len(ind2))
p1, p2 = np.zeros(size), np.zeros(size)
# Initialize the position of each indices in the individuals
for i in range(size):
p1[int(ind1[i])] = i
p2[int(ind2[i])] = i
# Choose crossover points
cxpoint1 = random.randint(0, size)
cxpoint2 = random.randint(0, size - 1)
if cxpoint2 >= cxpoint1:
cxpoint2 += 1
else:
cxpoint1, cxpoint2 = cxpoint2, cxpoint1
# Apply crossover between cx points
for i in range(cxpoint1, cxpoint2):
# Keep track of the selected values
temp1 = ind1[i]
temp2 = ind2[i]
# Swap the matched value
ind1[i], ind1[p1[temp2]] = temp2, temp1
ind2[i], ind2[p2[temp1]] = temp1, temp2
# Position bookkeeping
p1[temp1], p1[temp2] = p1[temp2], p1[temp1]
p2[temp1], p2[temp2] = p2[temp2], p2[temp1]
return ind1, ind2
def mut_shuffle(individual, indpb):
# 随机交换变异算子
size = len(individual)
for i in range(size):
if random.random() < indpb:
# Choose the second index in the individual
j = random.randint(0, size - 1)
# Swap the elements
individual[i], individual[j] = individual[j], individual[i]
return individual,
# 定义NSGA-II算法的参数
POPULATION_SIZE = 100
P_CROSSOVER = 0.9
P_MUTATION = 0.1
MAX_GENERATIONS = 100
HALL_OF_FAME_SIZE = 10
CROWDING_FACTOR = 20.0
# 为适应度和个体定义适应度类和个体类
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)
# 初始化工具箱
toolbox = base.Toolbox()
toolbox.register("permutation", random_permutation, n=10)
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.permutation)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("mate", cx_partialy_matched)
toolbox.register("mutate", mut_shuffle, indpb=1.0/10)
toolbox.register("select", tools.selNSGA2)
# 定义主函数
def main():
# 读取数据
jobs_data = [[1, 3, 2], [5, 1, 2], [2, 4, 4], [3, 2, 3], [4, 3, 1], [6, 2, 1], [3, 1, 4], [4, 4, 2], [2, 3, 5], [5, 4, 3]]
n_jobs = len(jobs_data)
n_machines = len(jobs_data[0])
# 创建问题实例
problem = JobShopProblem(n_jobs, n_machines, jobs_data)
# 创建种群
population = toolbox.population(n=POPULATION_SIZE)
# 评估所有个体
fitnesses = list(map(problem.makespan, population))
for ind, fit in zip(population, fitnesses):
ind.fitness.values = (fit,)
# 运行NSGA-II算法
for generation in range(MAX_GENERATIONS):
offspring = algorithms.varAnd(population, toolbox, P_CROSSOVER, P_MUTATION)
fitnesses = list(map(problem.makespan, offspring))
for ind, fit in zip(offspring, fitnesses):
ind.fitness.values = (fit,)
population = toolbox.select(offspring + population, k=POPULATION_SIZE)
# 更新Hall of Fame
top_individuals = tools.selBest(population, k=HALL_OF_FAME_SIZE)
hof.update(top_individuals)
# 打印当前代数和Hall of Fame中的个体
print("-- Generation %i --" % generation)
print("Best individuals = ", *hof)
return hof[0]
if __name__ == "__main__":
# 创建Hall of Fame
hof = tools.ParetoFront()
# 运行主函数
best_solution = main()
print("Best solution found: %s" % best_solution)
```
在上述代码中,我们定义了一个`JobShopProblem`类来表示柔性作业车间调度问题,其中`makespan`方法计算了给定排列的完成时间。随后,我们定义了两个用于交叉和变异的算子,并使用`DEAP`库中的`tools`模块注册到工具箱中。最后,我们定义了主函数来运行NSGA-II算法并输出结果。注意到在主函数中,我们使用`ParetoFront`类来创建了一个Hall of Fame,用于存储所有被发现的非支配解。
阅读全文