基于深度学习进行运输系统优化

该系统实现了一个运输优化方案,主要包含以下功能:

  • 生成运输任务和车辆的随机数据集
  • 基于线性规划的数学模型求解最优分配方案
  • 基于强化学习的深度学习模型求解分配方案
  • 对比两种方案的性能指标并可视化结果

系统使用 Python 实现,主要依赖以下库:

  • NumPy 和 Pandas:数据处理和分析
  • PyTorch:构建和训练强化学习模型
  • PuLP:构建和求解数学优化模型
  • Matplotlib:可视化结果
  • tqdm:显示训练进度

1. 导入库

python

复制

下载

复制代码
import numpy as np               # 数值计算
import pandas as pd              # 数据处理(虽然代码中没有直接使用)
import matplotlib.pyplot as plt  # 数据可视化
from pulp import LpMinimize, LpProblem, LpVariable, lpSum, PULP_CBC_CMD  # 线性规划建模
import torch                     # 深度学习框架
import torch.nn as nn            # 神经网络模块
import torch.optim as optim      # 优化器
from torch.utils.data import Dataset, DataLoader  # 数据加载
from sklearn.preprocessing import StandardScaler  # 数据标准化(未直接使用)
import random                    # 随机数生成
import time                      # 时间测量
from tqdm import tqdm            # 进度条显示
import warnings                  # 警告处理
warnings.filterwarnings('ignore')# 忽略警告

2. 设置随机种子

python

复制

下载

复制代码
np.random.seed(42)      # 确保numpy的随机性可复现
torch.manual_seed(42)  # 确保PyTorch的随机性可复现
random.seed(42)        # 确保Python内置随机模块的可复现性

3. 运输数据集类

python

复制

下载

复制代码
class TransportationDataset(Dataset):
    def __init__(self, num_samples, num_tasks, num_vehicles):
        self.num_samples = num_samples    # 样本数量
        self.num_tasks = num_tasks        # 任务数量
        self.num_vehicles = num_vehicles  # 车辆数量
        self.samples = []                 # 存储样本的列表
        
        for _ in range(num_samples):
            # 生成任务坐标(0-100范围内的二维点)
            task_locations = np.random.rand(num_tasks, 2) * 100
            # 生成任务货物量(1-20之间的整数)
            task_quantities = np.random.randint(1, 20, size=num_tasks)
            
            # 生成车辆容量(50-150之间的整数)
            vehicle_capacities = np.random.randint(50, 150, size=num_vehicles)
            # 生成车辆速度矩阵(30-60之间的均匀分布)
            vehicle_speeds = np.random.uniform(30, 60, size=(num_tasks, num_vehicles))
            
            # 计算任务间的欧氏距离矩阵
            distance_matrix = np.zeros((num_tasks, num_tasks))
            for i in range(num_tasks):
                for k in range(num_tasks):
                    if i != k:
                        distance_matrix[i, k] = np.sqrt(
                            (task_locations[i, 0] - task_locations[k, 0])**2 + 
                            (task_locations[i, 1] - task_locations[k, 1])**2
                        )
            
            # 计算运输成本矩阵(平均距离 × 货物量 × 0.1)
            cost_matrix = np.zeros((num_tasks, num_vehicles))
            for i in range(num_tasks):
                for j in range(num_vehicles):
                    cost_matrix[i, j] = distance_matrix[i, :].mean() * task_quantities[i] * 0.1
            
            # 计算行驶时间矩阵(距离 / 速度)
            time_matrix = np.zeros((num_tasks, num_tasks, num_vehicles))
            for i in range(num_tasks):
                for k in range(num_tasks):
                    if i != k:
                        for j in range(num_vehicles):
                            time_matrix[i, k, j] = distance_matrix[i, k] / vehicle_speeds[i, j]
            
            # 构建特征字典
            features = {
                'task_quantities': task_quantities,
                'vehicle_capacities': vehicle_capacities,
                'distance_matrix': distance_matrix,
                'cost_matrix': cost_matrix,
                'time_matrix': time_matrix,
                'vehicle_speeds': vehicle_speeds
            }
            self.samples.append(features)
    
    def __len__(self):
        return self.num_samples  # 返回数据集大小
    
    def __getitem__(self, idx):
        return self.samples[idx]  # 获取单个样本

4. 数学模型类(线性规划)

python

复制

下载

