From 18af821aae7ce464e816426e509354aad04d90ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:39:53 +0800 Subject: [PATCH 01/11] Create MetaGPT_log_MetaGPT_statistical_caliber.py --- ...MetaGPT_log_MetaGPT_statistical_caliber.py | 356 ++++++++++++++++++ 1 file changed, 356 insertions(+) create mode 100644 Minecraft plot/MetaGPT_log_MetaGPT_statistical_caliber.py diff --git a/Minecraft plot/MetaGPT_log_MetaGPT_statistical_caliber.py b/Minecraft plot/MetaGPT_log_MetaGPT_statistical_caliber.py new file mode 100644 index 000000000..5754f33ba --- /dev/null +++ b/Minecraft plot/MetaGPT_log_MetaGPT_statistical_caliber.py @@ -0,0 +1,356 @@ +import re +import argparse +import os +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +import math +import numpy as np +import random +import seaborn as sns +import matplotlib as mpl +import pandas as pd +mpl.rcParams.update(mpl.rcParamsDefault) + +def extract_logs(filename, start_time=None, end_time=None): + with open(filename, 'r',encoding='utf-8') as f: + lines = f.readlines() + + if start_time is None : + # 如果没有提供时间参数,则返回所有日志 + return lines + + # 截取开始时间和停止时间之间的日志块 + logs_block = [] + capture = False + for line in lines: + if start_time in line: + capture = True + if capture: + logs_block.append(line) + if end_time and end_time in line: + capture = False + break + + return logs_block + +def extract_time_from_first_round_zero(log_filename): + with open(log_filename, 'r',encoding='utf-8') as f: + lines = f.readlines() + + # 正向遍历文件的每一行 + for line in lines: + if "Config loading done" in line: + # 正则表达式匹配年月日 小时:分钟的格式 + match = re.search(r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2})', line) + if match: + return match.group(1) + return None + +def analyze_log_block(logs_block): + rounds: list[int] = [] + items_collected :list[int] = [] + total_items = 0 + positions:list[(int, int, int)] = [] + completed_tasks: list[int] = [] + failed_tasks: list[int] = [] + items_variety_collected :list[int] = [] + items_collected_dict :list[dict] = [] + biomes: list[str] = [] # 存储所有出现过的生物群系 + biomes_per_round: list[list[str]] = [] # 存储每轮结束时已经经历过的生物群系 + new_biome_rounds: list[int] = [] # 存储添加新生物群系的轮次 + round_start = False + check_for_info = False + line_after_message = 0 + first_group = True + + + first_group = True # 添加一个新变量来跟踪是否已经处理过这一轮的第一组信息 + + for line in logs_block: + if "round_id:" in line: + n = int(re.search(r'round_id:(\d+)', line).group(1)) + if n not in rounds: + rounds.append(n) + round_start = True + + if round_start: + if "Curriculum Agent human message" in line: + if check_for_info: # 如果已经开始解析,就跳过这一轮的剩余部分 + round_start = False + continue + check_for_info = True + line_after_message = 0 + continue + + if check_for_info: + line_after_message += 1 + + if line_after_message <= 100: + if "Position: x=" in line: + match = re.search(r'Position: x=([\d.-]+), y=([\d.-]+), z=([\d.-]+)', line) + x, y, z = float(match.group(1)), float(match.group(2)), float(match.group(3)) + positions.append((x, y, z)) + + if "Inventory (" in line: + if ": Empty" in line: + items_collected.append(0) + items = None + items_collected_dict.append({}) # 将这一轮结束时的物品存储状态添加到列表中 + total_items = 0 + items_variety_collected.append(0) # 统计物品种类数量 + else: + items = re.search(r'Inventory \(\d+/36\): ({.*?})', line).group(1) + items_dict = eval(items) + items_collected_dict.append(items_dict) # 将这一轮结束时的物品存储状态添加到列表中 + total_items = sum(items_dict.values()) + items_collected.append(total_items) + items_variety_collected.append(len(items_dict)) # 统计物品种类数量 + if "Biome: " in line: + biome = line.replace("Biome: ", "").strip() + if biome not in biomes: + biomes.append(biome) + new_biome_rounds.append(rounds[-1]) # 记录添加新生物群系的轮次 + biomes_per_round.append(biomes.copy()) # 记录当前已经经历过 + if "Completed tasks so far:" in line: + tasks = line.replace("Completed tasks so far:", "").strip().split("; ") + completed_tasks.append(0 if tasks == ['None'] else len(tasks)) + + if "Failed tasks that are too hard:" in line: + tasks = line.replace("Failed tasks that are too hard:", "").strip().split("; ") + failed_tasks.append(0 if tasks == ['None'] else len(tasks)) + check_for_info = False + round_start = False + if "metagpt.actions.minecraft.design_curriculumn" in line: + check_for_info = False + round_start = False + min_len: int = min(len(rounds), len(items_collected), len(positions), len(completed_tasks), len(failed_tasks)) + return rounds[:min_len], items_collected[:min_len], items_variety_collected[:min_len], items_collected_dict[:min_len], positions[:min_len], completed_tasks[:min_len], failed_tasks[:min_len], biomes, biomes_per_round[:min_len], new_biome_rounds +def save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix): + items_collected_total = {} + items_collected_total_list = [] + for round_index in range(len(rounds)): + for item, quantity in items_collected_dict[round_index].items(): + if item in items_collected_total: + items_collected_total[item] = max(items_collected_total[item], quantity) + else: + items_collected_total[item] = quantity + items_collected_total_list.append(sum(items_collected_total.values())) + print("总数",items_collected_total_list) + plt.figure(figsize=(10, 5)) + plt.plot(rounds, items_collected_total_list, label="Items Collected") + plt.xlabel("# of Rounds") + plt.ylabel("Total Items Collected") + plt.title("Items Collected Over Rounds") + plt.grid(True) + plt.legend() + + ax = plt.gca() + + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_items_collected_over_rounds.png', dpi=300) + plt.close() + + # 物品种类数量png + plt.figure(figsize=(10, 5)) + plt.xlabel("# of Rounds") + plt.ylabel("Total Variety of Items Collected") + plt.title("Variety of Items Collected Over Rounds") + plt.grid(True) + + special_items = ['oak_log', 'spruce_log', 'birch_log', 'jungle_log', 'dark_oak_log', 'acacia_log', 'stick', 'crafting_table', 'wooden_pickaxe', 'cobblestone', 'stone_pickaxe', 'coal', 'charcoal', 'furnace', 'blast_furnace', 'iron_ore', 'iron_ingot', 'iron_pickaxe', 'diamond', 'diamond_sword', 'diamond_pickaxe', 'diamond_axe', 'diamond_shovel', 'diamond_hoe', 'diamond_helmet', 'diamond_chestplate', 'diamond_leggings', 'diamond_boots'] + + collected_items_set = set() + items_variety_collected = [] + + for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + diff_items = list(current_round_items_set - collected_items_set) + collected_items_set.update(current_round_items_set) + items_variety_collected.append(len(collected_items_set)) + if diff_items and False: + for j, item in enumerate(diff_items): + # 判断物品类型,选择不同的背景颜色 + if item in special_items: + color = 'black' + bgcolor = 'orange' + + else : + color = 'black' + bgcolor = 'green' + # 避免文字重叠,通过调整 y 坐标的值 + y = items_variety_collected[i]-1-1*j + plt.text(rounds[i], y, item, fontsize=4, color=color, ha='center', va='top', + bbox=dict(boxstyle='round,pad=0.5', fc=bgcolor, alpha=0.5)) + + + plt.plot(rounds, items_variety_collected, label="Variety of Items Collected") + plt.legend() + + ax = plt.gca() + + # 设置坐标显示为整数 + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + # 移除所有边框 + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + # 设置网格线颜色和透明度 + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_variety_items_collected_over_rounds.png', dpi=600) + plt.close() + +def save_path_results_png(positions, start_time, path_prefix): + + x_coords = [pos[0] for pos in positions] + y_coords = [pos[1] for pos in positions] + z_coords = [pos[2] for pos in positions] + + # 计算总里程数 + total_distance = 0 + for i in range(1, len(positions)): + dx = positions[i][0] - positions[i - 1][0] + dy = positions[i][1] - positions[i - 1][1] + dz = positions[i][2] - positions[i - 1][2] + distance = math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) + total_distance += distance + + # 3D path png + fig = plt.figure(figsize=(10, 10)) + ax = fig.add_subplot(111, projection='3d') + ax.plot(x_coords, y_coords, z_coords, '-o', color='blue', markersize=4) + ax.set_title("Bot Movement Path in 3D") + ax.set_xlabel("X Coordinate") + ax.set_ylabel("Y Coordinate") + ax.set_zlabel("Z Coordinate") + ax.text(min(x_coords), max(y_coords), max(z_coords), f"Total Distance: {total_distance:.2f} units", fontsize=15, color='red') + ax.plot(x_coords[0], y_coords[0], z_coords[0], 'ro') # start point with red color + ax.plot(x_coords[-1], y_coords[-1], z_coords[-1], 'go') # end point with green color + + plt.savefig(f'{path_prefix}/{start_time}_bot_movement_3D_path.png', dpi=300) + plt.close() + +def save_task_results_png(rounds , completed, failed, start_time, path_prefix): + plt.plot(rounds, completed, label='Completed Tasks') + plt.plot(rounds, failed, label='Failed Tasks') + + plt.xlabel("# of Rounds") + plt.ylabel("Number of Tasks") + plt.title("Completed vs Failed Tasks per Round") + plt.legend() + + ax = plt.gca() + + # 设置坐标显示为整数 + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + # 移除所有边框 + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + # 设置网格线颜色和透明度 + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_task_results.png', dpi=300) + plt.close() + +def main(): + # parser = argparse.ArgumentParser(description="Analyze game log file between a start and end time.") + # parser.add_argument('--start_time', type=str, default=None, nargs='?', + # help="Start time for analysis in the log file.") + # parser.add_argument('--end_time', type=str, default=None, nargs='?', help="End time for analysis in the log file.") + # args = parser.parse_args() + + filename = r"D:\MG-MC\input\MG-1.txt" + path_prefix = r"D:\MG-MC\results_pic" + + # 自动寻找最新的实验开始时间 + start_time = extract_time_from_first_round_zero(filename) + logs_block = extract_logs(filename, start_time) + + rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks, biomes, biomes_per_round, new_biome_rounds = analyze_log_block(logs_block) + #print(positions) + #print(items_collected_dict) + + #print(completed_tasks) + #print(failed_tasks) + #print(rounds) + #print(new_biome_rounds) + #print(biomes_per_round) + #print(biomes) + + collected_items_set = set() + total_items_variety = [] + for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + collected_items_set.update(current_round_items_set) + total_items_variety.append(len(collected_items_set)) + + #save png + start_time = start_time.replace(":", "_") + save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix) + save_path_results_png(positions, start_time, path_prefix) + save_task_results_png(rounds, completed_tasks, failed_tasks, start_time, path_prefix) + #save_item_results_png(rounds, items_collected, items_variety_collected, items_collected_dict, start_time, path_prefix) + print("种类",total_items_variety) + print("轮次", rounds) + print("总数",items_collected) + print("成功",completed_tasks) + print("失败",failed_tasks) + print("位置",positions) + + data = {'rounds': rounds, + 'items_collected': items_collected, + 'total_items_variety':total_items_variety, + 'items_variety_collected': items_collected_dict, + 'positions': positions, + 'completed_tasks': completed_tasks, + 'failed_tasks': failed_tasks} + # 创建一个DataFrame + df = pd.DataFrame(data) + # 创建一个新的DataFrame,存储new_biome_rounds和biomes + df_new_biomes = pd.DataFrame({ + 'new_biome_rounds': new_biome_rounds, + 'biomes': biomes + }) + # 将新的DataFrame和原来的df进行合并 + df = pd.concat([df, df_new_biomes], axis=1) + + # 写入到Excel文件中 + df.to_excel(fr'D:\MG-MC\results_pic\{start_time}_results.xlsx', index=False) +if __name__ == "__main__": + main() From 24c5ce887e8c2cba109ed09a25b87d99ed19b8f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:43:01 +0800 Subject: [PATCH 02/11] Create MetaGPT_log_Voyager_statistical_caliber.py --- ...MetaGPT_log_Voyager_statistical_caliber.py | 378 ++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py diff --git a/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py b/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py new file mode 100644 index 000000000..61ded7cee --- /dev/null +++ b/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py @@ -0,0 +1,378 @@ +import re +import argparse +import os +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +import math +import numpy as np +import random +import seaborn as sns +import matplotlib as mpl +import pandas as pd +import ast +mpl.rcParams.update(mpl.rcParamsDefault) + +def extract_logs(filename, start_time=None, end_time=None): + with open(filename, 'r',encoding='utf-8') as f: + lines = f.readlines() + + if start_time is None : + # 如果没有提供时间参数,则返回所有日志 + return lines + + # 截取开始时间和停止时间之间的日志块 + logs_block = [] + capture = False + for line in lines: + if start_time in line: + capture = True + if capture: + logs_block.append(line) + if end_time and end_time in line: + capture = False + break + + return logs_block + +def extract_time_from_first_round_zero(log_filename): + with open(log_filename, 'r',encoding='utf-8') as f: + lines = f.readlines() + + # 正向遍历文件的每一行 + for line in lines: + if "Config loading done" in line: + # 正则表达式匹配年月日 小时:分钟的格式 + match = re.search(r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2})', line) + if match: + return match.group(1) + return None +def get_last_element_1(list, default=None): + if list: + return list[-1] + else: + return default +def get_last_element_2(list, default=0): + if list: + return list[-1] + else: + return default +def get_last_element_3(list, default={}): + if list: + return list[-1] + else: + return default +def analyze_log_block(logs_block): + absolute_rounds_current: list[int] = [] + items_collected_current :list[int] = [] + total_items = 0 + positions_current:list[(int, int, int)] = [] + completed_tasks_current: list[int] = [] + failed_tasks_current: list[int] = [] + items_variety_collected_current :list[int] = [] + items_collected_dict_current :list[dict] = [] + + absolute_rounds: list[int] = [] + items_collected :list[int] = [] + positions:list[(int, int, int)] = [] + completed_tasks: list[int] = [] + failed_tasks: list[int] = [] + items_variety_collected :list[int] = [] + items_collected_dict :list[dict] = [] + + round_start = False + check_for_info = False + line_after_message = 0 + first_group = True + round_counter = 0 + + + first_group = True # 添加一个新变量来跟踪是否已经处理过这一轮的第一组信息 + + for line in logs_block: + if "***Critic Agent human message***" in line: + round_counter += 1 + if round_counter not in absolute_rounds: + absolute_rounds.append(round_counter) + items_collected.append(get_last_element_2(items_collected_current)) + items_variety_collected.append(get_last_element_2(items_variety_collected_current)) + items_collected_dict.append(get_last_element_3(items_collected_dict_current)) + positions.append(get_last_element_1(positions_current)) + completed_tasks.append(get_last_element_2(completed_tasks_current)) + failed_tasks.append(get_last_element_2(failed_tasks_current)) + if "round_id:" in line: + round_start = True + if round_start: + if "Curriculum Agent human message" in line: + if check_for_info: # 如果已经开始解析,就跳过这一轮的剩余部分 + round_start = False + continue + check_for_info = True + line_after_message = 0 + continue + + if check_for_info: + line_after_message += 1 + + if line_after_message <= 100: + if "Position: x=" in line: + match = re.search(r'Position: x=([\d.-]+), y=([\d.-]+), z=([\d.-]+)', line) + x, y, z = float(match.group(1)), float(match.group(2)), float(match.group(3)) + positions_current.append((x, y, z)) + + if "Inventory (" in line: + if ": Empty" in line: + items_collected_current.append(0) + items = None + items_collected_dict_current.append({}) # 将这一轮结束时的物品存储状态添加到列表中 + total_items = 0 + items_variety_collected_current.append(0) # 统计物品种类数量 + else: + items = re.search(r'Inventory \(\d+/36\): ({.*?})', line).group(1) + items_dict = eval(items) + items_collected_dict_current.append(items_dict) # 将这一轮结束时的物品存储状态添加到列表中 + total_items = sum(items_dict.values()) + items_collected_current.append(total_items) + items_variety_collected_current.append(len(items_dict)) # 统计物品种类数量 + + if "Completed tasks so far:" in line: + tasks = line.replace("Completed tasks so far:", "").strip().split("; ") + completed_tasks_current.append(0 if tasks == ['None'] else len(tasks)) + + if "Failed tasks that are too hard:" in line: + tasks = line.replace("Failed tasks that are too hard:", "").strip().split("; ") + failed_tasks_current.append(0 if tasks == ['None'] else len(tasks)) + check_for_info = False + round_start = False + if "metagpt.actions.minecraft.design_curriculumn" in line: + check_for_info = False + round_start = False + + return absolute_rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks +def save_item_results_png(absolute_rounds, items_collected, items_collected_dict, start_time, path_prefix): + items_collected_total = {} + items_collected_total_list = [] + for round_index in range(len(absolute_rounds)): + for item, quantity in items_collected_dict[round_index].items(): + if item in items_collected_total: + items_collected_total[item] = max(items_collected_total[item], quantity) + else: + items_collected_total[item] = quantity + items_collected_total_list.append(sum(items_collected_total.values())) + print("总数",items_collected_total_list) + plt.figure(figsize=(10, 5)) + plt.plot(absolute_rounds, items_collected_total_list, label="Items Collected") + plt.xlabel("# of Rounds") + plt.ylabel("Total Items Collected") + plt.title("Items Collected Over Rounds") + plt.grid(True) + plt.legend() + + ax = plt.gca() + + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_items_collected_over_rounds.png', dpi=300) + plt.close() + + # 物品种类数量png + plt.figure(figsize=(10, 5)) + plt.xlabel("# of Rounds") + plt.ylabel("Total Variety of Items Collected") + plt.title("Variety of Items Collected Over Rounds") + plt.grid(True) + + special_items = ['oak_log', 'spruce_log', 'birch_log', 'jungle_log', 'dark_oak_log', 'acacia_log', 'stick', 'crafting_table', 'wooden_pickaxe', 'cobblestone', 'stone_pickaxe', 'coal', 'charcoal', 'furnace', 'blast_furnace', 'iron_ore', 'iron_ingot', 'iron_pickaxe', 'diamond', 'diamond_sword', 'diamond_pickaxe', 'diamond_axe', 'diamond_shovel', 'diamond_hoe', 'diamond_helmet', 'diamond_chestplate', 'diamond_leggings', 'diamond_boots'] + + collected_items_set = set() + items_variety_collected = [] + + for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + diff_items = list(current_round_items_set - collected_items_set) + collected_items_set.update(current_round_items_set) + items_variety_collected.append(len(collected_items_set)) + if diff_items: + for j, item in enumerate(diff_items): + # 判断物品类型,选择不同的背景颜色 + if item in special_items: + color = 'black' + bgcolor = 'orange' + + else : + color = 'black' + bgcolor = 'green' + # 避免文字重叠,通过调整 y 坐标的值 + y = items_variety_collected[i]-1-1*j + plt.text(absolute_rounds[i], y, item, fontsize=4, color=color, ha='center', va='top', + bbox=dict(boxstyle='round,pad=0.5', fc=bgcolor, alpha=0.5)) + + + plt.plot(absolute_rounds, items_variety_collected, label="Variety of Items Collected") + plt.legend() + + ax = plt.gca() + + # 设置坐标显示为整数 + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + # 移除所有边框 + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + # 设置网格线颜色和透明度 + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_variety_items_collected_over_rounds.png', dpi=600) + plt.close() + +def save_path_results_png(positions, start_time, path_prefix): + + x_coords = [pos[0] for pos in positions] + y_coords = [pos[1] for pos in positions] + z_coords = [pos[2] for pos in positions] + + # 计算总里程数 + total_distance = 0 + for i in range(1, len(positions)): + dx = positions[i][0] - positions[i - 1][0] + dy = positions[i][1] - positions[i - 1][1] + dz = positions[i][2] - positions[i - 1][2] + distance = math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) + total_distance += distance + + # 3D path png + fig = plt.figure(figsize=(10, 10)) + ax = fig.add_subplot(111, projection='3d') + ax.plot(x_coords, y_coords, z_coords, '-o', color='blue', markersize=4) + ax.set_title("Bot Movement Path in 3D") + ax.set_xlabel("X Coordinate") + ax.set_ylabel("Y Coordinate") + ax.set_zlabel("Z Coordinate") + ax.text(min(x_coords), max(y_coords), max(z_coords), f"Total Distance: {total_distance:.2f} units", fontsize=15, color='red') + ax.plot(x_coords[0], y_coords[0], z_coords[0], 'ro') # start point with red color + ax.plot(x_coords[-1], y_coords[-1], z_coords[-1], 'go') # end point with green color + + plt.savefig(f'{path_prefix}/{start_time}_bot_movement_3D_path.png', dpi=300) + plt.close() + +def save_task_results_png(absolute_rounds , completed, failed, start_time, path_prefix): + plt.plot(absolute_rounds, completed, label='Completed Tasks') + plt.plot(absolute_rounds, failed, label='Failed Tasks') + + plt.xlabel("# of Rounds") + plt.ylabel("Number of Tasks") + plt.title("Completed vs Failed Tasks per Round") + plt.legend() + + ax = plt.gca() + + # 设置坐标显示为整数 + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + # 移除所有边框 + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + # 设置网格线颜色和透明度 + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_task_results.png', dpi=300) + plt.close() + +def main(): + # parser = argparse.ArgumentParser(description="Analyze game log file between a start and end time.") + # parser.add_argument('--start_time', type=str, default=None, nargs='?', + # help="Start time for analysis in the log file.") + # parser.add_argument('--end_time', type=str, default=None, nargs='?', help="End time for analysis in the log file.") + # args = parser.parse_args() + + filename = r"D:\MG-MC\input\MG-1.txt" + path_prefix = r"D:\MG-MC\results_pic" + + # 自动寻找最新的实验开始时间 + start_time = extract_time_from_first_round_zero(filename) + logs_block = extract_logs(filename, start_time) + absolute_rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks = analyze_log_block(logs_block) + print(len(absolute_rounds)) + print(len(positions)) + print(len(items_collected_dict)) + print(len(items_variety_collected)) + #print(completed_tasks) + #print(failed_tasks) + print(positions) + print(items_collected_dict) + print(items_variety_collected) + print(completed_tasks) + print(failed_tasks) + print(absolute_rounds) + + positions_0 = [pos for pos in positions if pos is not None] + + + collected_items_set = set() + total_items_variety = [] + for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + collected_items_set.update(current_round_items_set) + total_items_variety.append(len(collected_items_set)) + print(total_items_variety) + #save png + start_time = start_time.replace(":", "_") + save_item_results_png(absolute_rounds, items_collected, items_collected_dict, start_time, path_prefix) + save_path_results_png(positions_0, start_time, path_prefix) + save_task_results_png(absolute_rounds, completed_tasks, failed_tasks, start_time, path_prefix) + #save_item_results_png(rounds, items_collected, items_variety_collected, items_collected_dict, start_time, path_prefix) + + print("种类",total_items_variety) + print("轮次", absolute_rounds) + print("总数",items_collected) + print("成功",completed_tasks) + print("失败",failed_tasks) + print("位置",positions) + + data = {'rounds': absolute_rounds, + 'items_collected': items_collected, + 'total_items_variety':total_items_variety, + 'items_variety_collected': items_collected_dict, + 'positions': positions, + 'completed_tasks': completed_tasks, + 'failed_tasks': failed_tasks} + # 创建一个DataFrame + df = pd.DataFrame(data) + + # 写入到Excel文件中 + df.to_excel(fr'D\MG-MC\results_pic\{start_time}_results.xlsx', index=False) +if __name__ == "__main__": + main() From 0efa07c4c39440890df497cc4224ed91e5971527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:51:52 +0800 Subject: [PATCH 03/11] Create Voyager_log_Voyager_statistical_caliber.py --- ...Voyager_log_Voyager_statistical_caliber.py | 349 ++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 Minecraft plot/Voyager_log_Voyager_statistical_caliber.py diff --git a/Minecraft plot/Voyager_log_Voyager_statistical_caliber.py b/Minecraft plot/Voyager_log_Voyager_statistical_caliber.py new file mode 100644 index 000000000..009f73f19 --- /dev/null +++ b/Minecraft plot/Voyager_log_Voyager_statistical_caliber.py @@ -0,0 +1,349 @@ +import re +import argparse +import os +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +import math +import numpy as np +import random +import seaborn as sns +import matplotlib as mpl +import pandas as pd +mpl.rcParams.update(mpl.rcParamsDefault) + +def extract_logs(filename, start_time=None, end_time=None): + with open(filename, 'r',encoding='utf-8') as f: + lines = f.readlines() + + if start_time is None : + # 如果没有提供时间参数,则返回所有日志 + return lines + + # 截取开始时间和停止时间之间的日志块 + logs_block = [] + capture = False + for line in lines: + if start_time in line: + capture = True + if capture: + logs_block.append(line) + if end_time and end_time in line: + capture = False + break + + return logs_block + +def extract_time_from_first_round_zero(log_filename): + with open(log_filename, 'r',encoding='utf-8') as f: + lines = f.readlines() + + # 反向遍历文件的每一行 + for line in reversed(lines): + if "****Recorder message:" in line: + if "iteration passed****" in line: + round_number = re.search(r'(\d+) iteration passed', line).group(1) + return round_number + return None + + +def analyze_log_block(logs_block): + rounds: list[int] = [] + items_collected: list[int] = [] + total_items = 0 + positions:list[(int, int, int)] = [] + completed_tasks: list[int] = [] + failed_tasks: list[int] = [] + items_variety_collected :list[int] = [] + items_collected_dict :list[dict] = [] + biomes: list[str] = [] # 存储所有出现过的生物群系 + biomes_per_round: list[list[str]] = [] # 存储每轮结束时已经经历过的生物群系 + new_biome_rounds: list[int] = [] # 存储添加新生物群系的轮次 + processing_block = False # 用于标记是否正在处理一个块 + round_counter = 0 # 用于计数轮数 + # Define the latest parameters + latest_items_collected = latest_items_variety_collected = latest_completed_tasks = latest_failed_tasks = latest_positions = latest_items_collected_dict = None + for line in logs_block: + if "****Curriculum Agent human message****" in line: + processing_block = True # 当找到新的 "****Curriculum Agent human message****" 时开始处理块 + continue + + if "****Curriculum Agent ai message****" in line: + processing_block = False # 当找到 "****Curriculum Agent ai message****" 时停止处理块 + continue + + if processing_block: # 如果正在处理一个块,则执行以下操作 + # Update the latest parameters + if "Position: x=" in line: + match = re.search(r'Position: x=([\d.-]+), y=([\d.-]+), z=([\d.-]+)', line) + x, y, z = float(match.group(1)), float(match.group(2)), float(match.group(3)) + latest_positions = (x, y, z) + + if "Inventory (" in line: + items = re.search(r'Inventory \(\d+/36\): ({.*?})', line).group(1) + items_dict = eval(items) + latest_items_collected_dict = items_dict # 将这一轮结束时的物品存储状态添加到列表中 + total_items = sum(items_dict.values()) + latest_items_collected = total_items + latest_items_variety_collected = len(items_dict) # 统计物品种类数量 + + if "Completed tasks so far:" in line: + tasks = line.replace("Completed tasks so far:", "").strip().split(", ") + latest_completed_tasks = 0 if tasks == ['None'] else len(tasks) + + if "Failed tasks that are too hard:" in line: + tasks = line.replace("Failed tasks that are too hard:", "").strip().split(", ") + latest_failed_tasks = 0 if tasks == ['None'] else len(tasks) + if "****Recorder message:" in line: + if "iteration passed" in line: + round_counter = int(re.search(r'Recorder message: (\d+) iteration passed', line).group(1)) + rounds.append(round_counter) + # Append the latest parameters to their lists + items_collected.append(latest_items_collected) + items_variety_collected.append(latest_items_variety_collected) + completed_tasks.append(latest_completed_tasks) + failed_tasks.append(latest_failed_tasks) + positions.append(latest_positions) + items_collected_dict.append(latest_items_collected_dict) + min_len: int = min(len(rounds), len(items_collected), len(positions), len(completed_tasks), len(failed_tasks)) + return rounds[:min_len], items_collected[:min_len], items_variety_collected[:min_len], items_collected_dict[:min_len], positions[:min_len], completed_tasks[:min_len], failed_tasks[:min_len], biomes, biomes_per_round[:min_len], new_biome_rounds +def save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix): + items_collected_total = {} + items_collected_total_list = [] + for round_index in range(len(rounds)): + for item, quantity in items_collected_dict[round_index].items(): + if item in items_collected_total: + items_collected_total[item] = max(items_collected_total[item], quantity) + else: + items_collected_total[item] = quantity + items_collected_total_list.append(sum(items_collected_total.values())) + print("总数",items_collected_total_list) + plt.figure(figsize=(10, 5)) + plt.plot(rounds, items_collected_total_list, label="Items Collected") + plt.xlabel("# of Rounds") + plt.ylabel("Total Items Collected") + plt.title("Items Collected Over Rounds") + plt.grid(True) + plt.legend() + + ax = plt.gca() + + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_items_collected_over_rounds.png', dpi=300) + plt.close() + + + # 物品种类数量png + plt.figure(figsize=(10, 5)) + plt.xlabel("# of Rounds") + plt.ylabel("Total Variety of Items Collected") + plt.title("Variety of Items Collected Over Rounds") + plt.grid(True) + + special_items = ['wood', 'crafting_table', 'wooden_pickaxe', 'wooden_sword', 'wooden_axe', 'wooden_shovel', 'wooden_hoe', + 'stone', 'furnace', 'stone_pickaxe', 'stone_sword', 'stone_axe', 'stone_shovel', 'stone_hoe', + 'iron_ingot', 'iron_pickaxe', 'iron_sword', 'iron_axe', 'iron_shovel', 'iron_hoe', + 'diamond', 'diamond_pickaxe', 'diamond_sword', 'diamond_axe', 'diamond_shovel', 'diamond_hoe'] + + collected_items_set = set() + items_variety_collected = [] + for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + diff_items = list(current_round_items_set - collected_items_set) + collected_items_set.update(current_round_items_set) + items_variety_collected.append(len(collected_items_set)) + if diff_items: + for j, item in enumerate(diff_items): + # 判断物品类型,选择不同的背景颜色 + if item in special_items: + color = 'black' + bgcolor = 'orange' + else: + color = 'black' + bgcolor = 'green' + # 避免文字重叠,通过调整 y 坐标的值 + y = items_variety_collected[i]-1-1*j + + plt.text(rounds[i], y, item, fontsize=4, color=color, ha='center', va='top', + bbox=dict(boxstyle='round,pad=0.5', fc=bgcolor, alpha=0.5)) + """for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + diff_items = list(current_round_items_set - collected_items_set) + collected_items_set.update(current_round_items_set) + items_variety_collected.append(len(collected_items_set)) + if diff_items: + for j, item in enumerate(diff_items): + color = 'red' if item in special_items else 'black' + plt.text(rounds[i], items_variety_collected[i] - 1 - j * 0.4, item, fontsize=8, color=color, ha='center', va='top', + bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.5))""" + plt.plot(rounds, items_variety_collected, label="Variety of Items Collected") + plt.legend() + + ax = plt.gca() + + # 设置坐标显示为整数 + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + # 移除所有边框 + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + # 设置网格线颜色和透明度 + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_variety_items_collected_over_rounds.png', dpi=600) + plt.close() + +def save_path_results_png(positions, start_time, path_prefix): + + x_coords = [pos[0] for pos in positions] + y_coords = [pos[1] for pos in positions] + z_coords = [pos[2] for pos in positions] + + # 计算总里程数 + total_distance = 0 + for i in range(1, len(positions)): + dx = positions[i][0] - positions[i - 1][0] + dy = positions[i][1] - positions[i - 1][1] + dz = positions[i][2] - positions[i - 1][2] + distance = math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) + total_distance += distance + + # 3D path png + fig = plt.figure(figsize=(10, 10)) + ax = fig.add_subplot(111, projection='3d') + ax.plot(x_coords, y_coords, z_coords, color='blue', markersize=4) + ax.set_title("Bot Movement Path in 3D") + ax.set_xlabel("X Coordinate") + ax.set_ylabel("Y Coordinate") + ax.set_zlabel("Z Coordinate") + ax.text(min(x_coords), max(y_coords), max(z_coords), f"Total Distance: {total_distance:.2f} units", fontsize=15, color='red') + ax.plot(x_coords[0], y_coords[0], z_coords[0], 'ro') # start point with red color + ax.plot(x_coords[-1], y_coords[-1], z_coords[-1], 'go') # end point with green color + + plt.savefig(f'{path_prefix}/{start_time}_bot_movement_3D_path.png', dpi=300) + plt.close() + +def save_task_results_png(rounds , completed, failed, start_time, path_prefix): + plt.plot(rounds, completed, label='Completed Tasks') + plt.plot(rounds, failed, label='Failed Tasks') + + plt.xlabel("# of Rounds") + plt.ylabel("Number of Tasks") + plt.title("Completed vs Failed Tasks per Round") + plt.legend() + + ax = plt.gca() + + # 设置坐标显示为整数 + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + # 移除所有边框 + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + # 设置网格线颜色和透明度 + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_task_results.png', dpi=300) + plt.close() + +def main(): + # parser = argparse.ArgumentParser(description="Analyze game log file between a start and end time.") + # parser.add_argument('--start_time', type=str, default=None, nargs='?', + # help="Start time for analysis in the log file.") + # parser.add_argument('--end_time', type=str, default=None, nargs='?', help="End time for analysis in the log file.") + # args = parser.parse_args() + + filename = r"D:\MG-MC\input\VG-1.txt" + path_prefix = r"D:\MG-MC\results_pic" + + # 自动寻找最新的实验开始时间 + start_time = extract_time_from_first_round_zero(filename) + logs_block = extract_logs(filename) + + rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks, biomes, biomes_per_round, new_biome_rounds = analyze_log_block(logs_block) + print(positions) + print(items_collected_dict) + print(items_variety_collected) + print(completed_tasks) + print(failed_tasks) + print(rounds) + + positions_0 = [pos for pos in positions if pos is not None] + items_collected_dict = [item if item is not None else {} for item in items_collected_dict] + + collected_items_set = set() + total_items_variety = [] + for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + collected_items_set.update(current_round_items_set) + total_items_variety.append(len(collected_items_set)) + print(total_items_variety) + #save png + start_time = start_time.replace(":", "_") + save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix) + save_path_results_png(positions_0, start_time, path_prefix) + save_task_results_png(rounds, completed_tasks, failed_tasks, start_time, path_prefix) + #save_item_results_png(rounds, items_collected, items_variety_collected, items_collected_dict, start_time, path_prefix) + + print("种类",total_items_variety) + print("轮次", rounds) + print("总数",items_collected) + print("成功",completed_tasks) + print("失败",failed_tasks) + print("位置",positions) + + data = {'rounds': rounds, + 'items_collected': items_collected, + 'total_items_variety':total_items_variety, + 'items_variety_collected': items_collected_dict, + 'positions': positions, + 'completed_tasks': completed_tasks, + 'failed_tasks': failed_tasks} + # 创建一个DataFrame + df = pd.DataFrame(data) + # 创建一个新的DataFrame,存储new_biome_rounds和biomes + df_new_biomes = pd.DataFrame({ + 'new_biome_rounds': new_biome_rounds, + 'biomes': biomes + }) + # 将新的DataFrame和原来的df进行合并 + df = pd.concat([df, df_new_biomes], axis=1) + + # 写入到Excel文件中 + df.to_excel(fr'D:\MG-MC\results_pic\{start_time}_results.xlsx', index=False) +if __name__ == "__main__": + main() From 4c0f7287d7641c77c478208e5128e2ef4aa64de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:55:08 +0800 Subject: [PATCH 04/11] Create Voyager_log_MetaGPT_statistical_caliber.py --- ...Voyager_log_MetaGPT_statistical_caliber.py | 382 ++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 Minecraft plot/Voyager_log_MetaGPT_statistical_caliber.py diff --git a/Minecraft plot/Voyager_log_MetaGPT_statistical_caliber.py b/Minecraft plot/Voyager_log_MetaGPT_statistical_caliber.py new file mode 100644 index 000000000..c415c5f44 --- /dev/null +++ b/Minecraft plot/Voyager_log_MetaGPT_statistical_caliber.py @@ -0,0 +1,382 @@ +import re +import argparse +import os +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +import math +import numpy as np +import random +import seaborn as sns +import matplotlib as mpl +import pandas as pd +mpl.rcParams.update(mpl.rcParamsDefault) + +def extract_logs(filename, start_time=None, end_time=None): + with open(filename, 'r',encoding='utf-8') as f: + lines = f.readlines() + + if start_time is None : + # 如果没有提供时间参数,则返回所有日志 + return lines + + # 截取开始时间和停止时间之间的日志块 + logs_block = [] + capture = False + for line in lines: + if start_time in line: + capture = True + if capture: + logs_block.append(line) + if end_time and end_time in line: + capture = False + break + + return logs_block + +def extract_time_from_first_round_zero(log_filename): + with open(log_filename, 'r',encoding='utf-8') as f: + lines = f.readlines() + + # 反向遍历文件的每一行 + for line in reversed(lines): + if "****Recorder message:" in line: + if "iteration passed****" in line: + round_number = re.search(r'(\d+) iteration passed', line).group(1) + return round_number + return None + +"""def analyze_log_block(logs_block): + rounds: list[int] = [] + items_collected: list[int] = [] + total_items = 0 + positions:list[(int, int, int)] = [] + completed_tasks: list[int] = [] + failed_tasks: list[int] = [] + items_variety_collected :list[int] = [] + items_collected_dict :list[dict] = [] + line_counter = 0 # 用于计数 + round_counter = 0 # 用于计数轮数 + for line in logs_block: + if "****Curriculum Agent human message****" in line: + line_counter = 0 # 当找到新的 "****Curriculum Agent human message****" 时重置计数器 + round_counter += 1 # 每次找到 "****Curriculum Agent human message****",轮数加1 + rounds.append(round_counter) # 将新的轮数添加到轮数列表中 + continue + + if line_counter < 50: + if "Position: x=" in line: + match = re.search(r'Position: x=([\d.-]+), y=([\d.-]+), z=([\d.-]+)', line) + x, y, z = float(match.group(1)), float(match.group(2)), float(match.group(3)) + positions.append((x, y, z)) + + if "Inventory (" in line: + items = re.search(r'Inventory \(\d+/36\): ({.*?})', line).group(1) + items_dict = eval(items) + items_collected_dict.append(items_dict) # 将这一轮结束时的物品存储状态添加到列表中 + total_items = sum(items_dict.values()) + items_collected.append(total_items) + items_variety_collected.append(len(items_dict)) # 统计物品种类数量 + + if "Completed tasks so far:" in line: + tasks = line.replace("Completed tasks so far:", "").strip().split(", ") + completed_tasks.append(0 if tasks == ['None'] else len(tasks)) + + if "Failed tasks that are too hard:" in line: + tasks = line.replace("Failed tasks that are too hard:", "").strip().split(", ") + failed_tasks.append(0 if tasks == ['None'] else len(tasks)) + + line_counter += 1 # 每处理一行就将计数器加1""" +def analyze_log_block(logs_block): + rounds: list[int] = [] + items_collected: list[int] = [] + total_items = 0 + positions:list[(int, int, int)] = [] + completed_tasks: list[int] = [] + failed_tasks: list[int] = [] + items_variety_collected :list[int] = [] + items_collected_dict :list[dict] = [] + biomes: list[str] = [] # 存储所有出现过的生物群系 + biomes_per_round: list[list[str]] = [] # 存储每轮结束时已经经历过的生物群系 + new_biome_rounds: list[int] = [] # 存储添加新生物群系的轮次 + processing_block = False # 用于标记是否正在处理一个块 + round_counter = 0 # 用于计数轮数 + for line in logs_block: + if "****Curriculum Agent human message****" in line: + processing_block = True # 当找到新的 "****Curriculum Agent human message****" 时开始处理块 + round_counter += 1 # 每次找到 "****Curriculum Agent human message****",轮数加1 + rounds.append(round_counter) # 将新的轮数添加到轮数列表中 + continue + + if "****Curriculum Agent ai message****" in line: + processing_block = False # 当找到 "****Curriculum Agent ai message****" 时停止处理块 + continue + + if processing_block: # 如果正在处理一个块,则执行以下操作 + if "Position: x=" in line: + match = re.search(r'Position: x=([\d.-]+), y=([\d.-]+), z=([\d.-]+)', line) + x, y, z = float(match.group(1)), float(match.group(2)), float(match.group(3)) + positions.append((x, y, z)) + + if "Inventory (" in line: + items = re.search(r'Inventory \(\d+/36\): ({.*?})', line).group(1) + items_dict = eval(items) + items_collected_dict.append(items_dict) # 将这一轮结束时的物品存储状态添加到列表中 + total_items = sum(items_dict.values()) + items_collected.append(total_items) + items_variety_collected.append(len(items_dict)) # 统计物品种类数量 + if "Biome: " in line: + biome = line.replace("Biome: ", "").strip() + if biome not in biomes: + biomes.append(biome) + new_biome_rounds.append(rounds[-1]) # 记录添加新生物群系的轮次 + biomes_per_round.append(biomes.copy()) # 记录当前已经经历过 + + if "Completed tasks so far:" in line: + tasks = line.replace("Completed tasks so far:", "").strip().split(", ") + completed_tasks.append(0 if tasks == ['None'] else len(tasks)) + + if "Failed tasks that are too hard:" in line: + tasks = line.replace("Failed tasks that are too hard:", "").strip().split(", ") + failed_tasks.append(0 if tasks == ['None'] else len(tasks)) + min_len: int = min(len(rounds), len(items_collected), len(positions), len(completed_tasks), len(failed_tasks)) + return rounds[:min_len], items_collected[:min_len], items_variety_collected[:min_len], items_collected_dict[:min_len], positions[:min_len], completed_tasks[:min_len], failed_tasks[:min_len], biomes, biomes_per_round[:min_len], new_biome_rounds +def save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix): + items_collected_total = {} + items_collected_total_list = [] + for round_index in range(len(rounds)): + for item, quantity in items_collected_dict[round_index].items(): + if item in items_collected_total: + items_collected_total[item] = max(items_collected_total[item], quantity) + else: + items_collected_total[item] = quantity + items_collected_total_list.append(sum(items_collected_total.values())) + print("总数",items_collected_total_list) + plt.figure(figsize=(10, 5)) + plt.plot(rounds, items_collected_total_list, label="Items Collected") + plt.xlabel("# of Rounds") + plt.ylabel("Total Items Collected") + plt.title("Items Collected Over Rounds") + plt.grid(True) + plt.legend() + + ax = plt.gca() + + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_items_collected_over_rounds.png', dpi=300) + plt.close() + + + # 物品种类数量png + plt.figure(figsize=(10, 5)) + plt.xlabel("# of Rounds") + plt.ylabel("Total Variety of Items Collected") + plt.title("Variety of Items Collected Over Rounds") + plt.grid(True) + + special_items = ['wood', 'crafting_table', 'wooden_pickaxe', 'wooden_sword', 'wooden_axe', 'wooden_shovel', 'wooden_hoe', + 'stone', 'furnace', 'stone_pickaxe', 'stone_sword', 'stone_axe', 'stone_shovel', 'stone_hoe', + 'iron_ingot', 'iron_pickaxe', 'iron_sword', 'iron_axe', 'iron_shovel', 'iron_hoe', + 'diamond', 'diamond_pickaxe', 'diamond_sword', 'diamond_axe', 'diamond_shovel', 'diamond_hoe'] + + collected_items_set = set() + items_variety_collected = [] + for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + diff_items = list(current_round_items_set - collected_items_set) + collected_items_set.update(current_round_items_set) + items_variety_collected.append(len(collected_items_set)) + if diff_items: + for j, item in enumerate(diff_items): + # 判断物品类型,选择不同的背景颜色 + if item in special_items: + color = 'black' + bgcolor = 'orange' + else: + color = 'black' + bgcolor = 'green' + # 避免文字重叠,通过调整 y 坐标的值 + y = items_variety_collected[i]-1-1*j + + plt.text(rounds[i], y, item, fontsize=4, color=color, ha='center', va='top', + bbox=dict(boxstyle='round,pad=0.5', fc=bgcolor, alpha=0.5)) + """for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + diff_items = list(current_round_items_set - collected_items_set) + collected_items_set.update(current_round_items_set) + items_variety_collected.append(len(collected_items_set)) + if diff_items: + for j, item in enumerate(diff_items): + color = 'red' if item in special_items else 'black' + plt.text(rounds[i], items_variety_collected[i] - 1 - j * 0.4, item, fontsize=8, color=color, ha='center', va='top', + bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.5))""" + plt.plot(rounds, items_variety_collected, label="Variety of Items Collected") + plt.legend() + + ax = plt.gca() + + # 设置坐标显示为整数 + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + # 移除所有边框 + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + # 设置网格线颜色和透明度 + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_variety_items_collected_over_rounds.png', dpi=600) + plt.close() + +def save_path_results_png(positions, start_time, path_prefix): + + x_coords = [pos[0] for pos in positions] + y_coords = [pos[1] for pos in positions] + z_coords = [pos[2] for pos in positions] + + # 计算总里程数 + total_distance = 0 + for i in range(1, len(positions)): + dx = positions[i][0] - positions[i - 1][0] + dy = positions[i][1] - positions[i - 1][1] + dz = positions[i][2] - positions[i - 1][2] + distance = math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) + total_distance += distance + + # 3D path png + fig = plt.figure(figsize=(10, 10)) + ax = fig.add_subplot(111, projection='3d') + ax.plot(x_coords, y_coords, z_coords, '-o', color='blue', markersize=4) + ax.set_title("Bot Movement Path in 3D") + ax.set_xlabel("X Coordinate") + ax.set_ylabel("Y Coordinate") + ax.set_zlabel("Z Coordinate") + ax.text(min(x_coords), max(y_coords), max(z_coords), f"Total Distance: {total_distance:.2f} units", fontsize=15, color='red') + ax.plot(x_coords[0], y_coords[0], z_coords[0], 'ro') # start point with red color + ax.plot(x_coords[-1], y_coords[-1], z_coords[-1], 'go') # end point with green color + + plt.savefig(f'{path_prefix}/{start_time}_bot_movement_3D_path.png', dpi=300) + plt.close() + +def save_task_results_png(rounds , completed, failed, start_time, path_prefix): + plt.plot(rounds, completed, label='Completed Tasks') + plt.plot(rounds, failed, label='Failed Tasks') + + plt.xlabel("# of Rounds") + plt.ylabel("Number of Tasks") + plt.title("Completed vs Failed Tasks per Round") + plt.legend() + + ax = plt.gca() + + # 设置坐标显示为整数 + ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True)) + ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) + + # 移除所有边框 + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + + # 设置网格线颜色和透明度 + ax.grid(color='gray', linestyle='-', linewidth=0.3, alpha=0.2) + + # 设置x轴和y轴的箭头 + ax.annotate('', xy=(1, 0), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + ax.annotate('', xy=(0, 1), xycoords='axes fraction', xytext=(0, 0), + arrowprops=dict(arrowstyle="->", color='black')) + + plt.savefig(f'{path_prefix}/{start_time}_task_results.png', dpi=300) + plt.close() + +def main(): + # parser = argparse.ArgumentParser(description="Analyze game log file between a start and end time.") + # parser.add_argument('--start_time', type=str, default=None, nargs='?', + # help="Start time for analysis in the log file.") + # parser.add_argument('--end_time', type=str, default=None, nargs='?', help="End time for analysis in the log file.") + # args = parser.parse_args() + + filename = r"C:\Users\86151\Desktop\数模国赛\新建文件夹\input\VG-2.txt" + path_prefix = r"C:\Users\86151\Desktop\数模国赛\新建文件夹\input\results_pic" + + # 自动寻找最新的实验开始时间 + filename = r"D:\MG-MC\input\VG-1.txt" + path_prefix = r"D:\MG-MC\results_pic" + + rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks, biomes, biomes_per_round, new_biome_rounds = analyze_log_block(logs_block) + """ print(positions) + print(items_collected_dict) + print(items_variety_collected) + print(completed_tasks) + print(failed_tasks) + print(rounds) + print(new_biome_rounds)""" + #print(biomes_per_round) + #print(biomes) + collected_items_set = set() + total_items_variety = [] + for i in range(0, len(items_collected_dict)): + current_round_items_set = set(items_collected_dict[i]) + collected_items_set.update(current_round_items_set) + total_items_variety.append(len(collected_items_set)) + print(total_items_variety) + #save png + start_time = start_time.replace(":", "_") + save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix) + save_path_results_png(positions, start_time, path_prefix) + save_task_results_png(rounds, completed_tasks, failed_tasks, start_time, path_prefix) + #save_item_results_png(rounds, items_collected, items_variety_collected, items_collected_dict, start_time, path_prefix) + + print("种类",total_items_variety) + print("轮次", rounds) + print("总数",items_collected) + print("成功",completed_tasks) + print("失败",failed_tasks) + print("位置",positions) + + data = {'rounds': rounds, + 'items_collected': items_collected, + 'total_items_variety':total_items_variety, + 'items_variety_collected': items_collected_dict, + 'positions': positions, + 'completed_tasks': completed_tasks, + 'failed_tasks': failed_tasks} + # 创建一个DataFrame + df = pd.DataFrame(data) + # 创建一个新的DataFrame,存储new_biome_rounds和biomes + df_new_biomes = pd.DataFrame({ + 'new_biome_rounds': new_biome_rounds, + 'biomes': biomes + }) + # 将新的DataFrame和原来的df进行合并 + df = pd.concat([df, df_new_biomes], axis=1) + + # 写入到Excel文件中 + df.to_excel(fr'D:\MG-MC\results_pic\{start_time}_results.xlsx', index=False) +if __name__ == "__main__": + main() From ce66b3a1dffea6ae8517fdbae8a4ad1c3404b00f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Mon, 23 Oct 2023 17:02:12 +0800 Subject: [PATCH 05/11] Create MetaGPT_vs_Voyager.m --- Minecraft plot/MetaGPT_vs_Voyager.m | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Minecraft plot/MetaGPT_vs_Voyager.m diff --git a/Minecraft plot/MetaGPT_vs_Voyager.m b/Minecraft plot/MetaGPT_vs_Voyager.m new file mode 100644 index 000000000..812e4d671 --- /dev/null +++ b/Minecraft plot/MetaGPT_vs_Voyager.m @@ -0,0 +1,68 @@ +y1 = {[1, 1, 4, 4, 4, 4, 5, 13, 13, 14, 15, 17, 19, 19, 22, 22, 23, 23, 24, 24, 24, 24, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26]; + [1, 1, 1, 1, 4, 4, 4, 4, 9, 9, 9, 12, 12, 13, 13, 15, 16, 16, 16, 16, 19, 20, 20, 20, 21, 22, 24, 24, 24, 24, 25, 27, 27, 27, 27, 31, 31, 31]; + [1, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 9, 10, 11, 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 19, 20, 20, 20, 20, 20, 21, 23, 24, 24, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 29, 30, 30, 32, 32, 33, 34, 34, 34, 34, 37, 37]; + [0, 1, 1, 3, 4, 4, 8, 9, 9, 9, 10, 10, 11, 11, 14, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 20, 20, 20, 20, 23, 24, 25, 27, 30, 30, 30, 30, 30, 30, 30, 30, 30, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42]; + [1, 1, 1, 2, 5, 7, 8, 9, 9, 9, 9, 9, 10, 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 20, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 25, 25, 26, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 32, 32, 32, 32, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 40, 40, 40, 40, 41, 42, 42]; + [1, 1, 1, 2, 3, 3, 3, 3, 5, 6, 6, 8, 9, 10, 10, 12, 12, 12, 12, 12, 12, 13, 14, 15, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24, 25, 27, 27, 28]}; +每个元素是一个向量代表一个曲线的x坐标 +x = {1:1:33;1:1:38;1:1:57;1:1:82;1:1:81;1:1:38}; + +% 创建共享的x向量,其范围是从0到最大的x值,步长为1 +shared_x = 0:1:max(cellfun(@max,x)); + +% 将y1和x拆分为MetaGPT和Voyager两部分 +y1_MetaGPT = y1(1:4); +x_MetaGPT = x(1:4); +y1_Voyager = y1(5:6); +x_Voyager = x(5:6); + +% 对MetaGPT部分进行插值和计算上下限 +interp_y1_MetaGPT = cellfun(@(y, x) interp1(x, y, shared_x, 'linear', 'extrap'), y1_MetaGPT, x_MetaGPT, 'UniformOutput', false); +minY_MetaGPT = min(cell2mat(interp_y1_MetaGPT)); +maxY_MetaGPT = max(cell2mat(interp_y1_MetaGPT)); + +% 对Voyager部分进行插值和计算上下限 +interp_y1_Voyager = cellfun(@(y, x) interp1(x, y, shared_x, 'linear', 'extrap'), y1_Voyager, x_Voyager, 'UniformOutput', false); +minY_Voyager = min(cell2mat(interp_y1_Voyager)); +maxY_Voyager = max(cell2mat(interp_y1_Voyager)); +% 计算MetaGPT和Voyager的均值 +meanY_MetaGPT = mean(cell2mat(interp_y1_MetaGPT)); +meanY_Voyager = mean(cell2mat(interp_y1_Voyager)); + +% 绘图 +figure +hold on + +% 绘制MetaGPT的均值曲线,颜色设为蓝色 +h1=plot(shared_x, meanY_MetaGPT, 'b', 'LineWidth', 2); + +% 绘制MetaGPT的上下限范围,颜色设为蓝色 +h2=fill([shared_x, fliplr(shared_x)], [minY_MetaGPT, fliplr(maxY_MetaGPT)], 'b', 'FaceAlpha', 0.2, 'EdgeColor', 'none'); + +% 绘制Voyager的均值曲线,颜色设为红色 +h3=plot(shared_x, meanY_Voyager, 'r', 'LineWidth', 2); + +% 绘制Voyager的上下限范围,颜色设为红色 +h4=fill([shared_x, fliplr(shared_x)], [minY_Voyager, fliplr(maxY_Voyager)], 'r', 'FaceAlpha', 0.2, 'EdgeColor', 'none'); + +%绘制MetaGPT的每一条曲线 + +for i = 1:length(y1_MetaGPT) + plot(x_MetaGPT{i}, y1_MetaGPT{i}, 'b--'); % 使用蓝色虚线 +end + +% 绘制Voyager的每一条曲线 +for i = 1:length(y1_Voyager) + plot(x_Voyager{i}, y1_Voyager{i}, 'r--'); % 使用红色虚线 +end + +% 设置坐标轴范围和标签 +xlim([0 35]) % x轴范围设为最大的x值 +ylim([0 35]) +xlabel('# of Rounds') +ylabel('Total Variety of Items Collected') + +% 设置标题和图例(假设每条线代表一个方法) +legend([h1,h2,h3,h4],'MetaGPT Mean','MetaGPT Range', 'Voyager Mean','Voyager Range') + +hold off From ff34a361ddad5d6f9cf4d780e3565018f72ee704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Tue, 24 Oct 2023 01:32:04 +0800 Subject: [PATCH 06/11] Update MetaGPT_log_MetaGPT_statistical_caliber.py --- ...MetaGPT_log_MetaGPT_statistical_caliber.py | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/Minecraft plot/MetaGPT_log_MetaGPT_statistical_caliber.py b/Minecraft plot/MetaGPT_log_MetaGPT_statistical_caliber.py index 5754f33ba..b0ff15ac7 100644 --- a/Minecraft plot/MetaGPT_log_MetaGPT_statistical_caliber.py +++ b/Minecraft plot/MetaGPT_log_MetaGPT_statistical_caliber.py @@ -12,7 +12,7 @@ import pandas as pd mpl.rcParams.update(mpl.rcParamsDefault) def extract_logs(filename, start_time=None, end_time=None): - with open(filename, 'r',encoding='utf-8') as f: + with open(filename, 'r', encoding='utf-8') as f: lines = f.readlines() if start_time is None : @@ -34,7 +34,7 @@ def extract_logs(filename, start_time=None, end_time=None): return logs_block def extract_time_from_first_round_zero(log_filename): - with open(log_filename, 'r',encoding='utf-8') as f: + with open(log_filename, 'r', encoding='utf-8') as f: lines = f.readlines() # 正向遍历文件的每一行 @@ -64,8 +64,6 @@ def analyze_log_block(logs_block): first_group = True - first_group = True # 添加一个新变量来跟踪是否已经处理过这一轮的第一组信息 - for line in logs_block: if "round_id:" in line: n = int(re.search(r'round_id:(\d+)', line).group(1)) @@ -125,6 +123,8 @@ def analyze_log_block(logs_block): round_start = False min_len: int = min(len(rounds), len(items_collected), len(positions), len(completed_tasks), len(failed_tasks)) return rounds[:min_len], items_collected[:min_len], items_variety_collected[:min_len], items_collected_dict[:min_len], positions[:min_len], completed_tasks[:min_len], failed_tasks[:min_len], biomes, biomes_per_round[:min_len], new_biome_rounds + + def save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix): items_collected_total = {} items_collected_total_list = [] @@ -289,29 +289,23 @@ def save_task_results_png(rounds , completed, failed, start_time, path_prefix): plt.close() def main(): - # parser = argparse.ArgumentParser(description="Analyze game log file between a start and end time.") - # parser.add_argument('--start_time', type=str, default=None, nargs='?', - # help="Start time for analysis in the log file.") - # parser.add_argument('--end_time', type=str, default=None, nargs='?', help="End time for analysis in the log file.") - # args = parser.parse_args() - filename = r"D:\MG-MC\input\MG-1.txt" - path_prefix = r"D:\MG-MC\results_pic" + # 获取当前脚本的路径 + current_script_path = os.path.dirname(os.path.abspath(__file__)) + + # 构建其他文件的路径 + filename = os.path.join(current_script_path, 'input', 'MG-1.txt') + path_prefix = os.path.join(current_script_path, 'results_pic') + + # 确保输出路径存在 + os.makedirs(path_prefix, exist_ok=True) # 自动寻找最新的实验开始时间 start_time = extract_time_from_first_round_zero(filename) logs_block = extract_logs(filename, start_time) rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks, biomes, biomes_per_round, new_biome_rounds = analyze_log_block(logs_block) - #print(positions) - #print(items_collected_dict) - - #print(completed_tasks) - #print(failed_tasks) - #print(rounds) - #print(new_biome_rounds) - #print(biomes_per_round) - #print(biomes) + collected_items_set = set() total_items_variety = [] @@ -351,6 +345,6 @@ def main(): df = pd.concat([df, df_new_biomes], axis=1) # 写入到Excel文件中 - df.to_excel(fr'D:\MG-MC\results_pic\{start_time}_results.xlsx', index=False) + df.to_excel(os.path.join(path_prefix, f'{start_time}_results.xlsx'), index=False) if __name__ == "__main__": main() From d57452d54f8a080c3a7e8b89bcb30ce0185847c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Tue, 24 Oct 2023 01:32:45 +0800 Subject: [PATCH 07/11] Update MetaGPT_log_Voyager_statistical_caliber.py --- ...MetaGPT_log_Voyager_statistical_caliber.py | 45 +++++++++---------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py b/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py index 61ded7cee..c1fdbb02f 100644 --- a/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py +++ b/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py @@ -1,3 +1,4 @@ +#MG-VG import re import argparse import os @@ -13,7 +14,7 @@ import ast mpl.rcParams.update(mpl.rcParamsDefault) def extract_logs(filename, start_time=None, end_time=None): - with open(filename, 'r',encoding='utf-8') as f: + with open(filename, 'r', encoding='utf-8') as f: lines = f.readlines() if start_time is None : @@ -35,7 +36,7 @@ def extract_logs(filename, start_time=None, end_time=None): return logs_block def extract_time_from_first_round_zero(log_filename): - with open(log_filename, 'r',encoding='utf-8') as f: + with open(log_filename, 'r', encoding='utf-8') as f: lines = f.readlines() # 正向遍历文件的每一行 @@ -46,21 +47,25 @@ def extract_time_from_first_round_zero(log_filename): if match: return match.group(1) return None + def get_last_element_1(list, default=None): if list: return list[-1] else: return default + def get_last_element_2(list, default=0): if list: return list[-1] else: return default + def get_last_element_3(list, default={}): if list: return list[-1] else: return default + def analyze_log_block(logs_block): absolute_rounds_current: list[int] = [] items_collected_current :list[int] = [] @@ -148,6 +153,7 @@ def analyze_log_block(logs_block): round_start = False return absolute_rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks + def save_item_results_png(absolute_rounds, items_collected, items_collected_dict, start_time, path_prefix): items_collected_total = {} items_collected_total_list = [] @@ -278,7 +284,7 @@ def save_path_results_png(positions, start_time, path_prefix): plt.savefig(f'{path_prefix}/{start_time}_bot_movement_3D_path.png', dpi=300) plt.close() -def save_task_results_png(absolute_rounds , completed, failed, start_time, path_prefix): +def save_task_results_png(absolute_rounds, completed, failed, start_time, path_prefix): plt.plot(absolute_rounds, completed, label='Completed Tasks') plt.plot(absolute_rounds, failed, label='Failed Tasks') @@ -312,35 +318,25 @@ def save_task_results_png(absolute_rounds , completed, failed, start_time, path_ plt.close() def main(): - # parser = argparse.ArgumentParser(description="Analyze game log file between a start and end time.") - # parser.add_argument('--start_time', type=str, default=None, nargs='?', - # help="Start time for analysis in the log file.") - # parser.add_argument('--end_time', type=str, default=None, nargs='?', help="End time for analysis in the log file.") - # args = parser.parse_args() + # 获取当前脚本的路径 + current_script_path = os.path.dirname(os.path.abspath(__file__)) + + # 构建其他文件的路径 + filename = os.path.join(current_script_path, 'input', 'MG-1.txt') + path_prefix = os.path.join(current_script_path, 'results_pic') + + # 确保输出路径存在 + os.makedirs(path_prefix, exist_ok=True) - filename = r"D:\MG-MC\input\MG-1.txt" - path_prefix = r"D:\MG-MC\results_pic" # 自动寻找最新的实验开始时间 start_time = extract_time_from_first_round_zero(filename) logs_block = extract_logs(filename, start_time) + absolute_rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks = analyze_log_block(logs_block) - print(len(absolute_rounds)) - print(len(positions)) - print(len(items_collected_dict)) - print(len(items_variety_collected)) - #print(completed_tasks) - #print(failed_tasks) - print(positions) - print(items_collected_dict) - print(items_variety_collected) - print(completed_tasks) - print(failed_tasks) - print(absolute_rounds) positions_0 = [pos for pos in positions if pos is not None] - collected_items_set = set() total_items_variety = [] for i in range(0, len(items_collected_dict)): @@ -353,7 +349,6 @@ def main(): save_item_results_png(absolute_rounds, items_collected, items_collected_dict, start_time, path_prefix) save_path_results_png(positions_0, start_time, path_prefix) save_task_results_png(absolute_rounds, completed_tasks, failed_tasks, start_time, path_prefix) - #save_item_results_png(rounds, items_collected, items_variety_collected, items_collected_dict, start_time, path_prefix) print("种类",total_items_variety) print("轮次", absolute_rounds) @@ -373,6 +368,6 @@ def main(): df = pd.DataFrame(data) # 写入到Excel文件中 - df.to_excel(fr'D\MG-MC\results_pic\{start_time}_results.xlsx', index=False) + df.to_excel(os.path.join(path_prefix, f'{start_time}_results.xlsx'), index=False) if __name__ == "__main__": main() From 6c223decb2966a9f76047c740a88e391e1dbe147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Tue, 24 Oct 2023 01:33:46 +0800 Subject: [PATCH 08/11] Update Voyager_log_MetaGPT_statistical_caliber.py --- ...Voyager_log_MetaGPT_statistical_caliber.py | 92 ++++--------------- 1 file changed, 19 insertions(+), 73 deletions(-) diff --git a/Minecraft plot/Voyager_log_MetaGPT_statistical_caliber.py b/Minecraft plot/Voyager_log_MetaGPT_statistical_caliber.py index c415c5f44..6f62f3577 100644 --- a/Minecraft plot/Voyager_log_MetaGPT_statistical_caliber.py +++ b/Minecraft plot/Voyager_log_MetaGPT_statistical_caliber.py @@ -12,7 +12,7 @@ import pandas as pd mpl.rcParams.update(mpl.rcParamsDefault) def extract_logs(filename, start_time=None, end_time=None): - with open(filename, 'r',encoding='utf-8') as f: + with open(filename, 'r', encoding='utf-8') as f: lines = f.readlines() if start_time is None : @@ -34,7 +34,7 @@ def extract_logs(filename, start_time=None, end_time=None): return logs_block def extract_time_from_first_round_zero(log_filename): - with open(log_filename, 'r',encoding='utf-8') as f: + with open(log_filename, 'r', encoding='utf-8') as f: lines = f.readlines() # 反向遍历文件的每一行 @@ -45,47 +45,6 @@ def extract_time_from_first_round_zero(log_filename): return round_number return None -"""def analyze_log_block(logs_block): - rounds: list[int] = [] - items_collected: list[int] = [] - total_items = 0 - positions:list[(int, int, int)] = [] - completed_tasks: list[int] = [] - failed_tasks: list[int] = [] - items_variety_collected :list[int] = [] - items_collected_dict :list[dict] = [] - line_counter = 0 # 用于计数 - round_counter = 0 # 用于计数轮数 - for line in logs_block: - if "****Curriculum Agent human message****" in line: - line_counter = 0 # 当找到新的 "****Curriculum Agent human message****" 时重置计数器 - round_counter += 1 # 每次找到 "****Curriculum Agent human message****",轮数加1 - rounds.append(round_counter) # 将新的轮数添加到轮数列表中 - continue - - if line_counter < 50: - if "Position: x=" in line: - match = re.search(r'Position: x=([\d.-]+), y=([\d.-]+), z=([\d.-]+)', line) - x, y, z = float(match.group(1)), float(match.group(2)), float(match.group(3)) - positions.append((x, y, z)) - - if "Inventory (" in line: - items = re.search(r'Inventory \(\d+/36\): ({.*?})', line).group(1) - items_dict = eval(items) - items_collected_dict.append(items_dict) # 将这一轮结束时的物品存储状态添加到列表中 - total_items = sum(items_dict.values()) - items_collected.append(total_items) - items_variety_collected.append(len(items_dict)) # 统计物品种类数量 - - if "Completed tasks so far:" in line: - tasks = line.replace("Completed tasks so far:", "").strip().split(", ") - completed_tasks.append(0 if tasks == ['None'] else len(tasks)) - - if "Failed tasks that are too hard:" in line: - tasks = line.replace("Failed tasks that are too hard:", "").strip().split(", ") - failed_tasks.append(0 if tasks == ['None'] else len(tasks)) - - line_counter += 1 # 每处理一行就将计数器加1""" def analyze_log_block(logs_block): rounds: list[int] = [] items_collected: list[int] = [] @@ -140,6 +99,8 @@ def analyze_log_block(logs_block): failed_tasks.append(0 if tasks == ['None'] else len(tasks)) min_len: int = min(len(rounds), len(items_collected), len(positions), len(completed_tasks), len(failed_tasks)) return rounds[:min_len], items_collected[:min_len], items_variety_collected[:min_len], items_collected_dict[:min_len], positions[:min_len], completed_tasks[:min_len], failed_tasks[:min_len], biomes, biomes_per_round[:min_len], new_biome_rounds + + def save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix): items_collected_total = {} items_collected_total_list = [] @@ -214,16 +175,7 @@ def save_item_results_png(rounds, items_collected, items_collected_dict, start_t plt.text(rounds[i], y, item, fontsize=4, color=color, ha='center', va='top', bbox=dict(boxstyle='round,pad=0.5', fc=bgcolor, alpha=0.5)) - """for i in range(0, len(items_collected_dict)): - current_round_items_set = set(items_collected_dict[i]) - diff_items = list(current_round_items_set - collected_items_set) - collected_items_set.update(current_round_items_set) - items_variety_collected.append(len(collected_items_set)) - if diff_items: - for j, item in enumerate(diff_items): - color = 'red' if item in special_items else 'black' - plt.text(rounds[i], items_variety_collected[i] - 1 - j * 0.4, item, fontsize=8, color=color, ha='center', va='top', - bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.5))""" + plt.plot(rounds, items_variety_collected, label="Variety of Items Collected") plt.legend() @@ -315,29 +267,23 @@ def save_task_results_png(rounds , completed, failed, start_time, path_prefix): plt.close() def main(): - # parser = argparse.ArgumentParser(description="Analyze game log file between a start and end time.") - # parser.add_argument('--start_time', type=str, default=None, nargs='?', - # help="Start time for analysis in the log file.") - # parser.add_argument('--end_time', type=str, default=None, nargs='?', help="End time for analysis in the log file.") - # args = parser.parse_args() + # 获取当前脚本的路径 + current_script_path = os.path.dirname(os.path.abspath(__file__)) - filename = r"C:\Users\86151\Desktop\数模国赛\新建文件夹\input\VG-2.txt" - path_prefix = r"C:\Users\86151\Desktop\数模国赛\新建文件夹\input\results_pic" + # 构建其他文件的路径 + filename = os.path.join(current_script_path, 'input', 'VG-1.txt') + path_prefix = os.path.join(current_script_path, 'results_pic') + + # 确保输出路径存在 + os.makedirs(path_prefix, exist_ok=True) + # 自动寻找最新的实验开始时间 - filename = r"D:\MG-MC\input\VG-1.txt" - path_prefix = r"D:\MG-MC\results_pic" + start_time = extract_time_from_first_round_zero(filename) + logs_block = extract_logs(filename) rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks, biomes, biomes_per_round, new_biome_rounds = analyze_log_block(logs_block) - """ print(positions) - print(items_collected_dict) - print(items_variety_collected) - print(completed_tasks) - print(failed_tasks) - print(rounds) - print(new_biome_rounds)""" - #print(biomes_per_round) - #print(biomes) + collected_items_set = set() total_items_variety = [] for i in range(0, len(items_collected_dict)): @@ -350,7 +296,7 @@ def main(): save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix) save_path_results_png(positions, start_time, path_prefix) save_task_results_png(rounds, completed_tasks, failed_tasks, start_time, path_prefix) - #save_item_results_png(rounds, items_collected, items_variety_collected, items_collected_dict, start_time, path_prefix) + print("种类",total_items_variety) print("轮次", rounds) @@ -377,6 +323,6 @@ def main(): df = pd.concat([df, df_new_biomes], axis=1) # 写入到Excel文件中 - df.to_excel(fr'D:\MG-MC\results_pic\{start_time}_results.xlsx', index=False) + df.to_excel(os.path.join(path_prefix, f'{start_time}_results.xlsx'), index=False) if __name__ == "__main__": main() From e94cdfebde8abc2ece7f5192170006219f7f7e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Tue, 24 Oct 2023 01:34:44 +0800 Subject: [PATCH 09/11] Update Voyager_log_Voyager_statistical_caliber.py --- ...Voyager_log_Voyager_statistical_caliber.py | 43 +++++++------------ 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/Minecraft plot/Voyager_log_Voyager_statistical_caliber.py b/Minecraft plot/Voyager_log_Voyager_statistical_caliber.py index 009f73f19..daa470bf8 100644 --- a/Minecraft plot/Voyager_log_Voyager_statistical_caliber.py +++ b/Minecraft plot/Voyager_log_Voyager_statistical_caliber.py @@ -12,7 +12,7 @@ import pandas as pd mpl.rcParams.update(mpl.rcParamsDefault) def extract_logs(filename, start_time=None, end_time=None): - with open(filename, 'r',encoding='utf-8') as f: + with open(filename, 'r', encoding='utf-8') as f: lines = f.readlines() if start_time is None : @@ -34,7 +34,7 @@ def extract_logs(filename, start_time=None, end_time=None): return logs_block def extract_time_from_first_round_zero(log_filename): - with open(log_filename, 'r',encoding='utf-8') as f: + with open(log_filename, 'r', encoding='utf-8') as f: lines = f.readlines() # 反向遍历文件的每一行 @@ -106,6 +106,8 @@ def analyze_log_block(logs_block): items_collected_dict.append(latest_items_collected_dict) min_len: int = min(len(rounds), len(items_collected), len(positions), len(completed_tasks), len(failed_tasks)) return rounds[:min_len], items_collected[:min_len], items_variety_collected[:min_len], items_collected_dict[:min_len], positions[:min_len], completed_tasks[:min_len], failed_tasks[:min_len], biomes, biomes_per_round[:min_len], new_biome_rounds + + def save_item_results_png(rounds, items_collected, items_collected_dict, start_time, path_prefix): items_collected_total = {} items_collected_total_list = [] @@ -116,7 +118,7 @@ def save_item_results_png(rounds, items_collected, items_collected_dict, start_t else: items_collected_total[item] = quantity items_collected_total_list.append(sum(items_collected_total.values())) - print("总数",items_collected_total_list) + print("总数", items_collected_total_list) plt.figure(figsize=(10, 5)) plt.plot(rounds, items_collected_total_list, label="Items Collected") plt.xlabel("# of Rounds") @@ -180,16 +182,6 @@ def save_item_results_png(rounds, items_collected, items_collected_dict, start_t plt.text(rounds[i], y, item, fontsize=4, color=color, ha='center', va='top', bbox=dict(boxstyle='round,pad=0.5', fc=bgcolor, alpha=0.5)) - """for i in range(0, len(items_collected_dict)): - current_round_items_set = set(items_collected_dict[i]) - diff_items = list(current_round_items_set - collected_items_set) - collected_items_set.update(current_round_items_set) - items_variety_collected.append(len(collected_items_set)) - if diff_items: - for j, item in enumerate(diff_items): - color = 'red' if item in special_items else 'black' - plt.text(rounds[i], items_variety_collected[i] - 1 - j * 0.4, item, fontsize=8, color=color, ha='center', va='top', - bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.5))""" plt.plot(rounds, items_variety_collected, label="Variety of Items Collected") plt.legend() @@ -281,26 +273,23 @@ def save_task_results_png(rounds , completed, failed, start_time, path_prefix): plt.close() def main(): - # parser = argparse.ArgumentParser(description="Analyze game log file between a start and end time.") - # parser.add_argument('--start_time', type=str, default=None, nargs='?', - # help="Start time for analysis in the log file.") - # parser.add_argument('--end_time', type=str, default=None, nargs='?', help="End time for analysis in the log file.") - # args = parser.parse_args() - filename = r"D:\MG-MC\input\VG-1.txt" - path_prefix = r"D:\MG-MC\results_pic" + # 获取当前脚本的路径 + current_script_path = os.path.dirname(os.path.abspath(__file__)) + + # 构建其他文件的路径 + filename = os.path.join(current_script_path, 'input', 'VG-1.txt') + path_prefix = os.path.join(current_script_path, 'results_pic') + + # 确保输出路径存在 + os.makedirs(path_prefix, exist_ok=True) # 自动寻找最新的实验开始时间 start_time = extract_time_from_first_round_zero(filename) logs_block = extract_logs(filename) rounds, items_collected, items_variety_collected, items_collected_dict, positions, completed_tasks, failed_tasks, biomes, biomes_per_round, new_biome_rounds = analyze_log_block(logs_block) - print(positions) - print(items_collected_dict) - print(items_variety_collected) - print(completed_tasks) - print(failed_tasks) - print(rounds) + positions_0 = [pos for pos in positions if pos is not None] items_collected_dict = [item if item is not None else {} for item in items_collected_dict] @@ -344,6 +333,6 @@ def main(): df = pd.concat([df, df_new_biomes], axis=1) # 写入到Excel文件中 - df.to_excel(fr'D:\MG-MC\results_pic\{start_time}_results.xlsx', index=False) + df.to_excel(os.path.join(path_prefix, f'{start_time}_results.xlsx'), index=False) if __name__ == "__main__": main() From 7b179641d82c48c87ce875bee593b2f9a40369cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Tue, 24 Oct 2023 01:34:56 +0800 Subject: [PATCH 10/11] Update MetaGPT_log_Voyager_statistical_caliber.py --- Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py b/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py index c1fdbb02f..f66b02503 100644 --- a/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py +++ b/Minecraft plot/MetaGPT_log_Voyager_statistical_caliber.py @@ -1,4 +1,3 @@ -#MG-VG import re import argparse import os From abd9d22d8306e6f5d4c3b7c8c2494787dd01e574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Tue, 24 Oct 2023 01:44:02 +0800 Subject: [PATCH 11/11] Update MetaGPT_vs_Voyager.m --- Minecraft plot/MetaGPT_vs_Voyager.m | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Minecraft plot/MetaGPT_vs_Voyager.m b/Minecraft plot/MetaGPT_vs_Voyager.m index 812e4d671..ccd5af8cc 100644 --- a/Minecraft plot/MetaGPT_vs_Voyager.m +++ b/Minecraft plot/MetaGPT_vs_Voyager.m @@ -1,31 +1,31 @@ +% 定义元素 y1 = {[1, 1, 4, 4, 4, 4, 5, 13, 13, 14, 15, 17, 19, 19, 22, 22, 23, 23, 24, 24, 24, 24, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26]; [1, 1, 1, 1, 4, 4, 4, 4, 9, 9, 9, 12, 12, 13, 13, 15, 16, 16, 16, 16, 19, 20, 20, 20, 21, 22, 24, 24, 24, 24, 25, 27, 27, 27, 27, 31, 31, 31]; [1, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 9, 10, 11, 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 19, 20, 20, 20, 20, 20, 21, 23, 24, 24, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 29, 30, 30, 32, 32, 33, 34, 34, 34, 34, 37, 37]; [0, 1, 1, 3, 4, 4, 8, 9, 9, 9, 10, 10, 11, 11, 14, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 20, 20, 20, 20, 23, 24, 25, 27, 30, 30, 30, 30, 30, 30, 30, 30, 30, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42]; [1, 1, 1, 2, 5, 7, 8, 9, 9, 9, 9, 9, 10, 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 20, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 25, 25, 26, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 32, 32, 32, 32, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 40, 40, 40, 40, 41, 42, 42]; [1, 1, 1, 2, 3, 3, 3, 3, 5, 6, 6, 8, 9, 10, 10, 12, 12, 12, 12, 12, 12, 13, 14, 15, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24, 25, 27, 27, 28]}; -每个元素是一个向量代表一个曲线的x坐标 x = {1:1:33;1:1:38;1:1:57;1:1:82;1:1:81;1:1:38}; -% 创建共享的x向量,其范围是从0到最大的x值,步长为1 +% 创建共享的x向量 shared_x = 0:1:max(cellfun(@max,x)); -% 将y1和x拆分为MetaGPT和Voyager两部分 +% 拆分y1和x y1_MetaGPT = y1(1:4); x_MetaGPT = x(1:4); y1_Voyager = y1(5:6); x_Voyager = x(5:6); -% 对MetaGPT部分进行插值和计算上下限 +% 插值和计算上下限 interp_y1_MetaGPT = cellfun(@(y, x) interp1(x, y, shared_x, 'linear', 'extrap'), y1_MetaGPT, x_MetaGPT, 'UniformOutput', false); minY_MetaGPT = min(cell2mat(interp_y1_MetaGPT)); maxY_MetaGPT = max(cell2mat(interp_y1_MetaGPT)); -% 对Voyager部分进行插值和计算上下限 interp_y1_Voyager = cellfun(@(y, x) interp1(x, y, shared_x, 'linear', 'extrap'), y1_Voyager, x_Voyager, 'UniformOutput', false); minY_Voyager = min(cell2mat(interp_y1_Voyager)); maxY_Voyager = max(cell2mat(interp_y1_Voyager)); -% 计算MetaGPT和Voyager的均值 + +% 计算均值 meanY_MetaGPT = mean(cell2mat(interp_y1_MetaGPT)); meanY_Voyager = mean(cell2mat(interp_y1_Voyager)); @@ -45,8 +45,7 @@ h3=plot(shared_x, meanY_Voyager, 'r', 'LineWidth', 2); % 绘制Voyager的上下限范围,颜色设为红色 h4=fill([shared_x, fliplr(shared_x)], [minY_Voyager, fliplr(maxY_Voyager)], 'r', 'FaceAlpha', 0.2, 'EdgeColor', 'none'); -%绘制MetaGPT的每一条曲线 - +% 绘制MetaGPT的每一条曲线 for i = 1:length(y1_MetaGPT) plot(x_MetaGPT{i}, y1_MetaGPT{i}, 'b--'); % 使用蓝色虚线 end