diff --git a/GA/main_parallel.py b/GA/main_parallel.py index ce83f4c..0548a0c 100644 --- a/GA/main_parallel.py +++ b/GA/main_parallel.py @@ -30,10 +30,10 @@ if __name__ == "__main__": # 重要:在 Windows 上必须加这一行 # --------------------------- # 需要修改的超参数 # --------------------------- - R = 1 + R = 3 C = 1 - params_file = 'params3' - batch_size = 10 # 控制一次最多并行多少个任务 + params_file = 'params_50_50_3' + batch_size = 60 # 控制一次最多并行多少个任务 with open(params_file + '.yml', 'r', encoding='utf-8') as file: params = yaml.safe_load(file) diff --git a/GA/sa_finetune.py b/GA/sa_finetune.py index 3ba46ec..5452018 100644 --- a/GA/sa_finetune.py +++ b/GA/sa_finetune.py @@ -225,8 +225,8 @@ if __name__ == "__main__": # --------------------------- # 需要修改的超参数 # --------------------------- - solution_path = r"solutions\trav_ga_params2_parallel.json" - params_file = r"params2" + solution_path = r"solutions\trav_ga_params_50_50_3_parallel.json" + params_file = r"params_50_50_3" max_iterations=10000 initial_temp=100 cooling_rate=0.95 diff --git a/mtkl_sovler.py b/mtkl_sovler.py index 5014705..ba0c995 100644 --- a/mtkl_sovler.py +++ b/mtkl_sovler.py @@ -15,9 +15,9 @@ num_iterations = 10000 # 随机生成分区的行分段数与列分段数 # R = random.randint(0, 3) # 行分段数 # C = random.randint(0, 3) # 列分段数 -R = 1 -C = 1 -params_file = 'params3' +R = 3 +C = 3 +params_file = 'params_50_50_3' with open(params_file + '.yml', 'r', encoding='utf-8') as file: @@ -45,7 +45,7 @@ best_T = float('inf') best_solution = None for iteration in range(num_iterations): - # 生成随机的行、列分割边界 + # 切比例 horiz = [np.clip(np.floor(random.random() * 10) / 10, 0.0, 0.9) for _ in range(R)] horiz = sorted(set(horiz)) diff --git a/mtkl_sovler2.py b/mtkl_sovler2.py new file mode 100644 index 0000000..90abafb --- /dev/null +++ b/mtkl_sovler2.py @@ -0,0 +1,189 @@ +import random +import math +import yaml +import json +import numpy as np + +# 固定随机种子,便于复现 +random.seed(42) + + +# --------------------------- +# 需要修改的超参数 +# --------------------------- +num_iterations = 10000000000 +# 随机生成分区的行分段数与列分段数 +R = random.randint(0, 3) # 行分段数 +C = random.randint(0, 3) # 列分段数 +# R = 3 +# C = 3 +params_file = 'params_50_50_3' + + +with open(params_file + '.yml', 'r', encoding='utf-8') as file: + params = yaml.safe_load(file) + +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'] + +# --------------------------- +# 蒙特卡洛模拟,寻找最佳方案 +# --------------------------- +best_T = float('inf') +best_solution = None + +for iteration in range(num_iterations): + # 直接切值 + horiz = [random.random() for _ in range(R)] + horiz = sorted(set(horiz)) + horiz = horiz if horiz else [] + row_boundaries = [0] + horiz + [1] + row_boundaries = [boundary * H for boundary in row_boundaries] + + vert = [random.random() for _ in range(C)] + vert = sorted(set(vert)) + vert = vert if vert else [] + col_boundaries = [0] + vert + [1] + col_boundaries = [boundary * W for boundary in col_boundaries] + + # --------------------------- + # 根据分割边界生成所有矩形任务 + # --------------------------- + rectangles = [] + valid_partition = True # 标记此分区是否满足所有约束 + 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) * (c2 - c1) # 任务的照片数量(矩形面积) + + # 求解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) + if rho_energy_limit < 0: + valid_partition = False + break + 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 + center_c = (c1 + c2) / 2.0 + + rectangles.append({ + 'r1': r1, 'r2': r2, 'c1': c1, 'c2': c2, + 'd': d, + 'rho': rho, + 'flight_time': flight_time, + 'comp_time': comp_time, + 'trans_time': trans_time, + 'bs_time': bs_time, + 'center': (center_r, center_c) + }) + if not valid_partition: + break + + # 如果分区中存在任务不满足电池约束,则跳过该分区 + if not valid_partition: + continue + + # --------------------------- + # 随机将所有矩形任务分配给 k 个系统(车-机-巢) + # --------------------------- + car_paths = [[] for _ in range(k)] + for i in range(len(row_boundaries) - 1): + for j in range(len(col_boundaries) - 1): + car_idx = random.randint(0, k - 1) + car_paths[car_idx].append(i * (len(col_boundaries) - 1) + j) + + # --------------------------- + # 对于每个系统,计算该系统的总完成时间 T_k: + # T_k = 所有任务的飞行时间之和 + 车辆的移动时间 + # 车辆移动时间:车辆从区域中心出发,依次经过各任务中心(顺序采用距离区域中心的启发式排序) + # --------------------------- + region_center = (H / 2.0, W / 2.0) + T_k_list = [] + for i in range(k): + car_path = car_paths[i] + car_path.sort(key=lambda r: math.dist( + rectangles[r]['center'], region_center)) + total_flight_time = sum( + rectangles[point]['flight_time'] for point in car_path) + if car_path: + # 车辆从区域中心到第一个任务中心 + car_time = math.dist(rectangles[car_path[0]]['center'], + region_center) * car_time_factor + # 依次经过任务中心 + for j in range(len(car_path) - 1): + prev_center = rectangles[car_path[j]]['center'] + curr_center = rectangles[car_path[j + 1]]['center'] + car_time += math.dist(curr_center, + prev_center) * car_time_factor + # 回到区域中心 + car_time += math.dist(region_center, curr_center) * car_time_factor + else: + car_time = 0 + + # 机巢的计算时间 + total_bs_time = sum(rectangles[point]['bs_time'] for point in car_path) + T_k = max(total_flight_time + car_time, total_bs_time) + T_k_list.append(T_k) + + T_max = max(T_k_list) # 整体目标 T 为各系统中最大的 T_k + + # TODO 没有限制系统的总能耗 + + if T_max < best_T: + best_T = T_max + best_solution = { + 'car_paths': car_paths, + 'T_k_list': T_k_list, + 'T_max': T_max, + 'iteration': iteration, + 'R': R, + 'C': C, + 'row_boundaries': row_boundaries, + 'col_boundaries': col_boundaries, + 'car_time': car_time, + 'flight_time': total_flight_time, + 'bs_time': total_bs_time + } + +# --------------------------- +# 输出最佳方案 +# --------------------------- +if best_solution is not None: + print("最佳 T:", best_solution['T_max']) + print("Row boundaries:", best_solution['row_boundaries']) + print("Col boundaries:", best_solution['col_boundaries']) + print("最佳路径:", best_solution['car_paths']) + + # 保存分区边界和车辆轨迹到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': best_solution['car_paths'] + } + with open(f'./solutions/mtkl_{params_file}.json', 'w', encoding='utf-8') as f: + json.dump(output_data, f, ensure_ascii=False, indent=4) +else: + print("在给定的模拟次数内未找到满足所有约束的方案。") diff --git a/params3.yml b/params3.yml deleted file mode 100644 index b3a45fe..0000000 --- a/params3.yml +++ /dev/null @@ -1,16 +0,0 @@ -H : 30 # 区域高度,网格点之间的距离为25m(单位距离) -W : 30 # 区域宽度 -num_cars : 2 # 系统数量(车-巢-机系统个数) - -# 时间系数(单位:秒,每个网格一张照片) -flight_time_factor : 3 # 每张照片对应的飞行时间,无人机飞行速度为9.5m/s,拍摄照片的时间间隔为3s -comp_time_factor : 5 # 无人机上每张照片计算时间,5s -trans_time_factor : 0.3 # 每张照片传输时间,0.3s -car_time_factor : 100 # TODO 汽车每单位距离的移动时间,2s,加了一个放大因子50 -bs_time_factor : 5 # 机巢上每张照片计算时间 - -# 其他参数 -flight_energy_factor : 0.05 # 单位:分钟/张 -comp_energy_factor : 0.05 # TODO 计算能耗需要重新估计 -trans_energy_factor : 0.0025 -battery_energy_capacity : 20 # 无人机只进行飞行,续航为30分钟 \ No newline at end of file diff --git a/params2.yml b/params_50_50_3.yml similarity index 100% rename from params2.yml rename to params_50_50_3.yml diff --git a/solutions/finetune_params2.json b/solutions/finetune_params_50_50_3.json similarity index 78% rename from solutions/finetune_params2.json rename to solutions/finetune_params_50_50_3.json index 59b0a55..12c335b 100644 --- a/solutions/finetune_params2.json +++ b/solutions/finetune_params_50_50_3.json @@ -1,7 +1,7 @@ { "row_boundaries": [ 0.0, - 0.3000000000000001, + 0.30000000000000016, 0.4800000000000001, 0.77, 1.0 @@ -12,19 +12,19 @@ 1.0 ], "car_paths": [ + [ + 0, + 2, + 4 + ], + [ + 6, + 7 + ], [ 1, 3, 5 - ], - [ - 4, - 2, - 0 - ], - [ - 7, - 6 ] ] } \ No newline at end of file diff --git a/solutions/mtkl_params2.json b/solutions/mtkl_params2.json deleted file mode 100644 index cca8d17..0000000 --- a/solutions/mtkl_params2.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "row_boundaries": [ - 0.0, - 0.5, - 1.0 - ], - "col_boundaries": [ - 0.0, - 0.2, - 0.5, - 0.8, - 1.0 - ], - "car_paths": [ - [ - 2, - 3, - 7 - ], - [ - 1, - 5, - 6 - ], - [ - 0, - 4 - ] - ] -} \ No newline at end of file diff --git a/solutions/mtkl_params3.json b/solutions/mtkl_params3.json deleted file mode 100644 index da3f6a7..0000000 --- a/solutions/mtkl_params3.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "row_boundaries": [ - 0.0, - 0.5, - 1.0 - ], - "col_boundaries": [ - 0.0, - 0.5, - 1.0 - ], - "car_paths": [ - [ - 0, - 2 - ], - [ - 1, - 3 - ] - ] -} \ No newline at end of file diff --git a/solutions/trav_ga_params2.json b/solutions/trav_ga_params2.json deleted file mode 100644 index cbbe99f..0000000 --- a/solutions/trav_ga_params2.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "row_boundaries": [ - 0.0, - 0.1, - 0.4, - 0.7, - 1.0 - ], - "col_boundaries": [ - 0.0, - 0.5, - 1.0 - ], - "car_paths": [ - [ - 0, - 2, - 4 - ], - [ - 5, - 3, - 1 - ], - [ - 7, - 6 - ] - ] -} \ No newline at end of file diff --git a/solutions/trav_ga_params3_parallel.json b/solutions/trav_ga_params3_parallel.json deleted file mode 100644 index 94bc288..0000000 --- a/solutions/trav_ga_params3_parallel.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "row_boundaries": [ - 0.0, - 0.5, - 1.0 - ], - "col_boundaries": [ - 0.0, - 0.5, - 1.0 - ], - "car_paths": [ - [ - 0, - 2 - ], - [ - 3, - 1 - ] - ] -} \ No newline at end of file diff --git a/solutions/trav_ga_params2_parallel.json b/solutions/trav_ga_params_50_50_3_parallel.json similarity index 100% rename from solutions/trav_ga_params2_parallel.json rename to solutions/trav_ga_params_50_50_3_parallel.json index 7ffa6a9..79fe975 100644 --- a/solutions/trav_ga_params2_parallel.json +++ b/solutions/trav_ga_params_50_50_3_parallel.json @@ -12,11 +12,6 @@ 1.0 ], "car_paths": [ - [ - 1, - 3, - 5 - ], [ 0, 2, @@ -25,6 +20,11 @@ [ 6, 7 + ], + [ + 1, + 3, + 5 ] ] } \ No newline at end of file diff --git a/visualization.py b/visualization.py index d059d63..5d83013 100644 --- a/visualization.py +++ b/visualization.py @@ -52,8 +52,8 @@ if __name__ == "__main__": # --------------------------- # 需要修改的超参数 # --------------------------- - params_file = 'params2' - solution_file = r'solutions\trav_finetune_params2.json' + params_file = 'params3' + solution_file = r'solutions\trav_ga_params3_parallel.json' with open(params_file + '.yml', 'r', encoding='utf-8') as file: params = yaml.safe_load(file)