import math import yaml import matplotlib.pyplot as plt import matplotlib.patches as patches import numpy as np def calculate_max_photos_per_flight(params): """计算每次飞行能拍摄的最大照片数量 基于以下约束: 1. 电池能量约束 2. 计算+传输时间 = 飞行时间 """ # 从参数中提取时间和能量因子 flight_time_factor = params['flight_time_factor'] comp_time_factor = params['comp_time_factor'] trans_time_factor = params['trans_time_factor'] battery_energy_capacity = params['battery_energy_capacity'] flight_energy_factor = params['flight_energy_factor'] comp_energy_factor = params['comp_energy_factor'] trans_energy_factor = params['trans_energy_factor'] # 基于时间约束求解rho:飞行时间 = 计算时间 + 传输时间 # flight_time_factor * d = comp_time_factor * rho * d + trans_time_factor * (1-rho) * d rho_time = (flight_time_factor - trans_time_factor) / (comp_time_factor - trans_time_factor) # 基于能量约束求解最大照片数d # battery_energy_capacity = flight_energy_factor * d + comp_energy_factor * rho * d + trans_energy_factor * (1-rho) * d energy_per_photo = (flight_energy_factor + comp_energy_factor * rho_time + trans_energy_factor * (1 - rho_time)) max_photos = math.floor(battery_energy_capacity / energy_per_photo) return max_photos, rho_time def solve_greedy(params): """使用贪心算法求解任务分配问题""" H = params['H'] W = params['W'] k = params['num_cars'] # 系统数量 car_time_factor = params['car_time_factor'] bs_time_factor = params['bs_time_factor'] flight_time_factor = params['flight_time_factor'] # 计算每次飞行能拍摄的最大照片数 photos_per_flight, rho = calculate_max_photos_per_flight(params) print(f"贪心无人机计算的情况下,每次飞行能拍摄的最大照片数: {photos_per_flight}") print(f"卸载率 rho: {rho:.3f}") # 用较小的边长来划分网格 min_side = min(H, W) next_side = photos_per_flight // min_side # 初始化任务分配列表 tasks = [[] for _ in range(k)] if min_side == H: grid_h = min_side grid_w = next_side num_rows = 1 num_cols = round(W / grid_w) current_col = 0 for i in range(math.ceil(num_cols / k)): for j in range(k): tasks[j].append((0, current_col)) current_col += 1 if current_col == num_cols: break else: grid_w = min_side grid_h = next_side num_cols = 1 num_rows = round(H / grid_h) current_row = 0 for i in range(math.ceil(num_rows / k)): for j in range(k): tasks[j].append((current_row, 0)) current_row += 1 if current_row == num_rows: break print(f"网格大小: {grid_w}x{grid_h}") print(f"网格数量: {num_rows}x{num_cols}") print(f"任务分配情况: {tasks}") # 计算区域中心点 center_x = W / 2 center_y = H / 2 # 为每个系统计算完成时间 system_times = [] for i in range(k): if not tasks[i]: # 如果该系统没有分配任务 system_times.append(0) continue # 生成该系统负责的网格中心坐标 grids = [] for row, col in tasks[i]: if min_side == H: # 如果H是较小边,那么row=0,col递增 # TODO 最后一个网格的中心点不能这么算 grid_center_x = (col + 0.5) * grid_w grid_center_y = (row + 0.5) * grid_h else: # 如果W是较小边,那么col=0,row递增 grid_center_x = (col + 0.5) * grid_w grid_center_y = (row + 0.5) * grid_h grids.append((grid_center_x, grid_center_y)) # 计算车辆路径长度(从中心点出发) car_distance = math.hypot(center_x - grids[0][0], center_y - grids[0][1]) # 从中心到第一个网格 for j in range(len(grids)-1): car_distance += math.hypot(grids[j+1][0] - grids[j][0], grids[j+1][1] - grids[j][1]) # 网格间距离 car_distance += math.hypot(grids[-1][0] - center_x, grids[-1][1] - center_y) # 从最后一个网格回到中心 # 计算时间 num_photos = len(grids) * photos_per_flight # 该系统需要拍摄的总照片数 flight_time = flight_time_factor * num_photos # 飞行时间 car_time = car_time_factor * car_distance # 车辆移动时间 bs_time = bs_time_factor * (1 - rho) * num_photos # 基站计算时间 total_time = max(flight_time + car_time, bs_time) system_times.append(total_time) print(f"\n系统 {i} 详细信息:") print(f"负责的网格数: {len(grids)}") print(f"总照片数: {num_photos}") print(f"车辆移动距离: {car_distance:.2f}") print(f"飞行时间: {flight_time:.2f}") print(f"车辆时间: {car_time:.2f}") print(f"基站时间: {bs_time:.2f}") print(f"总完成时间: {total_time:.2f}") # 找出最大完成时间 max_time = max(system_times) print(f"\n最大完成时间: {max_time:.2f}") # 准备返回结果 result = { 'max_time': max_time, 'system_times': system_times, 'photos_per_flight': photos_per_flight, 'grid_w': grid_w, 'grid_h': grid_h, 'num_rows': num_rows, 'num_cols': num_cols, 'tasks': tasks, 'rho': rho } return result def plot_results(params, result): """可视化结果""" H = params['H'] W = params['W'] k = params['num_cars'] plt.rcParams['font.family'] = ['sans-serif'] plt.rcParams['font.sans-serif'] = ['SimHei'] # 创建图形 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5)) # 1. 绘制系统完成时间对比 ax1.bar(range(k), result['system_times']) ax1.set_title('各系统完成时间对比') ax1.set_xlabel('系统编号') ax1.set_ylabel('完成时间(秒)') # 2. 绘制网格划分示意图 ax2.set_xlim(0, W) ax2.set_ylim(0, H) # 为不同系统的网格使用不同颜色 colors = plt.cm.rainbow(np.linspace(0, 1, k)) # 绘制网格和系统分配 grid_w = result['grid_w'] grid_h = result['grid_h'] tasks = result['tasks'] # 绘制每个系统的网格 for system_idx, system_tasks in enumerate(tasks): for row, col in system_tasks: rect = patches.Rectangle( (col * grid_w, row * grid_h), grid_w, grid_h, linewidth=1, edgecolor='black', facecolor=colors[system_idx], alpha=0.3 ) ax2.add_patch(rect) # 在网格中心添加系统编号 center_x = (col + 0.5) * grid_w center_y = (row + 0.5) * grid_h ax2.text(center_x, center_y, str(system_idx), ha='center', va='center') # 添加中心点标记 ax2.plot(W/2, H/2, 'r*', markersize=15, label='区域中心') ax2.legend() ax2.set_title('网格划分和系统分配示意图') ax2.set_xlabel('宽度') ax2.set_ylabel('高度') plt.tight_layout() plt.show() def main(): # 读取参数 with open('params.yml', 'r', encoding='utf-8') as file: params = yaml.safe_load(file) # 求解 result = solve_greedy(params) # 输出结果 print("\n求解结果:") print(f"最大完成时间: {result['max_time']:.2f} 秒") print("\n各系统完成时间:") for i, time in enumerate(result['system_times']): print(f"系统 {i}: {time:.2f} 秒") # 可视化 plot_results(params, result) if __name__ == "__main__": main()