From c21683083d908c43ba589eae781a971dcda5a68f Mon Sep 17 00:00:00 2001 From: Hgq <2757430053@qq.com> Date: Sat, 6 Dec 2025 19:42:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E7=9B=AE=E6=A0=87C?= =?UTF-8?q?=E7=9A=84=E8=AE=A1=E7=AE=97=E9=80=BB=E8=BE=91=EF=BC=88=E4=BD=86?= =?UTF-8?q?=E4=BB=8D=E9=9C=80=E8=A6=81=E8=A1=A5=E5=85=85=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 3 +- objective_calculator.py | 143 ++++++++++++++++++++++++---------------- 2 files changed, 86 insertions(+), 60 deletions(-) diff --git a/main.py b/main.py index 80e203b..17e9794 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,5 @@ import random import numpy as np -# 导入数据结构和工具类(根据实际项目结构调整导入路径) from data_structures import OrderData, RiskEnterpriseData, SupplierData, Config from chromosome_utils import ChromosomeUtils from objective_calculator import ObjectiveCalculator @@ -36,7 +35,7 @@ def main(): # 4. 初始化种群 print("初始化种群...") population = encoder.initialize_population() - print(f"初始化种群完成,种群大小: {population.shape if population.size > 0 else '空'}") + print(f"初始化种群完成,(种群大小,染色体长度): {population.shape if population.size > 0 else '空'}") # 若种群初始化失败(为空),直接退出 if population.size == 0: print("错误:种群初始化失败,无法继续进化") diff --git a/objective_calculator.py b/objective_calculator.py index 0bb1259..89e4447 100644 --- a/objective_calculator.py +++ b/objective_calculator.py @@ -40,26 +40,32 @@ class ObjectiveCalculator: def _calculate_change_cost(self, enterprise_layer: np.ndarray, capacity_layer: np.ndarray, quantity_layer: np.ndarray) -> float: """ - 计算变更成本 C = C1 + C2 + C3 + C4 - - C1: 变更惩罚成本(使用供应商替代风险企业的惩罚) - - C2: 采购成本差异(变更后 - 原始) - - C3: 运输成本差异(变更后 - 原始) - - C4: 提前交付惩罚成本 + 计算变更成本 C = C1 + C2 + C3 + C4(按新规则实现) + - C1: 变更惩罚成本(含α系数) + - C2: 采购成本差异(保持原有逻辑) + - C3: 运输成本差异(保持原有逻辑) + - C4: 提前交付惩罚成本(新公式) """ C1 = 0.0 C2 = 0.0 C3 = 0.0 C4 = 0.0 - # 原始成本(全部由风险企业生产时的成本) + # -------------------------- 基础数据计算(复用+新增)-------------------------- + # 1. 原始成本(全风险企业生产时的成本) original_purchase_cost = sum(self.order.Q[i] * self.order.P0[i] for i in range(self.order.I)) original_transport_cost = sum(self.order.Q[i] * self.order.T0[i] for i in range(self.order.I)) + original_total_cost = original_purchase_cost + original_transport_cost # 全风险生产总成本(用于C4) - # 变更后成本(当前解的成本) + # 2. 变更后成本(当前解的成本) new_purchase_cost = 0.0 new_transport_cost = 0.0 - risk_production = np.zeros(self.order.I) # 风险企业生产的数量 - supplier_production = np.zeros(self.order.I) # 供应商生产的数量 + + # 3. 关键变量收集(风险企业/供应商的产量、交货时间) + risk_production = np.zeros(self.order.I) # 风险企业生产的各物料数量(xi0) + supplier_production = np.zeros(self.order.I) # 供应商生产的各物料数量(Qi - xi0) + risk_delivery_times = [] # 风险企业的各物料交货时间(Di0 = 生产时间 + 运输时间) + supplier_delivery_times = {} # 供应商的各物料交货时间 {供应商ID: [Dij1, Dij2, ...]} start = 0 for i in range(self.order.I): # 遍历每种物料 @@ -67,73 +73,94 @@ class ObjectiveCalculator: ents = self.utils.material_optional_enterprises[i] # 可选企业 e_segment = enterprise_layer[start:end] # 企业选择状态 q_segment = quantity_layer[start:end] # 数量分配 + c_segment = capacity_layer[start:end] # 产能(用于计算生产时间) for idx, ent in enumerate(ents): if e_segment[idx] == 1: # 仅处理被选中的企业 q = q_segment[idx] # 分配的数量 + c = c_segment[idx] # 产能 + production_time = q / c if c != 0 else 0 # 生产时间 + if ent == 0: # 风险企业 risk_production[i] += q - new_purchase_cost += q * self.order.P0[i] # 采购成本 - new_transport_cost += q * self.order.T0[i] # 运输成本 + # 风险企业的采购/运输成本 + new_purchase_cost += q * self.order.P0[i] + new_transport_cost += q * self.order.T0[i] + # 风险企业的交货时间(Di0) + transport_time = self.risk.distance / self.order.transport_speed + risk_delivery_times.append(production_time + transport_time) else: # 供应商 supplier_id = ent - 1 supplier_production[i] += q - new_purchase_cost += q * self.supplier.P_ij[supplier_id][i] # 采购成本 - new_transport_cost += q * self.supplier.T_ij[supplier_id][i] # 运输成本 + # 供应商的采购/运输成本 + new_purchase_cost += q * self.supplier.P_ij[supplier_id][i] + new_transport_cost += q * self.supplier.T_ij[supplier_id][i] + # 供应商的交货时间(Dij) + transport_time = self.supplier.distance[supplier_id] / self.order.transport_speed + if supplier_id not in supplier_delivery_times: + supplier_delivery_times[supplier_id] = [] + supplier_delivery_times[supplier_id].append(production_time + transport_time) start = end - # 计算C1:变更惩罚成本(对供应商生产的部分收取惩罚) + # -------------------------- C1(变更惩罚成本)计算(新规则)-------------------------- + # 计算α的两个分子 + sum_xi0 = np.sum(risk_production) # 所有物料的风险企业总产量 + sum_Qi = np.sum(self.order.Q) # 所有物料的订单总需求 + if sum_Qi == 0: + ratio_risk_q = 1.0 # 避免除零 + else: + ratio_risk_q = sum_xi0 / sum_Qi + + D_original = self.order.Dd # 原定交货时间(Q1确认:需求交货期) + T_actual = self._calculate_actual_delivery_time(enterprise_layer, capacity_layer, quantity_layer) # 实际交货期(Q2确认) + if T_actual == 0: + ratio_delivery = 1.0 # 避免除零 + else: + ratio_delivery = D_original / T_actual + + # 计算α并应用约束(0, 1],≤0取1) + alpha = max(ratio_risk_q, ratio_delivery) + alpha = 1.0 if alpha > 1.0 else alpha # 超过1取1 + alpha = 1.0 if alpha <= 0.0 else alpha # ≤0取1 + + # 计算C1(按物料求和) for i in range(self.order.I): - # 惩罚系数×供应商生产数量×(风险企业的单位采购+运输成本) - C1 += self.config.delta * supplier_production[i] * (self.order.P0[i] + self.order.T0[i]) + supplier_q = supplier_production[i] # 物料i的供应商产量(Qi - xi0) + risk_unit_cost = self.order.P0[i] + self.order.T0[i] # 风险企业单位采运成本 + C1 += self.config.delta * alpha * supplier_q * risk_unit_cost - # 计算C2:采购成本差异(变更后 - 原始) - C2 = new_purchase_cost - original_purchase_cost + # -------------------------- C2、C3(保持原有逻辑)-------------------------- + C2 = new_purchase_cost - original_purchase_cost # 采购成本差异 + C3 = new_transport_cost - original_transport_cost # 运输成本差异 - # 计算C3:运输成本差异(变更后 - 原始) - C3 = new_transport_cost - original_transport_cost + # -------------------------- C4(提前交付惩罚成本)计算(新规则)-------------------------- + T_actual = self._calculate_actual_delivery_time(enterprise_layer, capacity_layer, quantity_layer) + if T_actual <= self.order.Dd: # 不延期时才计算(Q7确认) + # 步骤1:计算基础值 = 四舍五入(全风险生产总成本 / 需求交货期) + Dd = self.order.Dd + if Dd == 0: + base_value = 0.0 + else: + base_value = original_total_cost / Dd + base_value_rounded = round(base_value) # 四舍五入取整 - # 计算C4:提前交付惩罚成本(若实际交货期早于需求交货期) - actual_delivery_time = self._calculate_actual_delivery_time(enterprise_layer, capacity_layer, quantity_layer) - if actual_delivery_time < self.order.Dd: - # 计算风险企业和供应商的交货时间 - risk_delivery = [] # 风险企业的各物料交货时间 - supplier_deliveries = {} # {供应商ID: 各物料交货时间} + # 步骤2:计算风险企业提前天数 = max(0, Dd - D0)(D0为风险企业最长交货时间) + D0 = max(risk_delivery_times) if risk_delivery_times else 0.0 + risk_early_days = max(0.0, Dd - D0) - start = 0 - for i in range(self.order.I): - end = self.split_points[i] - ents = self.utils.material_optional_enterprises[i] - e_segment = enterprise_layer[start:end] - c_segment = capacity_layer[start:end] # 产能(用于计算生产时间) - q_segment = quantity_layer[start:end] # 数量 + # 步骤3:计算供应商最大提前天数 = max(0, Dd - Dj)的最大值(Dj为每个供应商的最长交货时间) + max_supplier_early = 0.0 + for supplier_id, times in supplier_delivery_times.items(): + Dj = max(times) if times else 0.0 + supplier_early = max(0.0, Dd - Dj) + if supplier_early > max_supplier_early: + max_supplier_early = supplier_early - for idx, ent in enumerate(ents): - if e_segment[idx] == 1: - q = q_segment[idx] - c = c_segment[idx] - # 生产时间 = 数量 / 产能(产能为0时按0处理) - production_time = q / c if c != 0 else 0 - - # 运输时间 = 距离 / 运输速度 - if ent == 0: - transport_time = self.risk.distance / self.order.transport_speed - risk_delivery.append(production_time + transport_time) - else: - supplier_id = ent - 1 - transport_time = self.supplier.distance[supplier_id] / self.order.transport_speed - if supplier_id not in supplier_deliveries: - supplier_deliveries[supplier_id] = [] - supplier_deliveries[supplier_id].append(production_time + transport_time) - start = end - - # 风险企业的最大交货时间(取最长) - D0 = max(risk_delivery) if risk_delivery else 0 - # 所有供应商的最大交货时间之和 - Dj_sum = sum(max(times) for times in supplier_deliveries.values()) if supplier_deliveries else 0 - # 提前交付惩罚 = 惩罚系数 ×(需求交货期 - 风险企业交货时间 + 供应商总交货时间) - C4 = self.config.gamma * ((self.order.Dd - D0) + Dj_sum) + # 步骤4:计算C4 + C4 = base_value_rounded * 0.1 * (risk_early_days + max_supplier_early) + C4 = round(C4) # 最终结果四舍五入取整 + # -------------------------- 总变更成本 -------------------------- return C1 + C2 + C3 + C4 def _calculate_actual_delivery_time(self, enterprise_layer: np.ndarray, capacity_layer: np.ndarray,