复制代码
class MathematicalModel:
    def __init__(self, task_quantities, vehicle_capacities, cost_matrix, time_matrix, distance_matrix):
        # 初始化参数
        self.num_tasks = len(task_quantities)
        self.num_vehicles = len(vehicle_capacities)
        self.task_quantities = task_quantities
        self.vehicle_capacities = vehicle_capacities
        self.cost_matrix = cost_matrix
        self.time_matrix = time_matrix
        self.distance_matrix = distance_matrix
        
        # 创建PuLP问题实例(最小化目标)
        self.problem = LpProblem("Transportation_Optimization", LpMinimize)
        
        # 定义决策变量
        # x[i][j]: 任务i是否分配给车辆j(二进制变量)
        self.x = [[LpVariable(f"x_{i}_{j}", cat='Binary') 
                  for j in range(self.num_vehicles)] 
                 for i in range(self.num_tasks)]
        # y[i][j][k]: 车辆j是否从任务i行驶到任务k(二进制变量)
        self.y = [[[LpVariable(f"y_{i}_{j}_{k}", cat='Binary') 
                  for k in range(self.num_tasks)] 
                 for j in range(self.num_vehicles)] 
                for i in range(self.num_tasks)]
        
        self.define_objective()  # 定义目标函数
        self.add_constraints()   # 添加约束条件
    
    def define_objective(self):
        # 总运输成本 = sum(成本矩阵 * 分配变量)
        total_cost = lpSum(self.cost_matrix[i][j] * self.x[i][j] 
                          for i in range(self.num_tasks) 
                          for j in range(self.num_vehicles))
        # 总运输时间 = sum(时间矩阵 * 路径变量)
        total_time = lpSum(self.time_matrix[i][k][j] * self.y[i][j][k] 
                          for i in range(self.num_tasks) 
                          for k in range(self.num_tasks) 
                          for j in range(self.num_vehicles) 
                          if i != k)
        # 目标函数:成本和时间加权和
        self.problem += total_cost + total_time
    
    def add_constraints(self):
        # 每个任务必须分配给一辆车
        for i in range(self.num_tasks):
            self.problem += lpSum(self.x[i][j] for j in range(self.num_vehicles)) == 1
        
        # 车辆容量约束
        for j in range(self.num_vehicles):
            self.problem += lpSum(self.task_quantities[i] * self.x[i][j] 
                                 for i in range(self.num_tasks)) <= self.vehicle_capacities[j]
        
        # 路径连续性约束
        for j in range(self.num_vehicles):
            for k in range(self.num_tasks):
                # 进入任务k的路径数等于任务k的分配状态
                self.problem += lpSum(self.y[i][j][k] for i in range(self.num_tasks)) == self.x[k][j]
            for i in range(self.num_tasks):
                # 离开任务i的路径数等于任务i的分配状态
                self.problem += lpSum(self.y[i][j][k] for k in range(self.num_tasks)) == self.x[i][j]
    
    def solve(self):
        # 使用CBC求解器(禁用日志,时间限制300秒)
        self.problem.solve(PULP_CBC_CMD(msg=0, timeLimit=300))
        
        if self.problem.status == 1:  # 最优解找到
            # 提取解决方案
            solution_x = np.zeros((self.num_tasks, self.num_vehicles))
            solution_y = np.zeros((self.num_tasks, self.num_vehicles, self.num_tasks))
            
            # 填充分配变量
            for i in range(self.num_tasks):
                for j in range(self.num_vehicles):
                    solution_x[i, j] = self.x[i][j].value()
            
            # 填充路径变量
            for i in range(self.num_tasks):
                for j in range(self.num_vehicles):
                    for k in range(self.num_tasks):
                        solution_y[i, j, k] = self.y[i][j][k].value()
            
            # 计算各项指标
            total_cost = sum(self.cost_matrix[i][j] * solution_x[i, j] 
                            for i in range(self.num_tasks) 
                            for j in range(self.num_vehicles))
            total_time = sum(self.time_matrix[i][k][j] * solution_y[i, j, k] 
                            for i in range(self.num_tasks) 
                            for k in range(self.num_tasks) 
                            for j in range(self.num_vehicles) 
                            if i != k)
            vehicle_utilization = []
            for j in range(self.num_vehicles):
                used_capacity = sum(self.task_quantities[i] * solution_x[i, j] 
                                   for i in range(self.num_tasks))
                vehicle_utilization.append(used_capacity / self.vehicle_capacities[j] * 100)
            
            return {
                'status': 'Optimal',
                'total_cost': total_cost,
                'total_time': total_time,
                'vehicle_utilization': np.mean(vehicle_utilization),
                'solution_x': solution_x,
                'solution_y': solution_y
            }
        else:
            return {
                'status': 'Not Optimal',
                'total_cost': None,
                'total_time': None,
                'vehicle_utilization': None,
                'solution_x': None,
                'solution_y': None
            }

(由于篇幅限制,后续部分将简要说明关键点)

5. 强化学习模型

  • ReinforcementLearningModel类:定义神经网络结构,包含特征提取层、策略网络(输出动作概率)和价值网络(评估状态价值)。

  • RLAgent类:管理RL训练过程,包括动作选择(基于概率分布)、经验回放和策略更新(使用策略梯度方法)。

