数学建模学习(111):改进遗传算法(引入模拟退火、轮盘赌和网格搜索)求解JSP问题

文章目录

  • 一、车间调度问题
    • 1.1目前处理方法
    • 1.2简单案例
  • 二、基于改进遗传算法求解车间调度
    • 2.1车间调度背景介绍
    • 2.2遗传算法介绍
      • 2.2.1基本流程
      • 2.2.2遗传算法的基本操作和公式
      • 2.2.3遗传算法的优势
      • 2.2.4遗传算法的不足
    • 2.3讲解本文思路及代码
    • 2.4算法执行结果:
  • 三、本文代码创新点
  • 四、附上完整代码

一、车间调度问题

  车间作业调度问题(JSP)是生产调度领域的经典问题之一,广泛应用于制造业、物流等领域。在一个典型的车间中,多个工件需要在多台机器上按特定的顺序进行加工。每个工件的加工步骤及其顺序是预先确定的,不同工件的加工顺序可能不同。 车间作业调度问题的目标是确定工件在各机器上的加工顺序,以最小化所有工件的完成总时间(即 makespan)。

1.1目前处理方法

  车间作业调度问题因其高度的复杂性和计算上的挑战性,被归类为NP难问题。为了解决这一问题,学术界和工业界已经提出了多种方法,涵盖了精确算法、启发式算法以及元启发式算法。
  精确算法,如分支定界法和动态规划,理论上能够找到全局最优解,但由于其高计算复杂度,通常不适用于大规模问题。
  启发式算法,例如优先规则,如最短加工时间优先(SPT)和最早截止时间优先(EDD),通过简单的规则快速生成可行解。尽管这些方法计算速度快,但解的质量往往无法得到保证。
  元启发式算法,包括遗传算法(GA)、模拟退火(SA)和粒子群优化(PSO),在处理复杂优化问题时表现出色。遗传算法通过模拟自然选择和遗传机制来不断优化解的种群;模拟退火算法通过模拟物质冷却过程中的能量变化来避免局部最优;粒子群优化算法则通过模拟鸟群觅食行为在多维空间中搜索全局最优解。
  近年来,混合算法也逐渐受到关注,例如结合遗传算法和禁忌算法的混合算法,能够利用不同算法的优势,提高解的质量和求解效率。

1.2简单案例

  我们假设有三个机器(M1, M2, M3)和三个工件(J1, J2, J3),每个工件已有不同的加工步骤和时间。这是一个简单的示例:
  假设加工步骤和时间如下:
  J1: M1(3) → M2(2) → M3(2)
  J2: M2(4) → M3(1) → M1(3)
  J3: M3(2) → M1(4) → M2(3)
  以时间为x轴,每个机器为y轴,利用Python求解,每种工件代表1种颜色,可绘制甘特图如下所示:
请添加图片描述
  绘图相应代码如下:

import matplotlib.pyplot as plt
import random
plt.rcParams['font.sans-serif'] = ['SimHei']
# 创建一个表示任务的列表,每个任务用一个字典表示
tasks = [{"Task": "J1", "Machine": "M1", "Start": 0, "Finish": 3},{"Task": "J1", "Machine": "M2", "Start": 3, "Finish": 5},{"Task": "J1", "Machine": "M3", "Start": 5, "Finish": 7},{"Task": "J2", "Machine": "M2", "Start": 0, "Finish": 4},{"Task": "J2", "Machine": "M3", "Start": 4, "Finish": 5},{"Task": "J2", "Machine": "M1", "Start": 5, "Finish": 8},{"Task": "J3", "Machine": "M3", "Start": 0, "Finish": 2},{"Task": "J3", "Machine": "M1", "Start": 2, "Finish": 6},{"Task": "J3", "Machine": "M2", "Start": 6, "Finish": 9},
]
# 创建一个新的图形
fig, gnt = plt.subplots()# 设置Y轴
gnt.set_ylim(0, 40)
gnt.set_xlim(0, 12)
# 设置Y轴标签
gnt.set_yticks([10, 20, 30])
gnt.set_yticklabels(['M1', 'M2', 'M3'])
# 设置X轴标签
gnt.set_xlabel('时间')
gnt.set_ylabel('机器')
# 生成不同的颜色,每个工件一个颜色
task_colors = {}
for task in tasks:if task["Task"] not in task_colors:task_colors[task["Task"]] = (random.random(), random.random(), random.random())
# 绘制任务
for task in tasks:machine_map = {"M1": 10, "M2": 20, "M3": 30}start = task["Start"]finish = task["Finish"]machine = machine_map[task["Machine"]]color = task_colors[task["Task"]]gnt.broken_barh([(start, finish - start)], (machine - 5, 9), facecolors=color)
# 显示甘特图
plt.show()

