增加注释,变异实现逻辑修改,增加了企业层变异后的初始化

This commit is contained in:
Hgq 2025-12-06 11:45:30 +08:00
parent 0849790f95
commit 5d5aaae2fc
4 changed files with 105 additions and 58 deletions

View File

@ -140,8 +140,9 @@ class ChromosomeUtils:
max_total_cap = self.supplier.Cj_total_max[supplier_id] # 供应商总产能上限 max_total_cap = self.supplier.Cj_total_max[supplier_id] # 供应商总产能上限
if total_cap > max_total_cap: # 超出上限时缩放 if total_cap > max_total_cap: # 超出上限时缩放
scale = max_total_cap / total_cap # 缩放比例 scale = max_total_cap / total_cap # 缩放比例(会出现浮点)
start = 0 start = 0
# 重新遍历,按比例缩小该企业所有物料的产能
for i in range(self.I): for i in range(self.I):
end = split_points[i] end = split_points[i]
ents = self.material_optional_enterprises[i] ents = self.material_optional_enterprises[i]
@ -160,8 +161,8 @@ class ChromosomeUtils:
repaired = quantity_layer.copy() repaired = quantity_layer.copy()
split_points = np.cumsum(self.material_enterprise_count) split_points = np.cumsum(self.material_enterprise_count)
start = 0 start = 0
for i in range(self.I): for i in range(self.I): # 遍历每种物料
qi = self.order.Q[i] qi = self.order.Q[i] # 物料i的需求量
end = split_points[i] end = split_points[i]
ents = self.material_optional_enterprises[i] ents = self.material_optional_enterprises[i]
segment = repaired[start:end] segment = repaired[start:end]
@ -184,7 +185,7 @@ class ChromosomeUtils:
segment[idx] = min_q segment[idx] = min_q
elif segment[idx] > max_q: elif segment[idx] > max_q:
segment[idx] = max_q segment[idx] = max_q
# 步骤2强制总量等于需求数量(核心修复) # 步骤2强制总量等于需求数量
current_total = np.sum(segment[selected_indices]) current_total = np.sum(segment[selected_indices])
if current_total <= 0: if current_total <= 0:
weights = np.random.rand(len(selected_indices)) weights = np.random.rand(len(selected_indices))

View File

@ -91,7 +91,7 @@ class Config:
def __init__(self): def __init__(self):
# 种群参数 # 种群参数
self.pop_size = 50 # 种群大小 self.pop_size = 300 # 种群大小
self.N1_ratio = 0.2 # 优先成本的种群比例 self.N1_ratio = 0.2 # 优先成本的种群比例
self.N2_ratio = 0.2 # 优先延期的种群比例 self.N2_ratio = 0.2 # 优先延期的种群比例
self.N3_ratio = 0.3 # 强制风险企业的种群比例 self.N3_ratio = 0.3 # 强制风险企业的种群比例
@ -99,12 +99,12 @@ class Config:
# 遗传操作参数 # 遗传操作参数
self.crossover_prob = 0.8 # 交叉概率 self.crossover_prob = 0.8 # 交叉概率
self.mutation_prob = 0.3 # 变异概率 self.mutation_prob = 0.2 # 变异概率
self.max_generations = 100 # 最大进化代数 self.max_generations = 800 # 最大进化代数
# 惩罚系数 # 惩罚系数
self.delta = 1.3 # 变更惩罚系数 self.delta = 1.3 # 变更惩罚系数
self.gamma = 0.8 # 提前交付惩罚系数 self.gamma = 500 # 提前交付惩罚系数
# 早停参数 # 早停参数
self.early_stop_patience = 50 # 连续多少代无改进则早停 self.early_stop_patience = 50 # 连续多少代无改进则早停

View File

@ -1,9 +1,9 @@
import random import random
import numpy as np import numpy as np
from data_structures import Config # 配置参数类 from data_structures import Config
from chromosome_utils import ChromosomeUtils # 染色体工具类 from chromosome_utils import ChromosomeUtils
from objective_calculator import ObjectiveCalculator # 目标函数计算器 from objective_calculator import ObjectiveCalculator
from nsga2 import NSGA2 # NSGA-II算法类 from nsga2 import NSGA2
class Encoder: class Encoder:
@ -109,8 +109,8 @@ class Encoder:
if count <= 0: # 数量为0时返回空数组 if count <= 0: # 数量为0时返回空数组
return np.array([]) return np.array([])
# 生成候选解数量为count的2倍或至少20个确保有足够选择空间 # 生成候选解数量为count的3倍或至少20个确保有足够选择空间
candidate_count = max(2 * count, 20) candidate_count = max(3 * count, 20)
candidates = [self._generate_random_chromosome() for _ in range(candidate_count)] candidates = [self._generate_random_chromosome() for _ in range(candidate_count)]
# 计算候选解的目标函数值 # 计算候选解的目标函数值

View File