6. 辅助函数

  • evaluate_solution:计算解决方案的总成本、时间和车辆利用率。

  • train_rl_agent:训练RL代理,通过与环境交互收集经验并更新网络参数。

7. 模型比较与可视化

  • compare_models:在多个样本上比较数学规划和RL模型的性能。

  • visualize_results:生成对比图表,展示成本、时间、利用率等指标。

8. 主程序

  • 设置参数并执行模型比较,最终可视化结果。

关键注意事项

  1. 数学模型的复杂性:当任务和车辆数量增加时,线性规划模型可能变得难以求解(组合爆炸问题)。

  2. 强化学习的状态表示:当前状态向量可能无法充分捕捉问题的空间特征,考虑使用图神经网络可能更合适。

  3. 奖励函数设计:当前的奖励函数较为简单,可能需要更精细的设计来引导学习过程。

  4. 路径连续性处理:代码中对路径变量y的处理较为简化,实际车辆路径规划可能需要考虑更多约束(如时间窗口等)。

完整代码

复制代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pulp import LpMinimize, LpProblem, LpVariable, lpSum, PULP_CBC_CMD
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from sklearn.preprocessing import StandardScaler
import random
import time
from tqdm import tqdm
import warnings
warnings.filterwarnings('ignore')

# 设置随机种子确保结果可复现
np.random.seed(42)
torch.manual_seed(42)
random.seed(42)

class TransportationDataset(Dataset):
    def __init__(self, num_samples, num_tasks, num_vehicles):
        self.num_samples = num_samples
        self.num_tasks = num_tasks
        self.num_vehicles = num_vehicles
        self.samples = []
        
        for _ in range(num_samples):
            # 生成任务数据
            task_locations = np.random.rand(num_tasks, 2) * 100  # 任务坐标
            task_quantities = np.random.randint(1, 20, size=num_tasks)  # 任务货物量
            
            # 生成车辆数据
            vehicle_capacities = np.random.randint(50, 150, size=num_vehicles)  # 车辆容量
            vehicle_speeds = np.random.uniform(30, 60, size=(num_tasks, num_vehicles))  # 车辆在各路段的速度
            
            # 计算距离矩阵
            distance_matrix = np.zeros((num_tasks, num_tasks))
            for i in range(num_tasks):
                for k in range(num_tasks):
                    if i != k:
                        distance_matrix[i, k] = np.sqrt(
                            (task_locations[i, 0] - task_locations[k, 0])**2 + 
                            (task_locations[i, 1] - task_locations[k, 1])**2
                        )
            
            # 计算运输成本矩阵 (简化:成本与距离和货物量相关)
            cost_matrix = np.zeros((num_tasks, num_vehicles))
            for i in range(num_tasks):
                for j in range(num_vehicles):
                    cost_matrix[i, j] = distance_matrix[i, :].mean() * task_quantities[i] * 0.1
            
            # 计算行驶时间矩阵
            time_matrix = np.zeros((num_tasks, num_tasks, num_vehicles))
            for i in range(num_tasks):
                for k in range(num_tasks):
                    if i != k:
                        for j in range(num_vehicles):
                            time_matrix[i, k, j] = distance_matrix[i, k] / vehicle_speeds[i, j]
            
            # 构建样本特征
            features = {
                'task_quantities': task_quantities,
                'vehicle_capacities': vehicle_capacities,
                'distance_matrix': distance_matrix,
                'cost_matrix': cost_matrix,
                'time_matrix': time_matrix,
                'vehicle_speeds': vehicle_speeds
            }
            
            self.samples.append(features)
    
    def __len__(self):
        return self.num_samples
    
    def __getitem__(self, idx):
        return self.samples[idx]