二、基于改进遗传算法求解车间调度

2.1车间调度背景介绍

  在一个车间内,有10台机器,每台机器负责一道加工步骤。这些机器需要完成10个工件的加工,每个工件都有10个加工步骤。不同工件的加工步骤顺序各不相同且顺序不可更改。每个加工步骤由对应的机器在一定时间内完成。你需要确定各个工件在不同机器上的加工顺序,以最小化所有工件完成加工所需的总时间。具体的不同工件加工顺序与加工时长如下表所示:
在这里插入图片描述
  对于每个工件,其加工顺序和每台机器上的加工耗时一定,拿第一行举例。工件1的加工顺序为:M1-M2-M4-M3-M5-M6-M8-M4-M7-M10。其花费时间固定,分别为28-33-11-48-18-19-86-64-65-90。我们要做的就是对机器进行调度,什么时候加工第几个工件的第几个工序

2.2遗传算法介绍

  遗传算法(Genetic Algorithm,GA)是一类模拟自然选择和遗传机制的进化算法,主要用于优化和搜索问题。它最早由约翰·霍兰德(John Holland)在20世纪70年代提出。遗传算法通过模拟自然界生物进化的过程,包括选择、交叉(杂交)和变异等操作,逐步优化问题的解。

2.2.1基本流程

  1. 初始化种群:随机生成一定数量的初始解,称为个体,这些个体构成初始种群。
  2. 适应度评估:计算每个个体的适应度值,适应度值越高表示该个体越适合问题的求解。
  3. 选择:根据个体的适应度值,选择一些个体作为父代。常用的选择方法有轮盘赌选择、锦标赛选择等。
  4. 交叉:通过交叉操作(即杂交)生成新的个体,交叉操作将两个父代个体的部分基因交换,从而生成子代个体。
  5. 变异:对新生成的个体进行变异操作,即随机改变个体的一部分基因,以增加种群的多样性。
  6. 生成新种群:用子代个体替换部分或全部父代个体,形成新一代种群。
  7. 重复迭代:重复上述步骤,直到满足终止条件,如达到最大迭代次数或种群中的最佳适应度值达到预期目标。

