OrderReallocation-HeavyTruc.../genetic_operators.py

118 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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] # 企业ID0为风险企业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