class MathematicalModel:
    def __init__(self, task_quantities, vehicle_capacities, cost_matrix, time_matrix, distance_matrix):
        self.num_tasks = len(task_quantities)
        self.num_vehicles = len(vehicle_capacities)
        self.task_quantities = task_quantities
        self.vehicle_capacities = vehicle_capacities
        self.cost_matrix = cost_matrix
        self.time_matrix = time_matrix
        self.distance_matrix = distance_matrix
        
        # 创建问题
        self.problem = LpProblem("Transportation_Optimization", LpMinimize)
        
        # 定义决策变量
        self.x = [[LpVariable(f"x_{i}_{j}", cat='Binary') 
                  for j in range(self.num_vehicles)] 
                 for i in range(self.num_tasks)]
        
        self.y = [[[LpVariable(f"y_{i}_{j}_{k}", cat='Binary') 
                  for k in range(self.num_tasks)] 
                 for j in range(self.num_vehicles)] 
                for i in range(self.num_tasks)]
        
        # 定义目标函数
        self.define_objective()
        
        # 添加约束条件
        self.add_constraints()
    
    def define_objective(self):
        # 总运输成本
        total_cost = lpSum(self.cost_matrix[i][j] * self.x[i][j] 
                          for i in range(self.num_tasks) 
                          for j in range(self.num_vehicles))
        
        # 总运输时间
        total_time = lpSum(self.time_matrix[i][k][j] * self.y[i][j][k] 
                          for i in range(self.num_tasks) 
                          for k in range(self.num_tasks) 
                          for j in range(self.num_vehicles) 
                          if i != k)
        
        # 目标函数:最小化总成本和总时间的加权和
        self.problem += total_cost + total_time
    
    def add_constraints(self):
        # 任务分配约束:每个任务必须由一辆车承担
        for i in range(self.num_tasks):
            self.problem += lpSum(self.x[i][j] for j in range(self.num_vehicles)) == 1
        
        # 车辆容量约束:每辆车承担的任务货物总量不能超过其容量
        for j in range(self.num_vehicles):
            self.problem += lpSum(self.task_quantities[i] * self.x[i][j] 
                                 for i in range(self.num_tasks)) <= self.vehicle_capacities[j]
        
        # 路径连续性约束
        for j in range(self.num_vehicles):
            for k in range(self.num_tasks):
                self.problem += lpSum(self.y[i][j][k] for i in range(self.num_tasks)) == self.x[k][j]
            
            for i in range(self.num_tasks):
                self.problem += lpSum(self.y[i][j][k] for k in range(self.num_tasks)) == self.x[i][j]
    
    def solve(self):
        # 使用CBC求解器求解问题
        self.problem.solve(PULP_CBC_CMD(msg=0, timeLimit=300))
        
        # 检查求解状态
        if self.problem.status == 1:  # Optimal
            # 提取解决方案
            solution_x = np.zeros((self.num_tasks, self.num_vehicles))
            solution_y = np.zeros((self.num_tasks, self.num_vehicles, self.num_tasks))
            
            for i in range(self.num_tasks):
                for j in range(self.num_vehicles):
                    solution_x[i, j] = self.x[i][j].value()
            
            for i in range(self.num_tasks):
                for j in range(self.num_vehicles):
                    for k in range(self.num_tasks):
                        solution_y[i, j, k] = self.y[i][j][k].value()
            
            # 计算总运输成本和总运输时间
            total_cost = sum(self.cost_matrix[i][j] * solution_x[i, j] 
                            for i in range(self.num_tasks) 
                            for j in range(self.num_vehicles))
            
            total_time = sum(self.time_matrix[i][k][j] * solution_y[i, j, k] 
                            for i in range(self.num_tasks) 
                            for k in range(self.num_tasks) 
                            for j in range(self.num_vehicles) 
                            if i != k)
            
            # 计算车辆利用率
            vehicle_utilization = []
            for j in range(self.num_vehicles):
                used_capacity = sum(self.task_quantities[i] * solution_x[i, j] 
                                   for i in range(self.num_tasks))
                vehicle_utilization.append(used_capacity / self.vehicle_capacities[j] * 100)
            
            return {
                'status': 'Optimal',
                'total_cost': total_cost,
                'total_time': total_time,
                'vehicle_utilization': np.mean(vehicle_utilization),
                'solution_x': solution_x,
                'solution_y': solution_y
            }
        else:
            return {
                'status': 'Not Optimal',
                'total_cost': None,
                'total_time': None,
                'vehicle_utilization': None,
                'solution_x': None,
                'solution_y': None
            }

class ReinforcementLearningModel(nn.Module):
    def __init__(self, num_tasks, num_vehicles):
        super(ReinforcementLearningModel, self).__init__()
        self.num_tasks = num_tasks
        self.num_vehicles = num_vehicles
        
        # 特征提取网络
        self.feature_extractor = nn.Sequential(
            nn.Linear(num_tasks + num_vehicles + num_tasks * num_vehicles, 128),
            nn.ReLU(),
            nn.Linear(128, 256),
            nn.ReLU()
        )
        
        # 策略网络 - 任务分配
        self.policy_network = nn.Sequential(
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, num_tasks * num_vehicles),
        )
        
        # 价值网络
        self.value_network = nn.Sequential(
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, 1)
        )
    
    def forward(self, state):
        # 提取特征
        features = self.feature_extractor(state)
        
        # 计算动作logits (移除softmax,改为在采样时使用)
        action_logits = self.policy_network(features)
        
        # 计算状态价值
        state_value = self.value_network(features)
        
        return action_logits, state_value

