添加greedy算法
This commit is contained in:
parent
27829c5d48
commit
58952f1fdb
255
greedy_solver.py
255
greedy_solver.py
@ -3,6 +3,8 @@ import yaml
|
|||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import matplotlib.patches as patches
|
import matplotlib.patches as patches
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
def calculate_max_photos_per_flight(params):
|
def calculate_max_photos_per_flight(params):
|
||||||
"""计算每次飞行能拍摄的最大照片数量
|
"""计算每次飞行能拍摄的最大照片数量
|
||||||
@ -21,217 +23,84 @@ def calculate_max_photos_per_flight(params):
|
|||||||
|
|
||||||
# 基于时间约束求解rho:飞行时间 = 计算时间 + 传输时间
|
# 基于时间约束求解rho:飞行时间 = 计算时间 + 传输时间
|
||||||
# flight_time_factor * d = comp_time_factor * rho * d + trans_time_factor * (1-rho) * d
|
# 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)
|
rho_time = (flight_time_factor - trans_time_factor) / \
|
||||||
|
(comp_time_factor - trans_time_factor)
|
||||||
|
|
||||||
# 基于能量约束求解最大照片数d
|
# 基于能量约束求解最大照片数d
|
||||||
# battery_energy_capacity = flight_energy_factor * d + comp_energy_factor * rho * d + trans_energy_factor * (1-rho) * 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 +
|
energy_per_photo = (flight_energy_factor +
|
||||||
comp_energy_factor * rho_time +
|
comp_energy_factor * rho_time +
|
||||||
trans_energy_factor * (1 - rho_time))
|
trans_energy_factor * (1 - rho_time))
|
||||||
|
|
||||||
max_photos = math.floor(battery_energy_capacity / energy_per_photo)
|
max_photos = battery_energy_capacity / energy_per_photo
|
||||||
|
|
||||||
return max_photos, rho_time
|
return max_photos
|
||||||
|
|
||||||
|
|
||||||
def solve_greedy(params):
|
def solve_greedy(params):
|
||||||
"""使用贪心算法求解任务分配问题"""
|
"""使用贪心算法求解任务分配问题"""
|
||||||
H = params['H']
|
H = params['H']
|
||||||
W = params['W']
|
W = params['W']
|
||||||
k = params['num_cars'] # 系统数量
|
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
|
|
||||||
|
|
||||||
# 初始化任务分配列表
|
# 1. 首先将区域均匀切分成k行
|
||||||
tasks = [[] for _ in range(k)]
|
row_ratio = 1 / k
|
||||||
|
row_boundaries = [i * row_ratio for i in range(k + 1)]
|
||||||
if min_side == H:
|
|
||||||
grid_h = min_side
|
|
||||||
grid_w = next_side
|
|
||||||
num_rows = 1
|
|
||||||
num_cols = round(W / grid_w)
|
|
||||||
|
|
||||||
current_col = 0
|
# 2. 计算每次飞行能拍摄的最大照片数量
|
||||||
for i in range(math.ceil(num_cols / k)):
|
photos_per_flight = calculate_max_photos_per_flight(params)
|
||||||
for j in range(k):
|
print(f"每次飞行能拍摄的最大照片数: {photos_per_flight}")
|
||||||
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}")
|
# 3. 针对每一行计算网格划分
|
||||||
print(f"网格数量: {num_rows}x{num_cols}")
|
row_start = row_boundaries[0]
|
||||||
print(f"任务分配情况: {tasks}")
|
row_end = row_boundaries[1]
|
||||||
|
row_height = (row_end - row_start) * H
|
||||||
# 计算区域中心点
|
|
||||||
center_x = W / 2
|
# 计算每个网格的宽度
|
||||||
center_y = H / 2
|
# 网格面积 = row_height * grid_width = photos_per_flight
|
||||||
|
grid_width = photos_per_flight / row_height
|
||||||
# 为每个系统计算完成时间
|
col_ratio = grid_width / W
|
||||||
system_times = []
|
|
||||||
|
col_boundaries = [0]
|
||||||
|
ratio = 0
|
||||||
|
while (ratio + col_ratio) < 1:
|
||||||
|
ratio += col_ratio
|
||||||
|
col_boundaries.append(ratio)
|
||||||
|
col_boundaries.append(1)
|
||||||
|
|
||||||
|
car_paths = []
|
||||||
for i in range(k):
|
for i in range(k):
|
||||||
if not tasks[i]: # 如果该系统没有分配任务
|
car_path = list(range(i * (len(col_boundaries) - 1),
|
||||||
system_times.append(0)
|
(i+1) * (len(col_boundaries) - 1)))
|
||||||
continue
|
car_paths.append(car_path)
|
||||||
|
|
||||||
# 生成该系统负责的网格中心坐标
|
return row_boundaries, col_boundaries, car_paths
|
||||||
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():
|
def main():
|
||||||
|
# ---------------------------
|
||||||
|
# 需要修改的超参数
|
||||||
|
# ---------------------------
|
||||||
|
params_file = 'params_50_50_3'
|
||||||
|
|
||||||
# 读取参数
|
# 读取参数
|
||||||
with open('params.yml', 'r', encoding='utf-8') as file:
|
with open(params_file + '.yml', 'r', encoding='utf-8') as file:
|
||||||
params = yaml.safe_load(file)
|
params = yaml.safe_load(file)
|
||||||
|
|
||||||
# 求解
|
# 求解
|
||||||
result = solve_greedy(params)
|
row_boundaries, col_boundaries, car_paths = solve_greedy(params)
|
||||||
|
|
||||||
# 输出结果
|
# ---------------------------
|
||||||
print("\n求解结果:")
|
# 输出最佳方案
|
||||||
print(f"最大完成时间: {result['max_time']:.2f} 秒")
|
# ---------------------------
|
||||||
print("\n各系统完成时间:")
|
output_data = {
|
||||||
for i, time in enumerate(result['system_times']):
|
'row_boundaries': row_boundaries,
|
||||||
print(f"系统 {i}: {time:.2f} 秒")
|
'col_boundaries': col_boundaries,
|
||||||
|
'car_paths': car_paths
|
||||||
# 可视化
|
}
|
||||||
plot_results(params, result)
|
with open(f'./solutions/greedy_{params_file}.json', 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(output_data, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -3,6 +3,7 @@ import math
|
|||||||
import yaml
|
import yaml
|
||||||
import json
|
import json
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
# 固定随机种子,便于复现
|
# 固定随机种子,便于复现
|
||||||
random.seed(42)
|
random.seed(42)
|
||||||
@ -11,7 +12,7 @@ random.seed(42)
|
|||||||
# ---------------------------
|
# ---------------------------
|
||||||
# 需要修改的超参数
|
# 需要修改的超参数
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
num_iterations = 10000000000
|
num_iterations = 100000000
|
||||||
# 随机生成分区的行分段数与列分段数
|
# 随机生成分区的行分段数与列分段数
|
||||||
R = random.randint(0, 3) # 行分段数
|
R = random.randint(0, 3) # 行分段数
|
||||||
C = random.randint(0, 3) # 列分段数
|
C = random.randint(0, 3) # 列分段数
|
||||||
@ -44,7 +45,7 @@ battery_energy_capacity = params['battery_energy_capacity']
|
|||||||
best_T = float('inf')
|
best_T = float('inf')
|
||||||
best_solution = None
|
best_solution = None
|
||||||
|
|
||||||
for iteration in range(num_iterations):
|
for iteration in tqdm(range(num_iterations), desc="蒙特卡洛模拟进度"):
|
||||||
# 直接切值
|
# 直接切值
|
||||||
horiz = [random.random() for _ in range(R)]
|
horiz = [random.random() for _ in range(R)]
|
||||||
horiz = sorted(set(horiz))
|
horiz = sorted(set(horiz))
|
||||||
|
35
solutions/greedy_params_50_50_3.json
Normal file
35
solutions/greedy_params_50_50_3.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"row_boundaries": [
|
||||||
|
0.0,
|
||||||
|
0.3333333333333333,
|
||||||
|
0.6666666666666666,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"col_boundaries": [
|
||||||
|
0,
|
||||||
|
0.3008,
|
||||||
|
0.6016,
|
||||||
|
0.9024000000000001,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"car_paths": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
30
solutions/mtkl_params_50_50_3.json
Normal file
30
solutions/mtkl_params_50_50_3.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"row_boundaries": [
|
||||||
|
0.0,
|
||||||
|
0.2145965901664986,
|
||||||
|
0.4480907391063933,
|
||||||
|
0.7086202525448272,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"col_boundaries": [
|
||||||
|
0.0,
|
||||||
|
0.5136187465626157,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"car_paths": [
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
2,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
6,
|
||||||
|
7
|
||||||
|
],
|
||||||
|
[
|
||||||
|
5,
|
||||||
|
3,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
219
visualization.py
219
visualization.py
@ -1,59 +1,206 @@
|
|||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import matplotlib.patches as patches
|
import matplotlib.patches as patches
|
||||||
import json
|
import json
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
def visualize_solution(row_boundaries, col_boundaries, car_paths_coords, W, H):
|
def visualize_solution(row_boundaries, col_boundaries, car_paths_coords, W, H, rho_list):
|
||||||
plt.rcParams['font.family'] = ['sans-serif']
|
region_center = (H / 2.0, W / 2.0)
|
||||||
plt.rcParams['font.sans-serif'] = ['SimHei']
|
|
||||||
fig, ax = plt.subplots()
|
# 创建正方形图像
|
||||||
|
fig, ax = plt.subplots(figsize=(8, 8)) # 设置固定的正方形大小
|
||||||
ax.set_xlim(0, W)
|
ax.set_xlim(0, W)
|
||||||
ax.set_ylim(H, 0) # 调整y轴方向,原点在左上角
|
ax.set_ylim(H, 0) # 调整y轴方向,原点在左上角
|
||||||
ax.set_title("区域划分与车-机-巢系统覆盖")
|
|
||||||
ax.set_xlabel("区域宽度")
|
# 设置英文标题和标签
|
||||||
ax.set_ylabel("区域高度")
|
# ax.set_title("Monte Carlo", fontsize=12)
|
||||||
|
ax.set_title("Greedy", fontsize=12)
|
||||||
|
# ax.set_title("Enumeration-Genetic Algorithm", fontsize=12)
|
||||||
|
# ax.set_title("DQN fine-tuning", fontsize=12)
|
||||||
|
|
||||||
# 定义若干颜色以区分不同系统(系统编号从0开始)
|
ax.set_xlabel("Region Width", fontsize=10)
|
||||||
colors = ['red', 'blue', 'green', 'orange', 'purple', 'cyan', 'magenta']
|
ax.set_ylabel("Region Height", fontsize=10)
|
||||||
|
|
||||||
# 绘制区域中心
|
# 定义配色方案(使用更专业的配色)
|
||||||
region_center = (H / 2.0, W / 2.0)
|
colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728',
|
||||||
ax.plot(region_center[1], region_center[0],
|
'#9467bd', '#8c564b', '#e377c2', '#7f7f7f']
|
||||||
'ko', markersize=8, label="区域中心")
|
|
||||||
|
|
||||||
# 绘制行分割边界
|
# 绘制行分割边界
|
||||||
for row in row_boundaries:
|
for row in row_boundaries[1:-1]:
|
||||||
ax.axhline(y=row * H, color='black', linestyle='--')
|
ax.axhline(y=row * H, color='gray', linestyle='--', alpha=0.5)
|
||||||
|
|
||||||
# 绘制列分割边界
|
# 绘制列分割边界
|
||||||
for col in col_boundaries:
|
for col in col_boundaries[1:-1]:
|
||||||
ax.axvline(x=col * W, color='black', linestyle='--')
|
ax.axvline(x=col * W, color='gray', linestyle='--', alpha=0.5)
|
||||||
|
|
||||||
# 绘制每辆车的轨迹并标注区域序号
|
# 绘制每辆车的轨迹并标注区域序号
|
||||||
for system_id, path in enumerate(car_paths_coords):
|
for system_id, path in enumerate(car_paths_coords):
|
||||||
path = [(region_center[0], region_center[1])] + \
|
path = [(region_center[0], region_center[1])] + \
|
||||||
path + [(region_center[0], region_center[1])]
|
path + [(region_center[0], region_center[1])]
|
||||||
y, x = zip(*path)
|
y, x = zip(*path)
|
||||||
ax.plot(x, y, marker='o', color=colors[int(
|
|
||||||
system_id) % len(colors)], label=f"系统 {system_id}")
|
# 使用箭头绘制路径
|
||||||
|
for i in range(len(path)-1):
|
||||||
|
# 绘制带箭头的线段
|
||||||
|
ax.annotate('',
|
||||||
|
xy=(x[i+1], y[i+1]),
|
||||||
|
xytext=(x[i], y[i]),
|
||||||
|
arrowprops=dict(arrowstyle='->',
|
||||||
|
color=colors[int(system_id) % len(colors)],
|
||||||
|
lw=2,
|
||||||
|
mutation_scale=15),
|
||||||
|
zorder=1)
|
||||||
|
|
||||||
|
# 绘制路径点
|
||||||
|
ax.plot(x, y, 'o', markersize=6,
|
||||||
|
color=colors[int(system_id) % len(colors)],
|
||||||
|
label=f"System {system_id}",
|
||||||
|
zorder=2)
|
||||||
|
|
||||||
# 标注每个区域的序号
|
# 标注每个区域的序号(将序号向上偏移一点)
|
||||||
for idx, (px, py) in enumerate(zip(x[1:-1], y[1:-1])): # 跳过起点和终点
|
for idx, (px, py) in enumerate(zip(x[1:-1], y[1:-1])):
|
||||||
ax.text(px, py, str(idx), color='black', fontsize=8, ha='center', va='center')
|
offset = H * 0.02 # 根据区域高度设置偏移量
|
||||||
|
ax.text(px, py - offset, str(idx),
|
||||||
|
color='black',
|
||||||
|
fontsize=9,
|
||||||
|
ha='center',
|
||||||
|
va='bottom',
|
||||||
|
bbox=dict(
|
||||||
|
facecolor='none',
|
||||||
|
edgecolor='none',
|
||||||
|
alpha=0.7,
|
||||||
|
pad=0.5))
|
||||||
|
|
||||||
|
# 绘制区域中心(设置最高的zorder确保在最上层)
|
||||||
|
ax.plot(region_center[1], region_center[0],
|
||||||
|
'k*', markersize=12, label="Region Center",
|
||||||
|
zorder=3)
|
||||||
|
|
||||||
# 添加图例
|
# 添加图例
|
||||||
ax.legend()
|
ax.legend(loc='upper right', fontsize=9)
|
||||||
|
|
||||||
|
# 保持坐标轴比例相等
|
||||||
|
ax.set_aspect('equal', adjustable='box')
|
||||||
|
|
||||||
|
# 调整布局,确保所有元素都显示完整
|
||||||
|
plt.tight_layout()
|
||||||
|
|
||||||
|
# 显示网格
|
||||||
|
ax.grid(True, linestyle=':', alpha=0.3)
|
||||||
|
|
||||||
|
# 在每个矩形区域左上角标注rho值
|
||||||
|
rho_idx = 0
|
||||||
|
for i in range(len(row_boundaries) - 1):
|
||||||
|
for j in range(len(col_boundaries) - 1):
|
||||||
|
# 获取矩形左上角坐标
|
||||||
|
x = col_boundaries[j] * W
|
||||||
|
y = row_boundaries[i] * H
|
||||||
|
|
||||||
|
# 添加一个小的偏移量,避免完全贴在边界上
|
||||||
|
offset_x = W * 0.02
|
||||||
|
offset_y = H * 0.02
|
||||||
|
|
||||||
|
# 标注rho值
|
||||||
|
ax.text(x + offset_x, y + offset_y,
|
||||||
|
f'ρ={rho_list[rho_idx]:.2f}',
|
||||||
|
color='black',
|
||||||
|
fontsize=8,
|
||||||
|
ha='left',
|
||||||
|
va='top',
|
||||||
|
bbox=dict(facecolor='white',
|
||||||
|
edgecolor='none',
|
||||||
|
alpha=0.7,
|
||||||
|
pad=0.5),
|
||||||
|
zorder=2)
|
||||||
|
rho_idx += 1
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def restore_from_solution(row_boundaries, col_boundaries, car_paths, params):
|
||||||
|
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']
|
||||||
|
car_time_factor = params['car_time_factor']
|
||||||
|
bs_time_factor = params['bs_time_factor']
|
||||||
|
|
||||||
|
flight_energy_factor = params['flight_energy_factor']
|
||||||
|
comp_energy_factor = params['comp_energy_factor']
|
||||||
|
trans_energy_factor = params['trans_energy_factor']
|
||||||
|
battery_energy_capacity = params['battery_energy_capacity']
|
||||||
|
|
||||||
|
rectangles = []
|
||||||
|
for i in range(len(row_boundaries) - 1):
|
||||||
|
for j in range(len(col_boundaries) - 1):
|
||||||
|
r1 = row_boundaries[i]
|
||||||
|
r2 = row_boundaries[i + 1]
|
||||||
|
c1 = col_boundaries[j]
|
||||||
|
c2 = col_boundaries[j + 1]
|
||||||
|
d = (r2 - r1) * H * (c2 - c1) * W # 任务的照片数量(矩形面积)
|
||||||
|
|
||||||
|
# 求解rho
|
||||||
|
rho_time_limit = (flight_time_factor - trans_time_factor) / \
|
||||||
|
(comp_time_factor - trans_time_factor)
|
||||||
|
rho_energy_limit = (battery_energy_capacity - flight_energy_factor * d - trans_energy_factor * d) / \
|
||||||
|
(comp_energy_factor * d - trans_energy_factor * d)
|
||||||
|
rho = min(rho_time_limit, rho_energy_limit)
|
||||||
|
|
||||||
|
flight_time = flight_time_factor * d
|
||||||
|
comp_time = comp_time_factor * rho * d
|
||||||
|
trans_time = trans_time_factor * (1 - rho) * d
|
||||||
|
bs_time = bs_time_factor * (1 - rho) * d
|
||||||
|
|
||||||
|
# 计算任务矩形中心,用于后续车辆移动时间计算
|
||||||
|
center_r = (r1 + r2) / 2.0 * H
|
||||||
|
center_c = (c1 + c2) / 2.0 * W
|
||||||
|
|
||||||
|
rectangles.append({
|
||||||
|
'rho': rho,
|
||||||
|
'flight_time': flight_time,
|
||||||
|
'bs_time': bs_time,
|
||||||
|
'center': (center_r, center_c)
|
||||||
|
})
|
||||||
|
|
||||||
|
system_times = []
|
||||||
|
# 根据car_paths计算时间
|
||||||
|
for car_idx in range(k):
|
||||||
|
car_path = car_paths[car_idx]
|
||||||
|
flight_time = sum(rectangles[point]['flight_time']
|
||||||
|
for point in car_path)
|
||||||
|
bs_time = sum(rectangles[point]['bs_time'] for point in car_path)
|
||||||
|
|
||||||
|
# 计算车的移动时间,首先在轨迹的首尾添加上大区域中心
|
||||||
|
car_time = 0
|
||||||
|
for i in range(len(car_path) - 1):
|
||||||
|
first_point = car_path[i]
|
||||||
|
second_point = car_path[i + 1]
|
||||||
|
car_time += math.dist(rectangles[first_point]['center'], rectangles[second_point]['center']) * \
|
||||||
|
car_time_factor
|
||||||
|
car_time += math.dist(rectangles[car_path[0]]
|
||||||
|
['center'], [H / 2, W / 2]) * car_time_factor
|
||||||
|
car_time += math.dist(rectangles[car_path[-1]]
|
||||||
|
['center'], [H / 2, W / 2]) * car_time_factor
|
||||||
|
system_time = max(flight_time + car_time, bs_time)
|
||||||
|
system_times.append(system_time)
|
||||||
|
print(f"系统{car_idx}的总时间: {system_time}")
|
||||||
|
print(f"最终时间: {max(system_times)}")
|
||||||
|
|
||||||
|
rho_list = [rectangle['rho'] for rectangle in rectangles]
|
||||||
|
return rectangles, rho_list
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
# 需要修改的超参数
|
# 需要修改的超参数
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
params_file = 'params3'
|
params_file = 'params_50_50_3'
|
||||||
solution_file = r'solutions\trav_ga_params3_parallel.json'
|
solution_file = r'solutions\greedy_params_50_50_3.json'
|
||||||
|
|
||||||
with open(params_file + '.yml', 'r', encoding='utf-8') as file:
|
with open(params_file + '.yml', 'r', encoding='utf-8') as file:
|
||||||
params = yaml.safe_load(file)
|
params = yaml.safe_load(file)
|
||||||
@ -70,27 +217,17 @@ if __name__ == "__main__":
|
|||||||
col_boundaries = best_solution['col_boundaries']
|
col_boundaries = best_solution['col_boundaries']
|
||||||
car_paths = best_solution['car_paths']
|
car_paths = best_solution['car_paths']
|
||||||
|
|
||||||
|
rectangles, rho_list = restore_from_solution(
|
||||||
|
row_boundaries, col_boundaries, car_paths, params)
|
||||||
|
|
||||||
# 计算分块区域的中心点坐标
|
# 计算分块区域的中心点坐标
|
||||||
rectangle_centers = []
|
rectangles_centers = [rectangle['center'] for rectangle in rectangles]
|
||||||
for i in range(len(row_boundaries) - 1):
|
|
||||||
for j in range(len(col_boundaries) - 1):
|
|
||||||
r1 = row_boundaries[i]
|
|
||||||
r2 = row_boundaries[i + 1]
|
|
||||||
c1 = col_boundaries[j]
|
|
||||||
c2 = col_boundaries[j + 1]
|
|
||||||
d = (r2 - r1) * H * (c2 - c1) * W # 任务的照片数量(矩形面积)
|
|
||||||
|
|
||||||
# 计算任务矩形中心,用于后续车辆移动时间计算
|
|
||||||
center_r = (r1 + r2) / 2.0 * H
|
|
||||||
center_c = (c1 + c2) / 2.0 * W
|
|
||||||
|
|
||||||
rectangle_centers.append((center_r, center_c))
|
|
||||||
|
|
||||||
# 将car_paths里的index换成坐标
|
# 将car_paths里的index换成坐标
|
||||||
car_paths_coords = [[] for _ in range(k)]
|
car_paths_coords = [[] for _ in range(k)]
|
||||||
for car_idx in range(k):
|
for car_idx in range(k):
|
||||||
car_path = car_paths[car_idx]
|
car_path = car_paths[car_idx]
|
||||||
for point in car_path:
|
for point in car_path:
|
||||||
car_paths_coords[car_idx].append(rectangle_centers[point])
|
car_paths_coords[car_idx].append(rectangles_centers[point])
|
||||||
|
|
||||||
visualize_solution(row_boundaries, col_boundaries, car_paths_coords, W, H)
|
visualize_solution(row_boundaries, col_boundaries, car_paths_coords, W, H, rho_list)
|
||||||
|
Loading…
Reference in New Issue
Block a user