大规模邻域搜索算法(Large Neighborhood Search, LNS)简介
核心思想:通过交替执行“破坏”(Destroy)和“修复”(Repair)操作,在解空间中高效搜索。
破坏阶段:移除当前解的一部分(如随机删除若干节点)
修复阶段:以新的方式重新填充被移除的部分,生成新解接受新解后重复迭代,逐步逼近全局最优解
优势:
跳出局部最优能力强
灵活性高,可适配多种组合优化问题(如TSP、VRP、调度问题)
易于与其他启发式算法结合
Python代码示例:TSP问题求解
问题描述
求解10个城市的旅行商问题(TSP),最小化总路径长度
import random
import math
# ========== 工具函数 ==========
def calculate_distance(city1, city2):
"""计算两个城市间的欧氏距离"""
return math.sqrt((city1[0]-city2[0])2 + (city1[1]-city2[1])2)
def total_distance(path, distance_matrix):
"""计算路径总长度"""
return sum(distance_matrix[path[i-1]][path[i]] for i in range(len(path)))
# ========== LNS核心组件 ==========
def destroy(current_solution, num_remove):
"""破坏操作:随机移除num_remove个城市"""
destroyed = current_solution.copy()
# 随机选择要移除的城市索引
remove_indices = random.sample(range(len(destroyed)), num_remove)
removed_cities = [destroyed[i] for i in remove_indices]
# 倒序删除避免索引错位
for i in sorted(remove_indices, reverse=True):
del destroyed[i]
return destroyed, removed_cities
def repair(partial_solution, removed_cities, distance_matrix):
"""修复操作:贪心插入最优位置"""
for city in removed_cities:
best_position = 0
min_increase = float('inf')
# 遍历所有可能插入位置
for i in range(len(partial_solution)+1):
new_path = partial_solution[:i] + [city] + partial_solution[i:]
increase = calculate_insertion_cost(new_path, i, distance_matrix)
if increase < min_increase:
min_increase = increase
best_position = i
partial_solution.insert(best_position, city)
return partial_solution
def calculate_insertion_cost(path, insert_index, distance_matrix):
"""计算插入新城市导致的路径长度变化"""
if insert_index == 0:
prev = path[-1] if len(path)>0 else path[0]
next_node = path[0]
elif insert_index == len(path):
prev = path[-1]
next_node = path[0]
else:
prev = path[insert_index-1]
next_node = path[insert_index]
new_city = path[insert_index]
return distance_matrix[prev][new_city] + distance_matrix[new_city][next_node] \
distance_matrix[prev][next_node]
# ========== 主算法 ==========
def lns_tsp(cities, iterations=100, num_remove=3):
# 初始化数据
n = len(cities)
distance_matrix = [[calculate_distance(i,j) for j in cities] for i in cities]
# 生成初始解(贪心算法)
current_solution = list(range(n))
random.shuffle(current_solution)
current_cost = total_distance(current_solution, distance_matrix)
# 迭代优化
for _ in range(iterations):
# 破坏阶段
partial_solution, removed = destroy(current_solution, num_remove)
# 修复阶段
new_solution = repair(partial_solution, removed, distance_matrix)
new_cost = total_distance(new_solution, distance_matrix)
# 接受更优解
if new_cost < current_cost:
current_solution = new_solution
current_cost = new_cost
print(f"Iteration {_+1}: New best cost = {current_cost:.2f}")
return current_solution, current_cost
# ========== 测试运行 ==========
if __name__ == "__main__":
# 随机生成10个城市坐标
random.seed(42)
cities = [(random.uniform(0,100), random.uniform(0,100)) for _ in range(10)]
# 运行LNS算法
best_path, best_cost = lns_tsp(cities, iterations=50, num_remove=3)
print("\nFinal Result:")
print(f"Best Path: {best_path}")
print(f"Total Distance: {best_cost:.2f}")
算法关键点说明
- 破坏强度控制:
num_remove
参数决定每次迭代移除的城市数量(通常设为总城市数的10-30%) - 修复策略:示例使用贪心插入,实际可替换为: regret-k插入 动态规划精确求解 元启发式方法
- 接受准则:示例使用严格改进接受策略,可扩展为: 模拟退火准则 禁忌搜索策略 自适应接受机制
典型应用场景
- 车辆路径规划(VRP)
- 车间调度问题
- 资源分配问题
- 组合优化问题(如二维装箱问题)
实际使用时需要根据具体问题特点设计针对性的破坏/修复策略,并调整参数设置。