class RLAgent:
    def __init__(self, num_tasks, num_vehicles):
        self.model = ReinforcementLearningModel(num_tasks, num_vehicles)
        self.optimizer = optim.Adam(self.model.parameters(), lr=0.001)
        self.gamma = 0.99  # 折扣因子
        
        # 存储轨迹
        self.states = []
        self.actions = []
        self.rewards = []
    
    def get_action(self, state):
        state_tensor = torch.FloatTensor(state)
        action_logits, _ = self.model(state_tensor)
        
        # 使用logits计算概率分布
        if len(action_logits.shape) == 1:  # 处理单个样本
            action_probs = torch.softmax(action_logits, dim=0)
        else:  # 处理批量样本
            action_probs = torch.softmax(action_logits, dim=1)
        
        # 从概率分布中采样动作
        action = torch.multinomial(action_probs, 1).item()
        
        # 将动作索引转换为任务-车辆分配
        task_idx = action // self.model.num_vehicles
        vehicle_idx = action % self.model.num_vehicles
        
        return task_idx, vehicle_idx, action_probs[0, action].item() if len(action_probs.shape) > 1 else action_probs[action].item()
    
    def store_transition(self, state, action, reward):
        self.states.append(state)
        self.actions.append(action)
        self.rewards.append(reward)
    
    def update(self):
        if not self.states:
            return
        
        # 计算累积奖励
        returns = []
        R = 0
        for r in reversed(self.rewards):
            R = r + self.gamma * R
            returns.insert(0, R)
        
        returns = torch.FloatTensor(returns)
        
        # 标准化回报
        returns = (returns - returns.mean()) / (returns.std() + 1e-8)
        
        # 计算损失
        states_tensor = torch.FloatTensor(self.states)
        actions_tensor = torch.LongTensor(self.actions)
        
        action_logits, state_values = self.model(states_tensor)
        state_values = state_values.squeeze()
        
        # 使用log_softmax计算策略梯度损失,提高数值稳定性
        if len(action_logits.shape) == 1:  # 处理单个样本
            log_probs = torch.nn.functional.log_softmax(action_logits, dim=0)
            selected_log_probs = log_probs[actions_tensor]
        else:  # 处理批量样本
            log_probs = torch.nn.functional.log_softmax(action_logits, dim=1)
            selected_log_probs = log_probs.gather(1, actions_tensor.unsqueeze(1)).squeeze()
        
        # 计算策略梯度损失
        advantage = returns - state_values.detach()
        policy_loss = -(selected_log_probs * advantage).mean()
        
        # 计算价值损失
        value_loss = nn.MSELoss()(state_values, returns)
        
        # 总损失
        loss = policy_loss + 0.5 * value_loss
        
        # 优化模型
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()
        
        # 清空轨迹
        self.states = []
        self.actions = []
        self.rewards = []
        
        return loss.item()

def evaluate_solution(task_quantities, vehicle_capacities, cost_matrix, time_matrix, solution_x, solution_y):
    """评估解决方案的性能指标"""
    num_tasks = len(task_quantities)
    num_vehicles = len(vehicle_capacities)
    
    # 计算总运输成本
    total_cost = sum(cost_matrix[i][j] * solution_x[i, j] 
                    for i in range(num_tasks) 
                    for j in range(num_vehicles))
    
    # 计算总运输时间
    total_time = sum(time_matrix[i][k][j] * solution_y[i, j, k] 
                    for i in range(num_tasks) 
                    for k in range(num_tasks) 
                    for j in range(num_vehicles) 
                    if i != k)
    
    # 计算车辆利用率
    vehicle_utilization = []
    for j in range(num_vehicles):
        used_capacity = sum(task_quantities[i] * solution_x[i, j] 
                          for i in range(num_tasks))
        vehicle_utilization.append(used_capacity / vehicle_capacities[j] * 100)
    
    return {
        'total_cost': total_cost,
        'total_time': total_time,
        'vehicle_utilization': np.mean(vehicle_utilization)
    }

