From 1f18d9d96f1eac41b185405e6025276a8fc25144 Mon Sep 17 00:00:00 2001 From: weixin_46229132 Date: Thu, 13 Mar 2025 11:18:58 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=AE=97=E6=B3=95=E7=9A=84?= =?UTF-8?q?=E8=BE=93=E5=87=BA=EF=BC=8C=E6=8A=8A=E5=8F=AF=E8=A7=86=E5=8C=96?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=8D=95=E7=8B=AC=E5=88=86=E7=A6=BB=E5=87=BA?= =?UTF-8?q?=E6=9D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + mtkl_sovler.py | 161 ++++++++++------------------------------------- visualization.py | 61 ++++++++++++++++++ 3 files changed, 95 insertions(+), 128 deletions(-) create mode 100644 visualization.py diff --git a/.gitignore b/.gitignore index 07940b9..21a7ae0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ __pycache__/ # Pytorch weights weights/ +solutions/ # Distribution / packaging .Python diff --git a/mtkl_sovler.py b/mtkl_sovler.py index 9afcec0..8526546 100644 --- a/mtkl_sovler.py +++ b/mtkl_sovler.py @@ -1,8 +1,8 @@ import random import math -import matplotlib.pyplot as plt -import matplotlib.patches as patches import yaml +import json + # 固定随机种子,便于复现 random.seed(42) @@ -18,7 +18,6 @@ H = params['H'] W = params['W'] k = params['num_cars'] - flight_time_factor = params['flight_time_factor'] comp_time_factor = params['comp_time_factor'] trans_time_factor = params['trans_time_factor'] @@ -117,7 +116,7 @@ for iteration in range(num_iterations): total_flight_time = sum(task['flight_time'] for task in tasks) if tasks: # 车辆从区域中心到第一个任务中心 - car_time += math.dist(tasks[0]['center'], region_center) * car_time_factor + car_time = math.dist(tasks[0]['center'], region_center) * car_time_factor # 依次经过任务中心 for j in range(len(tasks) - 1): prev_center = tasks[j]['center'] @@ -159,131 +158,37 @@ for iteration in range(num_iterations): if best_solution is not None: print("最佳 T (各系统中最长的完成时间):", best_solution['T_max']) print(best_solution['iteration'], "次模拟后找到最佳方案:") - print(best_solution['car_time'], best_solution['flight_time'], best_solution['bs_time']) + print("分区情况:") + print("行分段数:", best_solution['R']) + print("列分段数:", best_solution['C']) + print("行分割边界:", best_solution['row_boundaries']) + print("列分割边界:", best_solution['col_boundaries']) + print("每辆车的运行轨迹情况:") + car_paths = {} for i in range(k): num_tasks = len(best_solution['system_tasks'][i]) - print( - f"系统 {i}: 完成时间 T = {best_solution['T_k_list'][i]}, 飞行任务数量: {num_tasks}") + print(f"系统 {i}: 完成时间 T = {best_solution['T_k_list'][i]}, 飞行任务数量: {num_tasks}") + tasks = best_solution['system_tasks'][i] + tasks.sort(key=lambda r: math.hypot(r['center'][0] - region_center[0], + r['center'][1] - region_center[1])) + if tasks: + print(f"轨迹路线: 区域中心({region_center[0]:.1f}, {region_center[1]:.1f})", end="") + current_pos = region_center + car_path = [] + for j, task in enumerate(tasks, 1): + current_pos = task['center'] + car_path.append(current_pos) + print(f" -> 任务{j}({current_pos[0]:.1f}, {current_pos[1]:.1f})", end="") + print(" -> 区域中心") + car_paths[i] = car_path + + # 保存分区边界和车辆轨迹到JSON文件 + output_data = { + 'row_boundaries': [boundary / H for boundary in best_solution['row_boundaries']], + 'col_boundaries': [boundary / W for boundary in best_solution['col_boundaries']], + 'car_paths': car_paths + } + with open('./solutions/best_solution_mtkl.json', 'w', encoding='utf-8') as f: + json.dump(output_data, f, ensure_ascii=False, indent=4) else: print("在给定的模拟次数内未找到满足所有约束的方案。") - -# 在输出最佳方案后添加详细信息 -if best_solution is not None: - print("\n各系统详细信息:") - region_center = (W / 2.0, H / 2.0) - - for system_id, tasks in best_solution['system_tasks'].items(): - print(f"\n系统 {system_id} 的任务详情:") - - # 按距离区域中心的距离排序任务 - tasks_sorted = sorted(tasks, key=lambda r: math.hypot(r['center'][0] - region_center[0], - r['center'][1] - region_center[1])) - - if tasks_sorted: - print( - f"轨迹路线: 区域中心({region_center[0]:.1f}, {region_center[1]:.1f})", end="") - current_pos = region_center - total_car_time = 0 - total_flight_time = 0 - total_flight_energy = 0 - total_comp_energy = 0 - total_trans_energy = 0 - - for i, task in enumerate(tasks_sorted, 1): - # 计算车辆移动时间 - car_time = math.hypot(task['center'][0] - current_pos[0], - task['center'][1] - current_pos[1]) * car_time_factor - total_car_time += car_time - - # 更新当前位置 - current_pos = task['center'] - print( - f" -> 任务{i}({current_pos[0]:.1f}, {current_pos[1]:.1f})", end="") - - # 累加各项数据 - total_flight_time += task['flight_time'] - total_flight_energy += flight_energy_factor * task['d'] - total_comp_energy += comp_energy_factor * \ - task['rho'] * task['d'] - total_trans_energy += trans_energy_factor * \ - (1 - task['rho']) * task['d'] - - print("\n") - print(f"任务数量: {len(tasks_sorted)}") - print(f"车辆总移动时间: {total_car_time:.2f} 秒") - print(f"无人机总飞行时间: {total_flight_time:.2f} 秒") - print(f"能耗统计:") - print(f" - 飞行能耗: {total_flight_energy:.2f} 分钟") - print(f" - 计算能耗: {total_comp_energy:.2f} 分钟") - print(f" - 传输能耗: {total_trans_energy:.2f} 分钟") - print( - f" - 总能耗: {(total_flight_energy + total_comp_energy + total_trans_energy):.2f} 分钟") - - print("\n各任务详细信息:") - for i, task in enumerate(tasks_sorted, 1): - print(f"\n任务{i}:") - print( - f" 位置: ({task['center'][0]:.1f}, {task['center'][1]:.1f})") - print(f" 照片数量: {task['d']}") - print(f" 卸载比率(ρ): {task['rho']:.2f}") - print(f" 飞行时间: {task['flight_time']:.2f} 秒") - print(f" 计算时间: {task['comp_time']:.2f} 秒") - print(f" 传输时间: {task['trans_time']:.2f} 秒") - print(f" -- 飞行能耗: {task['d'] * flight_energy_factor:.2f} 分钟") - print(f" -- 计算能耗: {task['d'] * comp_energy_factor:.2f} 分钟") - print(f" -- 传输能耗: {task['d'] * trans_energy_factor:.2f} 分钟") - print(f" 基站计算时间: {task['bs_time']:.2f} 秒") - else: - print("该系统没有分配任务") - print("-" * 50) - -if best_solution is not None: - plt.rcParams['font.family'] = ['sans-serif'] - plt.rcParams['font.sans-serif'] = ['SimHei'] - fig, ax = plt.subplots() - ax.set_xlim(0, W) - ax.set_ylim(0, H) - ax.set_title("区域划分与车-机-巢系统覆盖") - ax.set_xlabel("区域宽度") - ax.set_ylabel("区域高度") - - # 定义若干颜色以区分不同系统(系统编号从0开始) - colors = ['red', 'blue', 'green', 'orange', 'purple', 'cyan', 'magenta'] - - # 绘制区域中心 - region_center = (W / 2.0, H / 2.0) # 注意:x对应宽度,y对应高度 - ax.plot(region_center[0], region_center[1], - 'ko', markersize=8, label="区域中心") - - # 绘制每个任务区域(矩形)及在矩形中心标注系统编号与卸载比率 ρ - for system_id, tasks in best_solution['system_tasks'].items(): - # 重新按车辆行驶顺序排序(启发式:以任务中心距离区域中心的距离排序) - tasks_sorted = sorted(tasks, key=lambda task: math.hypot( - (task['c1'] + (task['c2'] - task['c1']) / 2.0) - region_center[0], - (task['r1'] + (task['r2'] - task['r1']) / 2.0) - region_center[1] - )) - - for i, task in enumerate(tasks_sorted, 1): - # 绘制矩形:左下角坐标为 (c1, r1),宽度为 (c2 - c1),高度为 (r2 - r1) - rect = patches.Rectangle((task['c1'], task['r1']), - task['c2'] - task['c1'], - task['r2'] - task['r1'], - linewidth=2, - edgecolor=colors[system_id % len(colors)], - facecolor='none') - ax.add_patch(rect) - # 计算矩形中心 - center_x = task['c1'] + (task['c2'] - task['c1']) / 2.0 - center_y = task['r1'] + (task['r2'] - task['r1']) / 2.0 - # 在矩形中心标注:系统编号、执行顺序和卸载比率 ρ - ax.text(center_x, center_y, f"S{system_id}-{i}\nρ={task['rho']:.2f}", - color=colors[system_id % len(colors)], - ha='center', va='center', fontsize=10, fontweight='bold') - - # 添加图例 - ax.legend() - # 反转 y 轴使得行号从上到下递增(如需,可取消) - ax.invert_yaxis() - plt.show() -else: - print("没有找到满足约束条件的方案,无法进行可视化。") diff --git a/visualization.py b/visualization.py new file mode 100644 index 0000000..20e5ad0 --- /dev/null +++ b/visualization.py @@ -0,0 +1,61 @@ +import matplotlib.pyplot as plt +import matplotlib.patches as patches +import json + +def visualize_solution(row_boundaries, col_boundaries, car_paths, W, H): + plt.rcParams['font.family'] = ['sans-serif'] + plt.rcParams['font.sans-serif'] = ['SimHei'] + fig, ax = plt.subplots() + ax.set_xlim(0, W) + ax.set_ylim(0, H) + ax.set_title("区域划分与车-机-巢系统覆盖") + ax.set_xlabel("区域宽度") + ax.set_ylabel("区域高度") + + # 定义若干颜色以区分不同系统(系统编号从0开始) + colors = ['red', 'blue', 'green', 'orange', 'purple', 'cyan', 'magenta'] + + # 绘制区域中心 + region_center = (H / 2.0, W / 2.0) # 注意:x对应宽度,y对应高度 + ax.plot(region_center[1], region_center[0], + 'ko', markersize=8, label="区域中心") + + # 绘制行分割边界 + for row in row_boundaries: + ax.axhline(y=row * H, color='black', linestyle='--') + + # 绘制列分割边界 + for col in col_boundaries: + ax.axvline(x=col * W, color='black', linestyle='--') + + # 绘制每辆车的轨迹 + for system_id, path in car_paths.items(): + path = [(region_center[0], region_center[1])] + path + [(region_center[0], region_center[1])] + y, x = zip(*path) + ax.plot(x, y, marker='o', color=colors[int(system_id) % len(colors)], label=f"系统 {system_id}") + + # 添加图例 + ax.legend() + # 反转 y 轴使得行号从上到下递增(如需,可取消) + ax.invert_yaxis() + plt.show() + +if __name__ == "__main__": + import yaml + + # 读取参数 + with open('params.yml', 'r', encoding='utf-8') as file: + params = yaml.safe_load(file) + + H = params['H'] + W = params['W'] + + # 读取最佳方案的JSON文件 + with open('./solutions/best_solution_mtkl.json', 'r', encoding='utf-8') as f: + best_solution = json.load(f) + + row_boundaries = best_solution['row_boundaries'] + col_boundaries = best_solution['col_boundaries'] + car_paths = best_solution['car_paths'] + + visualize_solution(row_boundaries, col_boundaries, car_paths, W, H) \ No newline at end of file