2.2.2遗传算法的基本操作和公式

  1. 选择操作:选择操作通过适应度值选择个体。轮盘赌选择法的概率计算公式:
    P i = f i ∑ j = 1 N f j P_i = \frac{f_i}{\sum_{j=1}^{N} f_j} Pi=j=1Nfjfi
    其中,(P_i) 是第 (i) 个个体被选中的概率,(f_i) 是第 (i) 个个体的适应度值,(N) 是种群的大小。
  2. 交叉操作:交叉操作将两个父代个体的基因部分交换,生成两个新的个体。单点交叉的公式:
    子代1 = ( 父代1 1 , 父代1 2 , … , 父代1 c , 父代2 c + 1 , … , 父代2 n ) 子代2 = ( 父代2 1 , 父代2 2 , … , 父代2 c , 父代1 c + 1 , … , 父代1 n ) \begin{aligned} &\text{子代1} = (\text{父代1}_1, \text{父代1}_2, \ldots, \text{父代1}_c, \text{父代2}_{c+1}, \ldots, \text{父代2}_n) \\ &\text{子代2} = (\text{父代2}_1, \text{父代2}_2, \ldots, \text{父代2}_c, \text{父代1}_{c+1}, \ldots, \text{父代1}_n) \end{aligned} 子代1=(父代11,父代12,,父代1c,父代2c+1,,父代2n)子代2=(父代21,父代22,,父代2c,父代1c+1,,父代1n)
    其中,(c) 是交叉点的位置,(\text{父代1}) 和 (\text{父代2}) 是两个父代个体,(n) 是个体的基因长度。
  3. 变异操作:变异操作随机改变个体的一部分基因。对于一个基因序列 (x = (x_1, x_2, \ldots, x_n)),其变异公式可以表示为:
    x i ′ = { 随机值 如果 随机概率 < 变异概率 x i 否则 x_i' = \begin{cases} \text{随机值} & \text{如果 } \text{随机概率} < \text{变异概率} \\ x_i & \text{否则} \end{cases} xi={随机值xi如果 随机概率<变异概率否则
    其中,(x_i’) 是变异后的基因值,变异概率通常设为一个小值,如0.01或0.1。

2.2.3遗传算法的优势

  • 全局搜索能力强:遗传算法通过选择、交叉和变异等操作,可以在较大范围内进行搜索,能够较好地避免陷入局部最优。
  • 适用范围广:遗传算法适用于各种优化问题,包括离散问题和连续问题。
  • 易于并行化:由于种群中的个体可以并行计算适应度值,遗传算法易于实现并行计算,提升计算效率。

2.2.4遗传算法的不足

  • 计算开销大:遗传算法需要多次迭代,且每次迭代需要计算多个个体的适应度值,计算开销较大。
  • 参数选择复杂:遗传算法的性能对参数(如种群大小、交叉率、变异率等)依赖较大,参数选择不当可能影响算法效果。
  • 收敛速度慢:在某些情况下,遗传算法的收敛速度较慢,可能需要较多的迭代次数才能找到较优的解。

2.3讲解本文思路及代码

  本文改进遗传算法的代码更侧重于结合多种优化算法解决问题。利用网格搜索找到最优参数,并且在搜索过程中结合模拟退火算法进行局部优化,探索了更大范围的解空间,寻找最优解的可能性更大,利用上述显著优势尝试求解JSP问题。
  Step1:初始化。创建一个初始种群,每个个体代表一个可能的作业顺序。通过随机生成的方式确保种群的多样性。

def createPop(Jm, popSize):pop = []for i in range(popSize):pop.append(createInd(Jm))return pop

  Step2:选择。使用轮盘赌选择方法,根据个体的适应度(即完工时间)概率性地选择个体。适应度越高(即完工时间越短),被选择的概率越大。

def roulette_wheel_selection(fitness):total_fitness = sum(fitness)pick = random.uniform(0, total_fitness)current = 0for i, fit in enumerate(fitness):current += fitif current > pick:return i

  Step3:交叉。应用自定义的交叉操作,将父代个体组合生成新的后代。通过选择两个父代个体,交换它们的一部分基因片段,以继承父母双方的特征。

def cross(A, B):n = len(A)r1 = np.random.randint(n)r2 = np.random.randint(n)rl, rr = min(r1, r2), max(r1, r2)if rl == rr:return A, Bbt = copy.deepcopy(B)afinal = copy.deepcopy(A)for i in range(rl, rr + 1):bt.remove(A[i])k = 0for i in range(n):if i < rl or i > rr:afinal[i] = bt[k]k += 1at = copy.deepcopy(A)bfinal = copy.deepcopy(B)for i in range(rl, rr + 1):at.remove(B[i])k = 0for i in range(n):if i < rl or i > rr:bfinal[i] = at[k]k += 1return afinal, bfinal

  Step4:变异。通过随机交换作业操作引入变异,以保持基因多样性。变异操作有助于防止算法陷入局部最优。

def mutate(individual, mutation_rate):if random.random() < mutation_rate:index1, index2 = random.sample(range(len(individual)), 2)individual[index1], individual[index2] = individual[index2], individual[index1]return individual

  Step5:解码。使用详细的调度算法解码每个个体,以评估其完工时间,确保所有作业约束得到满足。解码过程包括为每个作业在特定机器上安排开始和结束时间。

def decode(J, P, s):n, m = J.shapeT = [[[0]] for _ in range(m)]C = np.zeros((n, m))k = np.zeros(n, dtype=int)for job in s:if job < 0 or job >= n:print(f"Invalid job index: {job}")continueif k[job] < 0 or k[job] >= m:print(f"Invalid operation index for job {job}: {k[job]}")continuemachine = J[job, k[job]] - 1process_time = P[job, k[job]]last_job_finish = C[job, k[job] - 1] if k[job] > 0 else 0start_time = max(last_job_finish, T[machine][-1][-1])insert_index = len(T[machine])for i in range(1, len(T[machine])):gap_start = max(last_job_finish, T[machine][i - 1][-1])gap_end = T[machine][i][0]if gap_end - gap_start >= process_time:start_time = gap_startinsert_index = ibreakend_time = start_time + process_timeC[job, k[job]] = end_timeT[machine].insert(insert_index, [start_time, job, k[job], end_time])k[job] += 1M = [[] for _ in range(m)]for machine in range(m):for j in T[machine][1:]:M[machine].append(j[1])return T, M, C

  Step6:模拟退火。为了增强搜索能力,本文结合模拟退火方法,对个体解进行微调,允许偶尔接受较差解,以跳出局部最优。模拟退火通过**逐渐降低“温度”**来减少接受较差解的概率,从而达到全局优化的效果。

def simulated_annealing(individual, J, P, T0, alpha, max_iter):current_solution = copy.deepcopy(individual)Tmax, _, current_fitness = decode(J, P, current_solution)best_solution = copy.deepcopy(current_solution)best_fitness = current_fitness.max()T = T0for i in range(max_iter):new_solution = mutate(copy.deepcopy(current_solution), 1.0)Tmax, _, new_fitness = decode(J, P, new_solution)delta_fitness = new_fitness.max() - current_fitness.max()if delta_fitness < 0 or random.random() < math.exp(-delta_fitness / T):current_solution = new_solutioncurrent_fitness = new_fitnessif current_fitness.max() < best_fitness:best_solution = copy.deepcopy(current_solution)best_fitness = current_fitness.max()T *= alphareturn best_solution, best_fitness

  Step7:算法执行过程。通过初始化种群并不断执行选择、交叉、变异和解码操作,结合模拟退火优化,遗传算法逐步优化种群中的个体。每一代后,种群会逐步接近最优解,最终输出最优的调度方案。以下是主函数部分,展示了算法的执行过程:

# 主函数
if __name__ == "__main__":J, P = load_data('05.txt')pop_size = 50max_iter = 5000w = 0.5c1 = 1.5c2 = 1.5best_position, best_fitness = pso(J, P, pop_size, max_iter, w, c1, c2)print(f'Best Solution: {best_position}')print(f'Best Fitness: {best_fitness}')T, M, C = decode(J, P, best_position)drawGantt(T)plt.show()

2.4算法执行结果:

  经过长时间运行,本文得到最少用时为 893s, 由网格搜索得到的具体参数如下所示:
在这里插入图片描述

三、本文代码创新点

  • 创新1:引入混合优化算法。本文结合了遗传算法、模拟退火和网格搜索三种优化方法,提升了搜索效率和解的质量。遗传算法利用选择、交叉和变异操作进行全局搜索,模拟退火通过局部搜索进一步优化解,而网格搜索则用于寻找最佳的参数组合。

  • 创新2:采用网格搜索。param_grid定义了一系列参数范围,通过遍历所有参数组合,自动化寻找最佳参数设置,确保算法在参数空间内找到最优解。

  • 创新3:引入模拟退火策略。在遗传算法的基础上,引入模拟退火策略,有效地跳出局部最优解,进一步提升解的质量。通过控制退火过程的温度,平衡了探索与开发。

  • 创新4:自适应交叉和变异操作。交叉和变异操作的实现更加灵活,能够根据个体特性进行调整。变异操作通过概率控制增加了种群的多样性,帮助避免过早收敛。

  • 创新5:甘特图绘制。通过rawGantt函数,使用不同颜色表示不同工件的操作,并在甘特图上显示详细的操作信息,提供了直观的调度结果可视化。

  • 创新6:基于轮盘赌选择。采用轮盘赌选择机制,增加了适应度高的个体被选中的概率,确保了优良基因的传递,提高了算法的收敛速度和效果。

四、附上完整代码

import copy
import numpy as np
import matplotlib.pyplot as plt
import random
import math
#------------------------------------------------------------------------------------------------------------------#-------------------------------------------------------------------------------------
def createInd(J):#创建个体n = J.shape[0]s = []Jm = J.copy()while not np.all(Jm == 0):I = np.random.randint(0, n)M = Jm[I, 0]if M != 0:s.append(I)b = np.roll(Jm[I, :], -1)b[-1] = 0Jm[I, :] = breturn sdef createPop(Jm, popSize):#创建种群pop = []for i in range(popSize):pop.append(createInd(Jm))return popdef decode(J, P, s):#解码n, m = J.shapeT = [[[0]] for _ in range(m)]C = np.zeros((n, m))k = np.zeros(n, dtype=int)for job in s:machine = J[job, k[job]] - 1process_time = P[job, k[job]]last_job_finish = C[job, k[job] - 1] if k[job] > 0 else 0start_time = max(last_job_finish, T[machine][-1][-1])insert_index = len(T[machine])for i in range(1, len(T[machine])):gap_start = max(last_job_finish, T[machine][i - 1][-1])gap_end = T[machine][i][0]if gap_end - gap_start >= process_time:start_time = gap_startinsert_index = ibreakend_time = start_time + process_timeC[job, k[job]] = end_timeT[machine].insert(insert_index, [start_time, job, k[job], end_time])k[job] += 1M = [[] for _ in range(m)]for machine in range(m):for j in T[machine][1:]:M[machine].append(j[1])return T, M, Cdef drawGantt(timelist):#绘制甘特图T = timelist.copy()plt.rcParams['font.sans-serif'] = ['SimHei']fig, ax = plt.subplots(figsize=(10, 6))color_map = {}for machine in T:for task_data in machine[1:]:job_idx, operation_idx = task_data[1], task_data[2]if job_idx not in color_map:color_map[job_idx] = (random.random(), random.random(), random.random())for machine_idx, machine_schedule in enumerate(T):for task_data in machine_schedule[1:]:start_time, job_idx, operation_idx, end_time = task_datacolor = color_map[job_idx]ax.barh(machine_idx, end_time - start_time, left=start_time, height=0.4, color=color)label = f'{job_idx}-{operation_idx}'ax.text((start_time + end_time) / 2, machine_idx, label, ha='center', va='center', color='white', fontsize=10)ax.set_yticks(range(len(T)))ax.set_yticklabels([f'machine{i + 1}' for i in range(len(T))])plt.xlabel("时间")plt.title("JSP甘特图")l = []for job_idx, color in color_map.items():l.append(plt.Rectangle((0, 0), 1, 1, color=color, label=f'{job_idx}'))plt.legend(handles=l, title='工件')def cross(A, B):#交叉操作n = len(A)r1 = np.random.randint(n)r2 = np.random.randint(n)rl, rr = min(r1, r2), max(r1, r2)if rl == rr:return A, Bbt = copy.deepcopy(B)afinal = copy.deepcopy(A)for i in range(rl, rr + 1):bt.remove(A[i])k = 0for i in range(n):if i < rl or i > rr:afinal[i] = bt[k]k += 1at = copy.deepcopy(A)bfinal = copy.deepcopy(B)for i in range(rl, rr + 1):at.remove(B[i])k = 0for i in range(n):if i < rl or i > rr:bfinal[i] = at[k]k += 1return afinal, bfinaldef load_data(path):#载入操作with open(path, 'r') as file:lines = file.readlines()job_num, machines_num = map(int, lines[0].split())J = np.zeros((job_num, len(lines[1].split()) // 2), dtype=int)P = np.zeros((job_num, len(lines[1].split()) // 2), dtype=int)for i in range(1, len(lines)):data = list(map(int, lines[i].split()))for j in range(len(data)):if j % 2 == 0:J[i - 1][j // 2] = data[j]else:P[i - 1][j // 2] = data[j]return J, Pdef mutate(individual, mutation_rate):#变异操作if random.random() < mutation_rate:index1, index2 = random.sample(range(len(individual)), 2)individual[index1], individual[index2] = individual[index2], individual[index1]return individualdef roulette_wheel_selection(fitness):#轮盘赌total_fitness = sum(fitness)pick = random.uniform(0, total_fitness)current = 0for i, fit in enumerate(fitness):current += fitif current > pick:return idef simulated_annealing(individual, J, P, T0, alpha, max_iter):#模拟退火current_solution = copy.deepcopy(individual)Tmax, _, current_fitness = decode(J, P, current_solution)best_solution = copy.deepcopy(current_solution)best_fitness = current_fitness.max()T = T0for i in range(max_iter):new_solution = mutate(copy.deepcopy(current_solution), 1.0)Tmax, _, new_fitness = decode(J, P, new_solution)delta_fitness = new_fitness.max() - current_fitness.max()if delta_fitness < 0 or random.random() < math.exp(-delta_fitness / T):current_solution = new_solutioncurrent_fitness = new_fitnessif current_fitness.max() < best_fitness:best_solution = copy.deepcopy(current_solution)best_fitness = current_fitness.max()T *= alphareturn best_solution, best_fitnessparam_grid = {#网格搜索'pop_size': [300, 400, 500],'mutation_rate': [ 0.5, 0.7, 0.9],'T0': [ 1500, 2000],'alpha': [0.95, 0.97, 0.99],'max_iter': [50, 100, 150, 200]
}# 加载数据
J, P = load_data('05.txt')
n, m = J.shape# 初始化最优参数和最优结果
best_params = {}
best_Cmax = float('inf')# 网格搜索循环
for pop_size in param_grid['pop_size']:for mutation_rate in param_grid['mutation_rate']:for T0 in param_grid['T0']:for alpha in param_grid['alpha']:for max_iter in param_grid['max_iter']:print(f'Testing parameters: pop_size={pop_size}, mutation_rate={mutation_rate}, T0={T0}, alpha={alpha}, max_iter={max_iter}')pop = createPop(J, pop_size)Tmax, _, C = decode(J, P, pop[0])fitness = [C.max()]Cmax = C.max()bestInd = copy.deepcopy(pop[0])for i in range(1, pop_size):T_, _, C = decode(J, P, pop[i])if C.max() < Cmax:Tmax = T_Cmax = C.max()bestInd = copy.deepcopy(pop[i])fitness.append(C.max())g = 0gen = n * mwhile g < gen:g += 1newInd = []newFitness = []l = 0while l < pop_size / 2:l += 1tm = roulette_wheel_selection(fitness)l1, l2 = cross(pop[tm], bestInd)T1, _, C1 = decode(J, P, l1)newInd.append(l1)newFitness.append(C1.max())if C1.max() < Cmax:Tmax = T1Cmax = C1.max()bestInd = copy.deepcopy(l1)T2, _, C2 = decode(J, P, l2)newInd.append(l2)newFitness.append(C2.max())if C2.max() < Cmax:Tmax = T2Cmax = C2.max()bestInd = copy.deepcopy(l2)newpop = pop + newIndnewFit = fitness + newFitnessnewId = np.array(newFit).argsort()[:pop_size]pop = copy.deepcopy([newpop[i] for i in newId])fitness = [newFit[i] for i in newId]for i in range(pop_size):pop[i] = mutate(pop[i], mutation_rate)Ind = copy.deepcopy(pop[i])Tt, _, Ct = decode(J, P, Ind)fitness[i] = Ct.max()if Ct.max() < Cmax:Tmax = TtCmax = Ct.max()bestInd = copy.deepcopy(Ind)# 模拟退火for i in range(pop_size):pop[i], fitness[i] = simulated_annealing(pop[i], J, P, T0, alpha, max_iter)if fitness[i] < Cmax:Tmax, _, _ = decode(J, P, pop[i])Cmax = fitness[i]bestInd = copy.deepcopy(pop[i])print(f'第{g}代, Cmax={Cmax}')if Cmax < best_Cmax:best_Cmax = Cmaxbest_params = {'pop_size': pop_size,'mutation_rate': mutation_rate,'T0': T0,'alpha': alpha,'max_iter': max_iter}print(f'Best parameters: {best_params}')
print(f'Best Cmax: {best_Cmax}')# 使用最优参数重新运行算法
pop_size = best_params['pop_size']
mutation_rate = best_params['mutation_rate']
T0 = best_params['T0']
alpha = best_params['alpha']
max_iter = best_params['max_iter']
pop = createPop(J, pop_size)
Tmax, _, C = decode(J, P, pop[0])
fitness = [C.max()]
Cmax = C.max()
bestInd = copy.deepcopy(pop[0])
for i in range(1, pop_size):T_, _, C = decode(J, P, pop[i])if C.max() < Cmax:Tmax = T_Cmax = C.max()bestInd = copy.deepcopy(pop[i])fitness.append(C.max())
g = 0
gen = n * m
chistory = []
while g < gen:g += 1newInd = []newFitness = []l = 0while l < pop_size / 2:l += 1tm = roulette_wheel_selection(fitness)l1, l2 = cross(pop[tm], bestInd)T1, _, C1 = decode(J, P, l1)newInd.append(l1)newFitness.append(C1.max())if C1.max() < Cmax:Tmax = T1Cmax = C1.max()bestInd = copy.deepcopy(l1)T2, _, C2 = decode(J, P, l2)newInd.append(l2)newFitness.append(C2.max())if C2.max() < Cmax:Tmax = T2Cmax = C2.max()bestInd = copy.deepcopy(l2)newpop = pop + newIndnewFit = fitness + newFitnessnewId = np.array(newFit).argsort()[:pop_size]pop = copy.deepcopy([newpop[i] for i in newId])fitness = [newFit[i] for i in newId]for i in range(pop_size):pop[i] = mutate(pop[i], mutation_rate)Ind = copy.deepcopy(pop[i])Tt, _, Ct = decode(J, P, Ind)fitness[i] = Ct.max()if Ct.max() < Cmax:Tmax = TtCmax = Ct.max()bestInd = copy.deepcopy(Ind)# 模拟退火for i in range(pop_size):pop[i], fitness[i] = simulated_annealing(pop[i], J, P, T0, alpha, max_iter)if fitness[i] < Cmax:Tmax, _, _ = decode(J, P, pop[i])Cmax = fitness[i]bestInd = copy.deepcopy(pop[i])print(f'第{g}代, Cmax={Cmax}')chistory.append(Cmax)
plt.plot(chistory)
plt.show()
drawGantt(Tmax)
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/382261.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于MobileNetv2的垃圾分类函数式自动微分-昇思25天打卡