def train_rl_agent(dataset, num_tasks, num_vehicles, num_episodes=100):
    """训练强化学习代理"""
    agent = RLAgent(num_tasks, num_vehicles)
    rewards_history = []
    
    for episode in tqdm(range(num_episodes), desc="Training RL Agent"):
        # 随机选择一个样本
        sample_idx = np.random.randint(len(dataset))
        sample = dataset[sample_idx]
        
        # 初始化状态
        state = np.concatenate([
            sample['task_quantities'] / sample['task_quantities'].max(),
            sample['vehicle_capacities'] / sample['vehicle_capacities'].max(),
            sample['cost_matrix'].flatten() / sample['cost_matrix'].max()
        ])
        
        # 初始化任务分配
        task_assignment = np.zeros((num_tasks, num_vehicles))
        vehicle_load = np.zeros(num_vehicles)
        
        episode_reward = 0
        done = False
        step = 0
        
        while not done and step < num_tasks:
            # 获取动作
            task_idx, vehicle_idx, prob = agent.get_action(state)
            
            # 如果任务已分配或车辆容量不足,则跳过
            if task_assignment[task_idx].sum() > 0 or \
               vehicle_load[vehicle_idx] + sample['task_quantities'][task_idx] > sample['vehicle_capacities'][vehicle_idx]:
                reward = -10  # 惩罚无效动作
            else:
                # 执行动作
                task_assignment[task_idx, vehicle_idx] = 1
                vehicle_load[vehicle_idx] += sample['task_quantities'][task_idx]
                
                # 计算奖励 (简化:基于当前成本和容量利用率)
                current_cost = sum(sample['cost_matrix'][i][j] * task_assignment[i, j] 
                                  for i in range(num_tasks) 
                                  for j in range(num_vehicles))
                
                capacity_utilization = sum(vehicle_load[j] / sample['vehicle_capacities'][j] 
                                         for j in range(num_vehicles)) / num_vehicles
                
                reward = -current_cost + capacity_utilization * 10
            
            # 更新状态
            state = np.concatenate([
                sample['task_quantities'] / sample['task_quantities'].max(),
                vehicle_load / sample['vehicle_capacities'].max(),
                sample['cost_matrix'].flatten() / sample['cost_matrix'].max()
            ])
            
            # 存储转换
            action_idx = task_idx * num_vehicles + vehicle_idx
            agent.store_transition(state, action_idx, reward)
            
            episode_reward += reward
            step += 1
            
            # 检查是否所有任务都已分配
            if task_assignment.sum() == num_tasks:
                done = True
        
        # 计算最终奖励 (基于总成本和时间)
        if task_assignment.sum() == num_tasks:
            # 构建solution_y (简化:假设车辆按任务分配顺序行驶)
            solution_y = np.zeros((num_tasks, num_vehicles, num_tasks))
            for j in range(num_vehicles):
                tasks = np.where(task_assignment[:, j] == 1)[0]
                if len(tasks) > 1:
                    for i in range(len(tasks) - 1):
                        solution_y[tasks[i], j, tasks[i+1]] = 1
            
            # 评估解决方案
            metrics = evaluate_solution(
                sample['task_quantities'], 
                sample['vehicle_capacities'], 
                sample['cost_matrix'], 
                sample['time_matrix'], 
                task_assignment, 
                solution_y
            )
            
            # 最终奖励:基于总成本和时间的负值
            final_reward = -metrics['total_cost'] - metrics['total_time']
            agent.store_transition(state, 0, final_reward)
            episode_reward += final_reward
        
        # 更新模型
        loss = agent.update()
        rewards_history.append(episode_reward)
        
        if (episode + 1) % 10 == 0:
            print(f"Episode {episode+1}/{num_episodes}, Avg Reward: {np.mean(rewards_history[-10:]):.2f}")
    
    return agent, rewards_history

