OrderReallocation-HeavyTruc.../objective_calculator.py

156 lines
7.1 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 numpy as np
from data_structures import OrderData, RiskEnterpriseData, SupplierData, Config
from chromosome_utils import ChromosomeUtils
class ObjectiveCalculator:
"""目标函数计算器变更成本C + 交付延期T"""
def __init__(self, order_data: OrderData, risk_data: RiskEnterpriseData, supplier_data: SupplierData,
utils: ChromosomeUtils, config: Config):
self.order = order_data
self.risk = risk_data
self.supplier = supplier_data
self.utils = utils
self.config = config
self.split_points = np.cumsum(utils.material_enterprise_count)
def calculate_objectives(self, chromosome: np.ndarray) -> tuple[float, float]:
"""计算双目标值:(变更成本C, 交付延期T)"""
enterprise_layer, capacity_layer, quantity_layer = self.utils._split_chromosome(chromosome)
# 修复传入capacity_layer参数
C = self._calculate_change_cost(enterprise_layer, capacity_layer, quantity_layer)
T = self._calculate_tardiness(enterprise_layer, capacity_layer, quantity_layer)
return C, T
# 修复添加capacity_layer参数
def _calculate_change_cost(self, enterprise_layer: np.ndarray, capacity_layer: np.ndarray, quantity_layer: np.ndarray) -> float:
"""计算变更成本C = C1 + C2 + C3 + C4"""
C1 = 0.0 # 变更惩罚成本
C2 = 0.0 # 采购变更成本
C3 = 0.0 # 运输变更成本
C4 = 0.0 # 提前交付惩罚成本
# 原始成本(全部由风险企业生产)
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))
# 变更后成本
new_purchase_cost = 0.0
new_transport_cost = 0.0
risk_production = np.zeros(self.order.I) # 风险企业生产数量
supplier_production = np.zeros(self.order.I) # 供应商生产数量
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]
q_segment = quantity_layer[start:end]
for idx, ent in enumerate(ents):
if e_segment[idx] == 1:
q = q_segment[idx]
if ent == 0:
# 风险企业
risk_production[i] += q
new_purchase_cost += q * self.order.P0[i]
new_transport_cost += q * self.order.T0[i]
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]
start = end
# 计算C1变更惩罚成本
for i in range(self.order.I):
C1 += self.config.delta * supplier_production[i] * (self.order.P0[i] + self.order.T0[i])
# 计算C2采购变更成本
C2 = new_purchase_cost - original_purchase_cost
# 计算C3运输变更成本
C3 = new_transport_cost - original_transport_cost
# 计算C4提前交付惩罚成本
# 修复传入capacity_layer参数
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 = {}
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]
for idx, ent in enumerate(ents):
if e_segment[idx] == 1:
q = q_segment[idx]
c = c_segment[idx]
if c == 0:
production_time = 0
else:
production_time = q / c
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)
return C1 + C2 + C3 + C4
def _calculate_actual_delivery_time(self, enterprise_layer: np.ndarray, capacity_layer: np.ndarray,
quantity_layer: np.ndarray) -> float:
"""计算实际交货期:所有企业中最长的生产+运输时间"""
max_time = 0.0
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]
for idx, ent in enumerate(ents):
if e_segment[idx] == 1:
q = q_segment[idx]
c = c_segment[idx]
if c == 0:
production_time = 0
else:
production_time = q / c
# 计算运输时间
if ent == 0:
transport_time = self.risk.distance / self.order.transport_speed
else:
supplier_id = ent - 1
transport_time = self.supplier.distance[supplier_id] / self.order.transport_speed
total_time = production_time + transport_time
if total_time > max_time:
max_time = total_time
start = end
return max_time
def _calculate_tardiness(self, enterprise_layer: np.ndarray, capacity_layer: np.ndarray,
quantity_layer: np.ndarray) -> float:
"""计算交付延期T = max(0, 实际交货期 - 需求交货期)"""
actual_delivery = self._calculate_actual_delivery_time(enterprise_layer, capacity_layer, quantity_layer)
return max(0.0, actual_delivery - self.order.Dd)