基于MobileNetv2的垃圾分类 本文档主要介绍垃圾分类代码开发的方法。通过读取本地图像数据作为输入&#xff0c;对图像中的垃圾物体进行检测&#xff0c;并且将检测结果图片保存到文件中。 1、实验目的 了解熟悉垃圾分类应用代码的编写&#xff08;Python语言&#xff09;&a…

linux 网络子系统

__netif_receive_skb_core 是 Linux 内核网络子系统中一个非常重要的函数&#xff0c;它负责将网络设备驱动层接收到的数据包传递到上层协议栈进行处理。以下是对该函数的一些关键点的详细解析&#xff1a; 一、函数作用 __netif_receive_skb_core 函数是处理接收到的网络数据…

linux 解决端口占用

1.查询被占用的端口 netstat -tln | grep 60602.查询该端口对应的服务 lsof -i :60603.杀死该进程 //14868是第二步的PID kill -9 14868

ubuntu在命令行输出里查找内容,dmesg

直接执行查看日志指令会出来很多页。dmesg为开机日志信息。记录了开机时硬件的过程 sudo dmesg 执行结果&#xff1a; 可以用竖号“|”&#xff0c;在前一条命令返回的内容进行查找。下图为查找bluetooth sudo dmesg |grep -i bluetooth