@ -52,67 +52,113 @@ class GeneticOperator:
# 拆分染色体为三层 # 拆分染色体为三层
enterprise_layer, capacity_layer, quantity_layer = self.utils._split_chromosome(mutated) enterprise_layer, capacity_layer, quantity_layer = self.utils._split_chromosome(mutated)
# 计算各物料的企业编码在染色体中的分割点(用于分层处理)
split_points = np.cumsum(self.utils.material_enterprise_count) split_points = np.cumsum(self.utils.material_enterprise_count)
# 1. 企业层变异0/1翻转即是否选择该企业 # ========== 第一步:记录原始企业层状态 ==========
start = 0 # 起始索引 original_enterprise_layer = enterprise_layer.copy()
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 start = 0
for i in range(self.utils.I): for i in range(self.utils.I):
end = split_points[i] end = split_points[i]
ents = self.utils.material_optional_enterprises[i] # 当前物料的可选企业列表
e_segment = enterprise_layer[start:end] # 当前物料的企业选择状态
for idx in range(start, end): for idx in range(start, end):
# 仅对被选中的企业e_segment[idx-start]==1进行变异 if random.random() < self.config.mutation_prob:
if random.random() < self.config.mutation_prob and e_segment[idx - start] == 1: enterprise_layer[idx] = 1 - enterprise_layer[idx]
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 start = end
# 修复能力层(确保不超过企业总产能约束)
capacity_layer = self.utils.repair_capacity_layer(enterprise_layer, capacity_layer)
# 3. 数量层变异(调整选中企业的生产数量) # 修复企业层
enterprise_layer = self.utils.repair_enterprise_layer(enterprise_layer)
# ========== 第三步:同步更新能力和数量层 ==========
start = 0
for i in range(self.utils.I):
end = split_points[i]
ents = self.utils.material_optional_enterprises[i]
for idx in range(start, end):
current_ent_selected = enterprise_layer[idx] # 变异后的选择状态
original_ent_selected = original_enterprise_layer[idx] # 变异前的选择状态
# 情况1企业从选中变为未选中1→0
if original_ent_selected == 1 and current_ent_selected == 0:
capacity_layer[idx] = 0 # 产能设为0
quantity_layer[idx] = 0 # 数量设为0
# 情况2企业从未选中变为选中0→1
elif original_ent_selected == 0 and current_ent_selected == 1:
ent = ents[idx - start]
# 初始化产能
if ent == 0:
max_cap = self.utils.risk.C0_i_std[i]
else:
supplier_id = ent - 1
max_cap = self.utils.supplier.Cj_i_std[supplier_id][i]
capacity_layer[idx] = random.uniform(1, max_cap)
# 初始化数量
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]
quantity_layer[idx] = random.uniform(1, max_q)
# 情况3企业保持选中1→1或保持未选中0→0
# 保持不变,后续的变异步骤会处理
start = end
# ========== 第四步:能力层变异(仅对保持选中的企业) ==========
start = 0 start = 0
for i in range(self.utils.I): for i in range(self.utils.I):
end = split_points[i] end = split_points[i]
ents = self.utils.material_optional_enterprises[i] ents = self.utils.material_optional_enterprises[i]
e_segment = enterprise_layer[start:end] e_segment = enterprise_layer[start:end]
for idx in range(start, end): for idx in range(start, end):
# 仅对被选中的企业进行变异 # 只对保持选中的企业进行变异1→1的情况
if random.random() < self.config.mutation_prob and e_segment[idx - start] == 1: if e_segment[idx - start] == 1 and original_enterprise_layer[idx] == 1:
ent = ents[idx - start] if random.random() < self.config.mutation_prob:
qi = self.utils.order.Q[i] # 当前物料的总需求 ent = ents[idx - start]
# 确定该企业的最大可分配数量 if ent == 0:
if ent == 0: max_cap = self.utils.risk.C0_i_std[i]
max_q = qi # 风险企业最多分配全部需求 else:
else: supplier_id = ent - 1
supplier_id = ent - 1 max_cap = self.utils.supplier.Cj_i_std[supplier_id][i]
max_q = self.utils.supplier.MaxOrder[supplier_id][i] # 供应商的最大供应量 capacity_layer[idx] = random.uniform(1, max_cap)
# 随机生成1到max_q之间的新数量
quantity_layer[idx] = random.uniform(1, max_q)
start = end start = end
# 修复数量层(确保总数量满足需求,且不超过企业最大供应)
# 修复能力层(考虑所有选中企业的产能)
capacity_layer = self.utils.repair_capacity_layer(enterprise_layer, capacity_layer)
# ========== 第五步:数量层变异(仅对保持选中的企业) ==========
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):
# 只对保持选中的企业进行变异1→1的情况
if e_segment[idx - start] == 1 and original_enterprise_layer[idx] == 1:
if random.random() < self.config.mutation_prob:
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]
quantity_layer[idx] = random.uniform(1, max_q)
start = end
# 修复数量层(考虑所有选中企业的分配)
quantity_layer = self.utils.repair_quantity_layer(enterprise_layer, quantity_layer) quantity_layer = self.utils.repair_quantity_layer(enterprise_layer, quantity_layer)
# 合并三层并返回 # 合并三层
mutated = self.utils._merge_chromosome(enterprise_layer, capacity_layer, quantity_layer) mutated = self.utils._merge_chromosome(enterprise_layer, capacity_layer, quantity_layer)
return mutated return mutated