添加greedy求解代码
This commit is contained in:
parent
3818343085
commit
fe4e754cc4
27
PPO/env.py
27
PPO/env.py
@ -61,7 +61,7 @@ class PartitionMazeEnv(gym.Env):
|
|||||||
|
|
||||||
# 路径规划阶段相关变量
|
# 路径规划阶段相关变量
|
||||||
self.MAX_STEPS = 50 # 迷宫走法步数上限
|
self.MAX_STEPS = 50 # 迷宫走法步数上限
|
||||||
self.BASE_LINE = 2750.0 # 基准时间,通过greedy或者蒙特卡洛计算出来
|
self.BASE_LINE = 3400.0 # 基准时间,通过greedy或者蒙特卡洛计算出来
|
||||||
self.step_count = 0
|
self.step_count = 0
|
||||||
self.rectangles = {}
|
self.rectangles = {}
|
||||||
self.car_pos = [[0.5, 0.5] for _ in range(self.num_cars)]
|
self.car_pos = [[0.5, 0.5] for _ in range(self.num_cars)]
|
||||||
@ -139,6 +139,7 @@ class PartitionMazeEnv(gym.Env):
|
|||||||
bs_time = self.bs_time_factor * (1 - rho) * d
|
bs_time = self.bs_time_factor * (1 - rho) * d
|
||||||
|
|
||||||
self.rectangles[(i, j)] = {
|
self.rectangles[(i, j)] = {
|
||||||
|
'center': ((h_boundaries[i] + h_boundaries[i+1]) * self.H / 2, (v_boundaries[j+1] - v_boundaries[j]) * self.W / 2),
|
||||||
'flight_time': flight_time,
|
'flight_time': flight_time,
|
||||||
'bs_time': bs_time,
|
'bs_time': bs_time,
|
||||||
'is_visited': False
|
'is_visited': False
|
||||||
@ -243,6 +244,8 @@ class PartitionMazeEnv(gym.Env):
|
|||||||
# 区域覆盖完毕,根据轨迹计算各车队的执行时间
|
# 区域覆盖完毕,根据轨迹计算各车队的执行时间
|
||||||
T = max([self._compute_motorcade_time(idx)
|
T = max([self._compute_motorcade_time(idx)
|
||||||
for idx in range(self.num_cars)])
|
for idx in range(self.num_cars)])
|
||||||
|
print(T)
|
||||||
|
print(self.car_traj)
|
||||||
reward += -(T - self.BASE_LINE)
|
reward += -(T - self.BASE_LINE)
|
||||||
elif done and self.step_count >= self.MAX_STEPS:
|
elif done and self.step_count >= self.MAX_STEPS:
|
||||||
reward += -100
|
reward += -100
|
||||||
@ -257,21 +260,23 @@ class PartitionMazeEnv(gym.Env):
|
|||||||
|
|
||||||
# 计算车的移动时间,首先在轨迹的首尾添加上大区域中心
|
# 计算车的移动时间,首先在轨迹的首尾添加上大区域中心
|
||||||
car_time = 0
|
car_time = 0
|
||||||
self.car_traj[idx].append([0.5, 0.5])
|
# self.car_traj[idx].append([0.5, 0.5])
|
||||||
self.car_traj[idx].insert(0, [0.5, 0.5])
|
# self.car_traj[idx].insert(0, [0.5, 0.5])
|
||||||
for i in range(len(self.car_traj[idx]) - 1):
|
for i in range(len(self.car_traj[idx]) - 1):
|
||||||
first_point = self.car_traj[idx][i]
|
first_point = self.car_traj[idx][i]
|
||||||
second_point = self.car_traj[idx][i + 1]
|
second_point = self.car_traj[idx][i + 1]
|
||||||
car_time += math.dist(first_point, second_point) * \
|
car_time += math.dist(self.rectangles[tuple(first_point)]['center'], self.rectangles[tuple(second_point)]['center']) * \
|
||||||
self.H * self.W * self.car_time_factor
|
self.car_time_factor
|
||||||
|
car_time + math.dist(self.rectangles[tuple(self.car_traj[idx][0])]['center'], [self.H, self.W])
|
||||||
|
car_time + math.dist(self.rectangles[tuple(self.car_traj[idx][-1])]['center'], [self.H, self.W])
|
||||||
|
|
||||||
return max(float(car_time) + flight_time, bs_time)
|
return max(float(car_time) + flight_time, bs_time)
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
if self.phase == 0:
|
if self.phase == 1:
|
||||||
print("Phase 0: Partitioning.")
|
print("Phase 1: Initialize maze environment.")
|
||||||
print(f"Partition step: {self.partition_step}")
|
|
||||||
print(f"Partition values so far: {self.partition_values}")
|
print(f"Partition values so far: {self.partition_values}")
|
||||||
elif self.phase == 1:
|
print(f"Motorcade positon: {self.car_pos}")
|
||||||
print("Phase 1: Path planning (maze).")
|
elif self.phase == 2:
|
||||||
print(f"Step count: {self.step_count}")
|
print("Phase 2: Play maze.")
|
||||||
|
print(f'Motorcade trajectory: {self.car_traj}')
|
||||||
|
237
greedy_solver.py
Normal file
237
greedy_solver.py
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
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()
|
@ -6,7 +6,7 @@ import yaml
|
|||||||
# 固定随机种子,便于复现
|
# 固定随机种子,便于复现
|
||||||
random.seed(42)
|
random.seed(42)
|
||||||
|
|
||||||
num_iterations = 100000
|
num_iterations = 1000000
|
||||||
|
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
# 参数设置
|
# 参数设置
|
||||||
@ -125,6 +125,9 @@ for iteration in range(num_iterations):
|
|||||||
curr_center = tasks[j]['center']
|
curr_center = tasks[j]['center']
|
||||||
car_time += math.hypot(curr_center[0] - prev_center[0],
|
car_time += math.hypot(curr_center[0] - prev_center[0],
|
||||||
curr_center[1] - prev_center[1]) * car_time_factor
|
curr_center[1] - prev_center[1]) * car_time_factor
|
||||||
|
# 回到区域中心
|
||||||
|
car_time += math.hypot(curr_center[0] - region_center[0],
|
||||||
|
curr_center[1] - prev_center[1]) * car_time_factor
|
||||||
else:
|
else:
|
||||||
car_time = 0
|
car_time = 0
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user