算法-嵌套类递归解题套路

文章目录 理论基础 :1. 基本计算器2. 字符串解码3. 求原子数量 理论基础 : 嵌套类递归是指一种一个字符串形式的问题通过嵌套调用子函数从而求解出结果的一类问题, 解题方法相对来说比较的固定, 我们总结为下面的几部分 大概过程 : 定义全局变量where递归函数 f ( i ) : s [ i …

【C++】——初识模版

文章目录 前言函数模版函数模版的原理函数模版的实例化 类模版类模版的实例化 前言 当我们使用一个通用的函数&#xff1a; //为每一个类型都编写一个重载版本 void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& …

C# 与C++ cli

cli CLI&#xff08;Command Line Interface&#xff09;是一种通过命令行界面与计算机系统进行交互的方式。它提供了一种以文本形式输入命令和接收系统输出的方法&#xff0c;用于执行各种操作和管理计算机系统。以下是CLI的详细解释&#xff1a; 一、定义与基本概念 定义&…

编程中的智慧四:设计模式总览

前面三篇我们通过从一些零散的例子&#xff0c;和简单应用来模糊的感受了下设计模式在编程中的智慧&#xff0c;从现在开始正式进入设计模式介绍&#xff0c;本篇将从设计模式的7大原则、设计模式的三大类型、与23种设计模式的进行总结&#xff0c;和描述具体意义。 设计模式体…

【中项】系统集成项目管理工程师-第4章 信息系统架构-4.5技术架构

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

关卡1-2:Python关卡

关卡1-2&#xff1a;Python关卡 一、python实现wordcount二、通过本地VSCODE连接internStudio与debug2.1使用本地的VSCODE连接InternStudio2.2 debug插件安装2.3 debug进行时2.3.1 代码准备2.3.2 选择python解释器2.3.3 打断点 一、python实现wordcount 采用python实现经典任务…

虚拟机迁移报错:虚拟机版本与主机“x.x.x.x”的版本不兼容

1.虚拟机在VCenter上从一个ESXi迁移到另一个ESXi上时报错&#xff1a;虚拟机版本与主机“x.x.x.x”的版本不兼容。 2.例如从10.0.128.13的ESXi上迁移到10.0.128.11的ESXi上。点击10.0.128.10上的任意一台虚拟机&#xff0c;查看虚拟机版本。 3.确认要迁移的虚拟机磁盘所在位…

大厂面试-基本功

大厂面试第4季 服务可用性多少个9是什么意思遍历集合add或remove操作bughashcode冲突案例BigdecimalList去重复IDEA Debugger测试框架ThreaLocal父子线程数据同步 InheritableThreadLocal完美解决线程数据同步方案 TransmittableThreadLocal 服务可用性多少个9是什么意思 遍历集…

Android中systrace配置及注意问题

Android中systrace配置及注意问题 systrace配置的官方文档地址如下&#xff1a;优化启动时间 Systrace systrace 允许在启动期间收集内核和 Android 跟踪记录。systrace 的可视化可以帮助分析启动过程中的具体问题。&#xff08;不过&#xff0c;如果要查看整个启动过程中的平…

[Spring] Spring配置文件

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

DocRED数据集

DocRED数据集文件夹包含多个JSON文件&#xff0c;每个文件都有不同的用途。以下是这些文件的用途解释以及哪个文件是训练集&#xff1a; 文件解释 dev.json&#xff1a;包含开发集&#xff08;验证集&#xff09;的数据&#xff0c;通常用于模型调优和选择超参数。 label_map…

Java | Leetcode Java题解之第260题只出现一次的数字III

题目&#xff1a; 题解&#xff1a; class Solution {public int[] singleNumber(int[] nums) {int xorsum 0;for (int num : nums) {xorsum ^ num;}// 防止溢出int lsb (xorsum Integer.MIN_VALUE ? xorsum : xorsum & (-xorsum));int type1 0, type2 0;for (int n…

Java 中的异常

异常&#xff1a;就是出现的问题。 在Java中异常被当成对象进行处理&#xff0c;所有的异常类都继承于Throwable类&#xff0c;如果Java提供的异常类并不能满足需求&#xff0c;用户还可以自己定义一个异常类。 下面是异常体系结构&#xff1a; Throwable又分成了Error和Exce…

PHP框架详解- symfony框架

文心一言 Symfony框架是一个用PHP语言编写的开放源代码的Web应用框架&#xff0c;旨在加速Web应用程序的开发过程&#xff0c;提高代码的可维护性和可扩展性。以下是对Symfony框架的详细解析&#xff1a; 一、框架概述 起源与开发者&#xff1a; Symfony由SensioLabs&#…

音乐曲谱软件Guitar Pro 8.2 for Mac 中文破解版

Guitar Pro 8.2 for Mac 中文破解版是一款功能强大的音乐曲谱软件&#xff0c;非常适合学习如何玩&#xff0c;改进技巧&#xff0c;重现喜爱的歌曲或陪伴自己。 Guitar Pro for Mac 是一款功能强大的音乐曲谱软件&#xff0c;非常适合学习如何玩&#xff0c;改进技巧&#xf…

宠物经济纵深观察:口红效应显著,呈可持续发展态势

七月以来&#xff0c;全国各地陆续开启高温模式。和人一样&#xff0c;“毛孩子们”同样也难耐高温&#xff0c;由此&#xff0c;围绕猫猫狗狗的“宠物经济”迅速升温&#xff0c;宠物冰垫、宠物饮水机、宠物烘干机......一系列宠物单品掀起夏日消费热潮。 就在几天前&#xf…