def compare_models(num_samples=10, num_tasks=10, num_vehicles=5):
    """比较数学模型和深度学习模型的性能"""
    # 创建数据集
    dataset = TransportationDataset(num_samples, num_tasks, num_vehicles)
    
    # 训练强化学习模型
    print("训练强化学习模型...")
    rl_agent, _ = train_rl_agent(dataset, num_tasks, num_vehicles, num_episodes=50)
    
    # 比较性能
    results = []
    
    for i in range(num_samples):
        print(f"\n处理样本 {i+1}/{num_samples}...")
        sample = dataset[i]
        
        # 使用数学模型求解
        print("运行数学模型...")
        start_time = time.time()
        math_model = MathematicalModel(
            sample['task_quantities'],
            sample['vehicle_capacities'],
            sample['cost_matrix'],
            sample['time_matrix'],
            sample['distance_matrix']
        )
        math_result = math_model.solve()
        math_time = time.time() - start_time
        
        # 使用强化学习模型求解
        print("运行强化学习模型...")
        start_time = time.time()
        
        # 初始化状态
        state = np.concatenate([
            sample['task_quantities'] / sample['task_quantities'].max(),
            sample['vehicle_capacities'] / sample['vehicle_capacities'].max(),
            sample['cost_matrix'].flatten() / sample['cost_matrix'].max()
        ])
        
        # 初始化任务分配
        task_assignment = np.zeros((num_tasks, num_vehicles))
        vehicle_load = np.zeros(num_vehicles)
        
        # 执行RL决策
        for _ in range(num_tasks):
            task_idx, vehicle_idx, _ = rl_agent.get_action(state)
            
            # 如果任务已分配或车辆容量不足,则寻找下一个最佳动作
            if task_assignment[task_idx].sum() > 0 or \
               vehicle_load[vehicle_idx] + sample['task_quantities'][task_idx] > sample['vehicle_capacities'][vehicle_idx]:
                
                # 获取所有可能的动作及其概率
                state_tensor = torch.FloatTensor(state)
                action_logits, _ = rl_agent.model(state_tensor)
                
                # 使用log_softmax计算概率,提高数值稳定性
                if len(action_logits.shape) == 1:
                    action_probs = torch.softmax(action_logits, dim=0)
                    # 对于单样本,argsort返回一维数组
                    sorted_actions = np.argsort(-action_probs.detach().numpy())
                else:
                    action_probs = torch.softmax(action_logits, dim=1)
                    # 对于批量样本,argsort返回二维数组
                    sorted_actions = np.argsort(-action_probs.detach().numpy())
                
                # 确保sorted_actions是一维数组
                if len(sorted_actions.shape) > 1:
                    sorted_actions = sorted_actions[0]
                
                # 尝试下一个最佳动作
                for action_idx in sorted_actions:
                    task_idx = action_idx // num_vehicles
                    vehicle_idx = action_idx % num_vehicles
                    
                    if task_assignment[task_idx].sum() == 0 and \
                       vehicle_load[vehicle_idx] + sample['task_quantities'][task_idx] <= sample['vehicle_capacities'][vehicle_idx]:
                        break
            
            # 执行动作
            task_assignment[task_idx, vehicle_idx] = 1
            vehicle_load[vehicle_idx] += sample['task_quantities'][task_idx]
            
            # 更新状态
            state = np.concatenate([
                sample['task_quantities'] / sample['task_quantities'].max(),
                vehicle_load / sample['vehicle_capacities'].max(),
                sample['cost_matrix'].flatten() / sample['cost_matrix'].max()
            ])
        
        # 构建solution_y (简化:假设车辆按任务分配顺序行驶)
        solution_y = np.zeros((num_tasks, num_vehicles, num_tasks))
        for j in range(num_vehicles):
            tasks = np.where(task_assignment[:, j] == 1)[0]
            if len(tasks) > 1:
                for i in range(len(tasks) - 1):
                    solution_y[tasks[i], j, tasks[i+1]] = 1
        
        # 评估RL解决方案
        rl_metrics = evaluate_solution(
            sample['task_quantities'], 
            sample['vehicle_capacities'], 
            sample['cost_matrix'], 
            sample['time_matrix'], 
            task_assignment, 
            solution_y
        )
        rl_time = time.time() - start_time
        
        # 计算改进百分比
        cost_improvement = ((math_result['total_cost'] - rl_metrics['total_cost']) / math_result['total_cost'] * 100) if math_result['total_cost'] else 0
        time_improvement = ((math_result['total_time'] - rl_metrics['total_time']) / math_result['total_time'] * 100) if math_result['total_time'] else 0
        utilization_improvement = (rl_metrics['vehicle_utilization'] - math_result['vehicle_utilization']) if math_result['vehicle_utilization'] else 0
        
        results.append({
            'sample': i,
            'math_cost': math_result['total_cost'],
            'math_time': math_result['total_time'],
            'math_utilization': math_result['vehicle_utilization'],
            'math_solve_time': math_time,
            'rl_cost': rl_metrics['total_cost'],
            'rl_time': rl_metrics['total_time'],
            'rl_utilization': rl_metrics['vehicle_utilization'],
            'rl_solve_time': rl_time,
            'cost_improvement': cost_improvement,
            'time_improvement': time_improvement,
            'utilization_improvement': utilization_improvement
        })
    
    # 计算平均改进
    avg_results = {
        'cost_improvement': np.mean([r['cost_improvement'] for r in results]),
        'time_improvement': np.mean([r['time_improvement'] for r in results]),
        'utilization_improvement': np.mean([r['utilization_improvement'] for r in results]),
        'math_avg_cost': np.mean([r['math_cost'] for r in results]),
        'math_avg_time': np.mean([r['math_time'] for r in results]),
        'math_avg_utilization': np.mean([r['math_utilization'] for r in results]),
        'rl_avg_cost': np.mean([r['rl_cost'] for r in results]),
        'rl_avg_time': np.mean([r['rl_time'] for r in results]),
        'rl_avg_utilization': np.mean([r['rl_utilization'] for r in results]),
        'math_avg_solve_time': np.mean([r['math_solve_time'] for r in results]),
        'rl_avg_solve_time': np.mean([r['rl_solve_time'] for r in results])
    }
    
    return results, avg_results

