D:\annaconda\python.exe C:\Users\竹石子\Desktop\电工杯\3.py Traceback (most recent call last): File "C:\Users\竹石子\Desktop\电工杯\3.py", line 232, in <module> best_stage1 = stage1_sa(df_transfer, df_garbage, distance) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\竹石子\Desktop\电工杯\3.py", line 174, in stage1_sa neighbor_cost = total_cost(neighbor_sol) ^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\竹石子\Desktop\电工杯\3.py", line 140, in total_cost transport = transport_cost(solution) ^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\竹石子\Desktop\电工杯\3.py", line 130, in transport_cost Ck = vehicle_data['cost_per_km'].values[0] ~~~~~~~~~~~~^^^^^^^^^^^^^^^ File "D:\annaconda\Lib\site-packages\pandas\core\frame.py", line 4078, in __getitem__ return self._get_item_cache(key) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\annaconda\Lib\site-packages\pandas\core\frame.py", line 4639, in _get_item_cache res = self._ixs(loc, axis=1) ^^^^^^^^^^^^^^^^^^^^^^ File "D:\annaconda\Lib\site-packages\pandas\core\frame.py", line 4014, in _ixs result._set_as_cached(label, self) File "D:\annaconda\Lib\site-packages\pandas\core\series.py", line 1478, in _set_as_cached self._cacher = (item, weakref.ref(cacher)) ^^^^^^^^^^^^^^^^^^^ KeyboardInterrupt 进程已结束,退出代码为 -1073741510 (0xC000013A: interrupted by Ctrl+C)
时间: 2025-05-31 19:53:12 浏览: 27
从错误信息来看,程序在运行过程中遇到了一个 `KeyboardInterrupt` 中断(用户通过 Ctrl+C 强制终止了程序)。此外,在中断之前,程序尝试访问 `vehicle_data['cost_per_km'].values[0]` 时可能出现了问题。以下是详细的分析和解决方案。
---
### 1. **问题分析**
#### (1) `KeyboardInterrupt`
- 错误信息表明程序运行时间过长或陷入死循环,用户被迫中断。
- 模拟退火算法(SA)的迭代次数可能过高,导致程序运行缓慢。
#### (2) `vehicle_data['cost_per_km'].values[0]` 访问问题
- 如果 `vehicle_data` 是空的(即没有找到匹配的车辆类型),则会抛出 `IndexError`。
- 这可能是因为垃圾类型 `k` 超出了车辆参数表中的范围。
---
### 2. **解决方案**
#### (1) 防止空数据访问
在 `transport_cost` 函数中,添加对 `vehicle_data` 是否为空的检查,并在空时抛出明确的异常。
#### (2) 控制模拟退火算法的运行时间
- 减少每次温度下降的迭代次数 `iter_per_temp`。
- 设置最大迭代次数或时间限制以避免长时间运行。
#### (3) 优化代码逻辑
- 确保所有输入数据的格式正确。
- 添加日志输出以便调试。
---
### 3. **修复后的代码**
以下是修复后的代码:
```python
import numpy as np
import pandas as pd
import math
import random
import time
import matplotlib.pyplot as plt
# 设置随机种子以保证结果可重复
random.seed(42)
# 数据加载
def load_data():
# 收集点坐标(附件1)
df_points = pd.read_excel('附件1.xlsx', sheet_name='附件130个垃圾分类收集点坐标及总垃圾量', skiprows=1)
df_points.columns = ['id', 'x', 'y', 'w_total', 'remark']
# 中转站候选参数(附件4)
df_transfer = pd.read_excel('中转站候选位置及参数.xlsx', sheet_name='附件4中转站候选位置及参数', skiprows=1)
df_transfer.columns = ['id', 'x', 'y', 'cost', 'time_window', 'capacity']
df_transfer['capacity'] = df_transfer['capacity'].apply(eval)
# 车辆参数(附件2)
df_vehicles = pd.read_excel('4种运输车辆参数.xlsx', sheet_name='附件24类运输车辆参数', skiprows=1)
df_vehicles.columns = ['type', 'garbage_type', 'max_weight', 'volume', 'cost_per_km', 'alpha', 'beta']
# 收集点垃圾分布(附件3)
df_garbage = pd.read_excel('附件3.xlsx', sheet_name='附件330个收集点的4类垃圾量分布', skiprows=1)
df_garbage.columns = ['id', 'k1', 'k2', 'k3', 'k4']
return df_points, df_transfer, df_vehicles, df_garbage
# 距离矩阵计算(处理非对称)
def build_distance_matrix(df_points, df_transfer):
nodes = []
# 处理厂(0号)
nodes.append({'id': 0, 'x': 0, 'y': 0})
# 收集点1-30
for _, row in df_points.iterrows():
if row['id'] == 0:
continue
nodes.append({'id': row['id'], 'x': row['x'], 'y': row['y']})
# 中转站31-35
for _, row in df_transfer.iterrows():
nodes.append({'id': row['id'], 'x': row['x'], 'y': row['y']})
# 构建距离字典
distance = {}
for i in nodes:
for j in nodes:
key = (i['id'], j['id'])
# 处理特殊路径(根据附件5)
if (i['id'] == 4 and j['id'] == 31):
distance[key] = 18
elif (i['id'] == 31 and j['id'] == 4):
distance[key] = 15
else:
dx = i['x'] - j['x']
dy = i['y'] - j['y']
distance[key] = round(math.hypot(dx, dy))
return distance
# 第一阶段:中转站选址与分配
def stage1_sa(df_transfer, df_garbage, distance):
# 模拟退火参数
T0 = 1000
alpha = 0.95
iter_per_temp = 50 # 减少每次温度下降的迭代次数
T_min = 1e-3
candidate_stations = df_transfer['id'].tolist()
# 初始解
def initial_solution():
selected = random.sample(candidate_stations, 2)
assignments = {}
for i in range(1, 31):
for k in range(1, 5):
j = random.choice(selected)
assignments[(i, k)] = j
return {'selected': selected, 'assignments': assignments}
# 计算容量违规
def capacity_penalty(solution):
penalty = 0
for j in solution['selected']:
cap = df_transfer[df_transfer['id'] == j]['capacity'].iloc[0]
for k in range(4):
total = sum(df_garbage[df_garbage['id'] == i][f'k{k+1}'].values[0]
for (i, k_), j_ in solution['assignments'].items()
if k_ == k+1 and j_ == j)
if total > cap[k]:
penalty += (total - cap[k]) * 1000
return penalty
# 运输成本估计
def transport_cost(solution):
cost = 0
for (i, k), j in solution['assignments'].items():
vehicle_data = df_vehicles[df_vehicles['type'] == k]
if vehicle_data.empty:
raise ValueError(f"未找到匹配的车辆类型: {k}")
Ck = vehicle_data['cost_per_km'].values[0]
d = distance[(0, j)] + distance[(j, i)] + distance[(i, 0)]
w = df_garbage[df_garbage['id'] == i][f'k{k}'].values[0]
cost += Ck * d * w
return cost
# 总成本
def total_cost(solution):
construction = sum(df_transfer[df_transfer['id'].isin(solution['selected'])]['cost']) * 10000
transport = transport_cost(solution)
penalty = capacity_penalty(solution)
return construction + transport + penalty
# 邻域生成
def neighbor(solution):
new_sol = {
'selected': solution['selected'].copy(),
'assignments': solution['assignments'].copy()
}
op = random.choice(['add', 'remove', 'reassign'])
if op == 'add':
available = set(candidate_stations) - set(new_sol['selected'])
if available:
new_sol['selected'].append(random.choice(list(available)))
elif op == 'remove':
if len(new_sol['selected']) > 2:
new_sol['selected'].remove(random.choice(new_sol['selected']))
elif op == 'reassign':
i, k = random.choice(list(new_sol['assignments'].keys()))
j = random.choice(new_sol['selected'])
new_sol['assignments'][(i, k)] = j
return new_sol
# SA主循环
current = initial_solution()
current_cost = total_cost(current)
best = current.copy()
best_cost = current_cost
T = T0
start_time = time.time() # 记录开始时间
max_runtime = 60 # 最大运行时间(秒)
while T > T_min and (time.time() - start_time) < max_runtime:
for _ in range(iter_per_temp):
neighbor_sol = neighbor(current)
try:
neighbor_cost = total_cost(neighbor_sol)
except ValueError as e:
print(e) # 打印错误信息并跳过当前邻居
continue
delta = neighbor_cost - current_cost
if delta < 0 or random.random() < math.exp(-delta / T):
current = neighbor_sol
current_cost = neighbor_cost
if current_cost < best_cost:
best = current.copy()
best_cost = current_cost
T *= alpha
return best
# 主程序
df_points, df_transfer, df_vehicles, df_garbage = load_data()
distance = build_distance_matrix(df_points, df_transfer)
best_stage1 = stage1_sa(df_transfer, df_garbage, distance)
print("最佳方案:", best_stage1)
```
---
### 4. **代码解释**
1. **防止空数据访问**:
- 在 `transport_cost` 函数中,如果找不到匹配的车辆类型,则抛出明确的异常 `ValueError`。
2. **控制运行时间**:
- 使用 `time.time()` 记录程序开始时间,并设置最大运行时间为 60 秒。
- 如果超过最大运行时间,则退出模拟退火主循环。
3. **优化逻辑**:
- 减少了每次温度下降的迭代次数 `iter_per_temp`,以加快收敛速度。
---
###
阅读全文
相关推荐



















