修改绘图

This commit is contained in:
yangyudong 2025-05-15 22:00:38 +08:00
parent 7ca00525bb
commit bffda01a6d
10 changed files with 3493 additions and 1259 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 220 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,29 +1,26 @@
import numpy as np
import random
from typing import List, Tuple, Dict
from typing import Dict, List, Tuple
def generate_dataset(num_items: int, container_size: Tuple[int, int], seed: int = 2025) -> Dict[str, Tuple[List[Tuple[int, int]], Tuple[int, int]]]:
def generate_instance() -> Dict[str, Tuple[List[Tuple[int, int]], Tuple[int, int]]]:
"""
生成二维装箱问题的数据集
Args:
num_items: 物品数量
container_size: 容器的宽度和高度
seed: 随机种子默认为2025
Generate a single instance for the 2D Bin Packing Problem.
Returns:
Dict[str, Tuple[List[Tuple[int, int]], Tuple[int, int]]]: 包含物品列表和容器尺寸的字典
A dictionary containing:
- 'items': A list of tuples, where each tuple represents the (width, height) of an item.
- 'bin_dimensions': A tuple representing the (width, height) of the bin.
"""
random.seed(seed)
np.random.seed(seed)
np.random.seed(2025) # Set seed for reproducibility
items = []
for _ in range(num_items):
width = random.randint(1, container_size[0] // 2)
height = random.randint(1, container_size[1] // 2)
items.append((width, height))
# Generate random item dimensions, ensuring no item exceeds the bin dimensions
bin_width, bin_height = 100, 100
n_items = 100
item_widths = np.random.randint(10, bin_width - 10, size=n_items)
item_heights = np.random.randint(10, bin_height - 10, size=n_items)
items = list(zip(item_widths, item_heights))
bin_dimensions = (bin_width, bin_height)
return {"data": (items, container_size)}
return {"items": items, "bin_dimensions": bin_dimensions}
class ProblemDataLoader:
def __init__(self, problem_path: str):
@ -31,12 +28,11 @@ class ProblemDataLoader:
def get_data(self) -> Dict[str, Tuple[List[Tuple[int, int]], Tuple[int, int]]]:
"""
加载二维装箱问题的数据集
Load the 2D Bin Packing Problem dataset.
Returns:
Dict[str, Tuple[List[Tuple[int, int]], Tuple[int, int]]]: 包含物品列表和容器尺寸的字典
A dictionary containing:
- 'items': A list of tuples, where each tuple represents the (width, height) of an item.
- 'bin_dimensions': A tuple representing the (width, height) of the bin.
"""
# 使用固定随机种子生成数据集
num_items = 10
container_size = (100, 100)
return generate_dataset(num_items, container_size, seed=2025)
return generate_instance()

View File

@ -2,99 +2,87 @@ import numpy as np
import time
from typing import Callable, Dict, List, Tuple
def evaluate(packing_func: Callable[[Dict[str, Tuple[List[Tuple[int, int]], Tuple[int, int]]]], List[Dict[str, int]]],
def evaluate(packing_func: Callable[[Dict[str, Tuple[List[Tuple[int, int]], Tuple[int, int]]]], List[List[Tuple[Tuple[int, int], Tuple[int, int]]]]],
input_data: Dict[str, Tuple[List[Tuple[int, int]], Tuple[int, int]]]) -> Dict[str, float]:
"""评估二维装箱算法的多目标性能
"""
Evaluate the performance of a 2D bin packing algorithm.
Args:
packing_func: 装箱算法函数
input_data: 一个字典包含两个部分:
- 'data': 一个元组包含物品列表和容器尺寸
packing_func: The bin packing algorithm function.
input_data: A dictionary containing:
- 'items': A list of tuples, where each tuple represents the (width, height) of an item.
- 'bin_dimensions': A tuple representing the (width, height) of the bin.
Returns:
Dict[str, float]: 包含两个目标值的字典:
- vacancy_rate: 容器的利用率
- execution_time: 运行时间()
如果解不合法(物品超出容器边界或重叠)则返回无穷大
Dict[str, float]: A dictionary containing:
- bins_used: The number of bins used.
- execution_time: The execution time in seconds.
If the solution is invalid (e.g., items overlap or exceed bin boundaries), returns infinity for both metrics.
"""
try:
# 解包输入数据
items, container = input_data["data"]
# Extract items and bin dimensions from input_data
items = input_data["items"]
bin_dimensions = input_data["bin_dimensions"]
# 计时并执行装箱算法
# Measure execution time
start_time = time.time()
packing_result = packing_func(input_data)
print(f"[DEBUG] Packing result: {packing_result}")
bins = packing_func(input_data)
print(f"[DEBUG] Raw bins returned from packing_func: {bins}")
end_time = time.time()
execution_time = end_time - start_time
# 检查解的合法性
container_width, container_height = container
occupied_area = 0
# Validate the solution
bin_width, bin_height = bin_dimensions
total_bins_used = len(bins)
# 尝试标准化 packing_result 的结构
standardized_result = []
for placement in packing_result:
if isinstance(placement, tuple) and len(placement) >= 3:
x, y, rotated = placement[:3]
standardized_result.append({"x": x, "y": y, "rotated": rotated})
elif isinstance(placement, dict):
standardized_result.append(placement)
else:
print(f"[ERROR] Invalid packing_result structure: {packing_result}")
return {
"vacancy_rate": float('inf'),
"execution_time": float('inf')
}
packing_result = standardized_result
for bin_content in bins:
occupied_area = 0
for item in bin_content:
corner = item["corner"]
width, height = item["dimensions"]
x, y = corner
for item, placement in zip(items, packing_result):
item_width, item_height = item
x, y, rotated = placement["x"], placement["y"], placement["rotated"]
if rotated:
item_width, item_height = item_height, item_width
# 检查是否超出容器边界
if x + item_width > container_width or y + item_height > container_height:
print(f"非法解:物品超出容器边界")
return {
"vacancy_rate": float('inf'),
"execution_time": float('inf')
}
# 检查是否重叠
for other_item, other_placement in zip(items, packing_result):
if placement == other_placement:
continue
other_x, other_y, other_rotated = other_placement["x"], other_placement["y"], other_placement["rotated"]
other_width, other_height = other_item
if other_rotated:
other_width, other_height = other_height, other_width
if not (x + item_width <= other_x or other_x + other_width <= x or
y + item_height <= other_y or other_y + other_height <= y):
print(f"非法解:物品重叠")
# Check if the item exceeds bin boundaries
if x + width > bin_width or y + height > bin_height:
print(f"Invalid solution: Item at ({x}, {y}) with size ({width}, {height}) exceeds bin boundaries.")
return {
"vacancy_rate": float('inf'),
"bins_used": float('inf'),
"execution_time": float('inf')
}
occupied_area += item_width * item_height
# Check for overlaps with other items in the same bin
for other_corner, (other_width, other_height) in bin_content:
if (corner == other_corner):
continue
other_x, other_y = other_corner
if not (x + width <= other_x or other_x + other_width <= x or
y + height <= other_y or other_y + other_height <= y):
print(f"Invalid solution: Items at ({x}, {y}) and ({other_x}, {other_y}) overlap.")
return {
"bins_used": float('inf'),
"execution_time": float('inf')
}
# 计算容器利用率
vacancy_rate = 1 - (occupied_area / (container_width * container_height))
occupied_area += width * height
print(f"执行时间:{execution_time:.4f}秒, 容器空置率:{vacancy_rate:.4f}")
# Ensure no item exceeds the bin's capacity
if occupied_area > bin_width * bin_height:
print(f"Invalid solution: Bin capacity exceeded.")
return {
"bins_used": float('inf'),
"execution_time": float('inf')
}
print(f"Execution time: {execution_time:.4f} seconds, Bins used: {total_bins_used}")
return {
"vacancy_rate": vacancy_rate,
"bins_used": total_bins_used,
"execution_time": execution_time
}
except Exception as e:
print(f"评估过程出错: {str(e)}")
print(f"Error during evaluation: {str(e)}")
return {
"vacancy_rate": float('inf'),
"bins_used": float('inf'),
"execution_time": float('inf')
}

View File

@ -7,3 +7,12 @@ Generation 0004 | Pareto Front Size: 1 | Timestamp: 2025-05-13T15:56:18.905940
Generation 0005 | Pareto Front Size: 1 | Timestamp: 2025-05-13T15:59:55.953455
Generation 0006 | Pareto Front Size: 1 | Timestamp: 2025-05-13T16:00:39.951690
Generation 0007 | Pareto Front Size: 1 | Timestamp: 2025-05-13T16:02:14.607527
Generation 0000 | Pareto Front Size: 2 | Timestamp: 2025-05-15T15:47:17.387937
Generation 0000 | Pareto Front Size: 1 | Timestamp: 2025-05-15T15:50:11.979996
Generation 0001 | Pareto Front Size: 1 | Timestamp: 2025-05-15T15:52:01.064112
Generation 0002 | Pareto Front Size: 1 | Timestamp: 2025-05-15T15:53:46.976949
Generation 0003 | Pareto Front Size: 1 | Timestamp: 2025-05-15T15:55:05.807839
Generation 0004 | Pareto Front Size: 1 | Timestamp: 2025-05-15T15:56:30.922968
Generation 0005 | Pareto Front Size: 1 | Timestamp: 2025-05-15T16:00:15.734229
Generation 0006 | Pareto Front Size: 1 | Timestamp: 2025-05-15T16:01:31.540137
Generation 0007 | Pareto Front Size: 1 | Timestamp: 2025-05-15T16:05:09.684054

View File

@ -1,10 +1,10 @@
{
"description": "尝试开发一个高效的算法用于解决二维装箱问题。你被给定一组矩形物品和一个固定大小的矩形容器,目标是通过算法规划将所有物品放入容器中,使得容器的利用率最大化。",
"description": "开发一个高效的算法用于解决二维装箱问题。给定一组矩形物品和一个固定大小的矩形容器,目标是通过算法规划将所有物品放入尽可能少的容器中。",
"function_name": "solve_bp",
"input_format": "一个字典,包含两个部分:\n1. 'data': 一个元组,包含多个矩形物品的列表和一个表示容器宽度和高度的元组。\n - 矩形物品列表的每个元素是一个元组,表示物品的宽度和高度。\n - 容器元组表示容器的宽度和高度。\n",
"output_format": "返回一个列表,表示每个物品在容器中的位置和旋转状态。\n每个元素是一个字典包含以下键\n1. 'x': 物品左上角的x坐标。\n2. 'y': 物品左上角的y坐标。\n3. 'rotated': 一个布尔值,表示物品是否旋转。",
"input_format": "一个字典,包含以下两部分:\n1. 'items': 一个列表,包含多个矩形物品的尺寸,每个物品由其宽度和高度表示为一个元组 (width, height)。\n2. 'bin_dimensions': 一个元组,表示容器的宽度和高度 (width, height)。",
"output_format": "返回一个列表,表示每个容器中的物品放置情况。\n每个容器是一个列表包含多个物品的放置信息每个物品由以下两部分组成\n1. corner: 一个元组,表示物品左上角的坐标 (x, y)。\n2. dimensions: 一个元组,表示物品的宽度和高度 (width, height)。",
"multi_objective": true,
"objective_names": ["vacancy_rate", "execution_time"],
"objective_names": ["bins_used", "execution_time"],
"evaluation_timeout": 60,
"llm_config": {
"api_key": "sk-cOqgMkQ605Om9Z28q3UtAfOAtOn7c53tld94Cu01oOEoVTmg",
@ -16,7 +16,7 @@
"evolution_params": {
"algorithm": "MO",
"population_size": 2,
"generations": 8,
"generations": 2,
"mutation_rate": 0.5,
"crossover_rate": 0.4,
"F": 0.8,

View File

@ -39,6 +39,7 @@ class MultiObjectiveEvaluator:
# 使用超时控制调用评估函数
timeout = Timeout(self.timeout)
# print(f"[DEBUG] Dataset structure: {self.dataset}")
if self.dataset is not None:
results = timeout.run(self.evaluation_module.evaluate, func, self.dataset)
else:

BIN
tsp_data/tsp_pareto.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 KiB

After

Width:  |  Height:  |  Size: 686 KiB