import random import numpy as np from data_structures import Config # 算法配置参数类 from chromosome_utils import ChromosomeUtils # 染色体工具类 class GeneticOperator: """遗传操作类:实现交叉和变异操作,用于产生新个体""" def __init__(self, config: Config, utils: ChromosomeUtils): """ 初始化遗传操作器 :param config: 算法配置参数(如交叉概率、变异概率等) :param utils: 染色体工具类实例(提供染色体修复等功能) """ self.config = config # 配置参数 self.utils = utils # 染色体工具 def two_point_crossover(self, parent1: np.ndarray, parent2: np.ndarray) -> tuple[np.ndarray, np.ndarray]: """ 两点交叉:在染色体上随机选择两个点,交换两点之间的基因片段 :param parent1: 父代染色体1 :param parent2: 父代染色体2 :return: 两个子代染色体(经过修复) """ length = self.utils.chromosome_length # 染色体总长度 if length < 2: # 染色体长度不足2时无法交叉,直接返回父代副本 return parent1.copy(), parent2.copy() # 随机选择两个交叉点(point1 < point2) point1 = random.randint(0, length // 2) point2 = random.randint(point1 + 1, length - 1) # 复制父代基因并交换片段 child1 = parent1.copy() child2 = parent2.copy() child1[point1:point2] = parent2[point1:point2] # 交换point1到point2之间的基因 child2[point1:point2] = parent1[point1:point2] # 修复染色体(确保满足约束条件) child1 = self.utils.repair_chromosome(child1) child2 = self.utils.repair_chromosome(child2) return child1, child2 def uniform_mutation(self, chromosome: np.ndarray) -> np.ndarray: """ 均匀变异:对染色体的三层基因(企业层、能力层、数量层)进行随机变异 :param chromosome: 待变异的染色体 :return: 变异后的染色体(经过修复) """ mutated = chromosome.copy() # 复制原始染色体,避免直接修改 # 拆分染色体为三层 enterprise_layer, capacity_layer, quantity_layer = self.utils._split_chromosome(mutated) # 计算各物料的企业编码在染色体中的分割点(用于分层处理) split_points = np.cumsum(self.utils.material_enterprise_count) # 1. 企业层变异(0/1翻转,即是否选择该企业) start = 0 # 起始索引 for i in range(self.utils.I): # 遍历每种物料 end = split_points[i] # 当前物料的企业编码结束索引 # 遍历该物料的所有可选企业 for idx in range(start, end): # 以设定的变异概率进行翻转 if random.random() < self.config.mutation_prob: enterprise_layer[idx] = 1 - enterprise_layer[idx] # 0→1或1→0 start = end # 更新起始索引为下一个物料 # 修复企业层(确保每种物料至少选择一个企业) enterprise_layer = self.utils.repair_enterprise_layer(enterprise_layer) # 2. 能力层变异(调整选中企业的产能) start = 0 for i in range(self.utils.I): end = split_points[i] ents = self.utils.material_optional_enterprises[i] # 当前物料的可选企业列表 e_segment = enterprise_layer[start:end] # 当前物料的企业选择状态 for idx in range(start, end): # 仅对被选中的企业(e_segment[idx-start]==1)进行变异 if random.random() < self.config.mutation_prob and e_segment[idx - start] == 1: ent = ents[idx - start] # 企业ID(0为风险企业,1+为供应商) # 确定该企业的最大产能 if ent == 0: max_cap = self.utils.risk.C0_i_std[i] # 风险企业的单物料产能 else: supplier_id = ent - 1 # 供应商索引(转换为0基) max_cap = self.utils.supplier.Cj_i_std[supplier_id][i] # 供应商的单物料产能 # 随机生成1到max_cap之间的新产能 capacity_layer[idx] = random.uniform(1, max_cap) start = end # 修复能力层(确保不超过企业总产能约束) capacity_layer = self.utils.repair_capacity_layer(enterprise_layer, capacity_layer) # 3. 数量层变异(调整选中企业的生产数量) start = 0 for i in range(self.utils.I): end = split_points[i] ents = self.utils.material_optional_enterprises[i] e_segment = enterprise_layer[start:end] for idx in range(start, end): # 仅对被选中的企业进行变异 if random.random() < self.config.mutation_prob and e_segment[idx - start] == 1: ent = ents[idx - start] qi = self.utils.order.Q[i] # 当前物料的总需求 # 确定该企业的最大可分配数量 if ent == 0: max_q = qi # 风险企业最多分配全部需求 else: supplier_id = ent - 1 max_q = self.utils.supplier.MaxOrder[supplier_id][i] # 供应商的最大供应量 # 随机生成1到max_q之间的新数量 quantity_layer[idx] = random.uniform(1, max_q) start = end # 修复数量层(确保总数量满足需求,且不超过企业最大供应) quantity_layer = self.utils.repair_quantity_layer(enterprise_layer, quantity_layer) # 合并三层并返回 mutated = self.utils._merge_chromosome(enterprise_layer, capacity_layer, quantity_layer) return mutated