def visualize_results(results, avg_results):
    """可视化比较结果"""
    plt.figure(figsize=(15, 10))
    
    # 比较总运输成本
    plt.subplot(2, 2, 1)
    samples = range(len(results))
    math_costs = [r['math_cost'] for r in results]
    rl_costs = [r['rl_cost'] for r in results]
    
    plt.bar([s - 0.2 for s in samples], math_costs, width=0.4, label='数学模型')
    plt.bar([s + 0.2 for s in samples], rl_costs, width=0.4, label='深度学习模型')
    plt.xticks(samples)
    plt.xlabel('样本')
    plt.ylabel('总运输成本')
    plt.title('总运输成本比较')
    plt.legend()
    
    # 比较总运输时间
    plt.subplot(2, 2, 2)
    math_times = [r['math_time'] for r in results]
    rl_times = [r['rl_time'] for r in results]
    
    plt.bar([s - 0.2 for s in samples], math_times, width=0.4, label='数学模型')
    plt.bar([s + 0.2 for s in samples], rl_times, width=0.4, label='深度学习模型')
    plt.xticks(samples)
    plt.xlabel('样本')
    plt.ylabel('总运输时间')
    plt.title('总运输时间比较')
    plt.legend()
    
    # 比较车辆利用率
    plt.subplot(2, 2, 3)
    math_utils = [r['math_utilization'] for r in results]
    rl_utils = [r['rl_utilization'] for r in results]
    
    plt.bar([s - 0.2 for s in samples], math_utils, width=0.4, label='数学模型')
    plt.bar([s + 0.2 for s in samples], rl_utils, width=0.4, label='深度学习模型')
    plt.xticks(samples)
    plt.xlabel('样本')
    plt.ylabel('车辆利用率 (%)')
    plt.title('车辆利用率比较')
    plt.legend()
    
    # 显示平均改进
    plt.subplot(2, 2, 4)
    metrics = ['成本降低', '时间缩短', '利用率提升']
    improvements = [avg_results['cost_improvement'], avg_results['time_improvement'], avg_results['utilization_improvement']]
    
    plt.bar(metrics, improvements, color='skyblue')
    for i, v in enumerate(improvements):
        plt.text(i, v + 0.5, f'{v:.2f}%', ha='center')
    plt.ylabel('改进百分比 (%)')
    plt.title('深度学习模型相对于数学模型的平均改进')
    
    plt.tight_layout()
    plt.savefig('comparison_results.png')
    plt.show()
    
    # 打印平均结果
    print("\n===== 平均结果 =====")
    print(f"数学模型 - 平均成本: {avg_results['math_avg_cost']:.2f}, 平均时间: {avg_results['math_avg_time']:.2f}, 平均利用率: {avg_results['math_avg_utilization']:.2f}%")
    print(f"深度学习模型 - 平均成本: {avg_results['rl_avg_cost']:.2f}, 平均时间: {avg_results['rl_avg_time']:.2f}, 平均利用率: {avg_results['rl_avg_utilization']:.2f}%")
    print(f"成本降低: {avg_results['cost_improvement']:.2f}%")
    print(f"时间缩短: {avg_results['time_improvement']:.2f}%")
    print(f"利用率提升: {avg_results['utilization_improvement']:.2f}%")
    print(f"数学模型平均求解时间: {avg_results['math_avg_solve_time']:.2f}秒")
    print(f"深度学习模型平均求解时间: {avg_results['rl_avg_solve_time']:.2f}秒")

if __name__ == "__main__":
    # 设置任务和车辆数量
    num_tasks = 10  # 减少任务数量以便更快运行
    num_vehicles = 5  # 减少车辆数量以便更快运行
    
    # 比较模型
    results, avg_results = compare_models(num_samples=5, num_tasks=num_tasks, num_vehicles=num_vehicles)
    
    # 可视化结果
    visualize_results(results, avg_results)      
相关推荐
你是一个铁憨憨4 小时前
使用深度学习预训练模型检测物体
人工智能·深度学习·arcgis·影像
reasonsummer4 小时前
【办公类-100-01】20250515手机导出教学照片,自动上传csdn+最大化、最小化Vs界面
开发语言·python
Doker 多克5 小时前
Python-Django系列—日志
python·日志
AI算法工程师Moxi5 小时前
什么时候可以开始学习深度学习?
人工智能·深度学习·学习
好评笔记5 小时前
Meta的AIGC视频生成模型——Emu Video
人工智能·深度学习·机器学习·aigc·transformer·校招·面试八股
苏三福6 小时前
ros2 hunmle bag 数据包转为图片数据 python版
开发语言·python·ros2humble
大神薯条老师7 小时前
Python零基础入门到高手8.4节: 元组与列表的区别
开发语言·爬虫·python·深度学习·机器学习·数据分析
z人间防沉迷k7 小时前
堆(Heap)
开发语言·数据结构·笔记·python·算法
小白学大数据7 小时前
Python爬虫如何应对网站的反爬加密策略?
开发语言·爬虫·python
Eric.Lee20217 小时前
Ubuntu shell指定conda的python环境启动脚本
python·ubuntu·conda·shell