用A*算法、爬山法、遗传算法解决旅行商问题

编写TSP(旅行商问题)的实例生成器,城市的位置用在单位正方形内的随机点表示。并分别用A*算法与爬山法、遗传算法来求解TSP问题实例。
以下是具体题目要求,用c++、python、java都可以!要标明并附上代码!

img

img

TechWhizKid参考GPT回答:

以下是使用A*算法、爬山法和遗传算法解决旅行商问题的示例代码:

A*算法:

import heapq

# 定义城市类
class City:
    def __init__(self, name, x, y):
        self.name = name
        self.x = x
        self.y = y

    def __str__(self):
        return self.name

# 计算两个城市之间的距离
def calculate_distance(city1, city2):
    return ((city2.x - city1.x) ** 2 + (city2.y - city1.y) ** 2) ** 0.5

# A*算法求解TSP问题
def solve_tsp_A_star(cities, start_city):
    # 定义优先队列
    pq = []
    heapq.heappush(pq, (0, [start_city], set()))

    while pq:
        cost, path, visited = heapq.heappop(pq)
        current_city = path[-1]

        # 判断是否已经访问过所有城市
        if len(path) == len(cities):
            return path, cost

        for city in cities:
            if city != current_city and city not in visited:
                new_cost = cost + calculate_distance(current_city, city)
                heuristic = calculate_distance(city, start_city)
                heapq.heappush(pq, (new_cost + heuristic, path + [city], visited | {city}))

    return None

# 示例生成器:生成随机城市列表
def generate_cities(num_cities):
    import random
    cities = []
    for i in range(num_cities):
        name = chr(ord('A') + i)
        x = random.random()
        y = random.random()
        cities.append(City(name, x, y))
    return cities

# 测试示例
cities = generate_cities(5)
start_city = cities[0]
path, cost = solve_tsp_A_star(cities, start_city)
print("Path:", ' -> '.join(str(city) for city in path))
print("Total Cost:", cost)

爬山法:

import random

# 评估路径的总距离
def evaluate_path(cities, path):
    total_distance = 0
    for i in range(len(path)):
        city1 = path[i]
        city2 = path[(i + 1) % len(path)]
        total_distance += calculate_distance(cities[city1], cities[city2])
    return total_distance

# 随机生成初始路径
def generate_initial_path(num_cities):
    path = list(range(num_cities))
    random.shuffle(path)
    return path

# 爬山法求解TSP问题
def solve_tsp_hill_climbing(cities):
    num_cities = len(cities)
    current_path = generate_initial_path(num_cities)
    current_cost = evaluate_path(cities, current_path)

    while True:
        neighbors = []
        for i in range(num_cities):
            for j in range(i + 1, num_cities):
                neighbor = current_path.copy()
                neighbor[i], neighbor[j] = neighbor[j], neighbor[i]
                neighbors.append(neighbor)

        best_neighbor = None
        best_neighbor_cost = float('inf')
        for neighbor in neighbors:
            neighbor_cost = evaluate_path(cities, neighbor)
            if neighbor_cost < best_neighbor_cost:
                best_neighbor = neighbor
                best_neighbor_cost = neighbor_cost

        if best_neighbor_cost < current_cost:
            current_path = best_neighbor
            current_cost = best_neighbor_cost
        else:
            break

    return current_path, current_cost

# 测试示例
cities = generate_cities(5)
path, cost = solve_tsp_hill_climbing(cities)
print("Path:", ' -> '.join(cities[i].name for i in path))
print("Total Cost:", cost)

遗传算法:

import random

# 生成初始种群
def generate_initial_population(num_cities, population_size):
    population = []
    for _ in range(population_size):
        path = list(range(num_cities))
        random.shuffle(path)
        population.append(path)
    return population

# 评估个体路径的适应度(倒数距离)
def evaluate_fitness(cities, path):
    distance = evaluate_path(cities, path)
    return 1 / distance

# 选择父代个体
def selection(population, fitness):
    # 使用轮盘赌选择方法
    total_fitness = sum(fitness)
    probabilities = [fit / total_fitness for fit in fitness]
    selected_indices = random.choices(range(len(population)), probabilities, k=2)
    return [population[idx] for idx in selected_indices]

# 交叉生成子代个体
def crossover(parent1, parent2):
    # 使用顺序交叉算子
    num_cities = len(parent1)
    start = random.randint(0, num_cities - 2)
    end = random.randint(start + 1, num_cities - 1)
    child = [-1] * num_cities

    # 保留父代1的部分路径
    for i in range(start, end + 1):
        child[i] = parent1[i]

    # 填充子代剩余部分
    index = 0
    for i in range(num_cities):
        if child[index] == -1:
            while parent2[index] in child:
                index = (index + 1) % num_cities
            child[index] = parent2[index]
            index = (index + 1) % num_cities

    return child

# 变异个体
def mutate(individual):
    # 使用交换变异算子
    index1 = random.randint(0, len(individual) - 1)
    index2 = random.randint(0, len(individual) - 1)
    individual[index1], individual[index2] = individual[index2], individual[index1]
    return individual

# 遗传算法求解TSP问题
def solve_tsp_genetic(cities, population_size, num_generations):
    num_cities = len(cities)
    population = generate_initial_population(num_cities, population_size)
    best_path = None
    best_cost = float('inf')

    for _ in range(num_generations):
        fitness = [evaluate_fitness(cities, path) for path in population]

        for i in range(population_size):
            if fitness[i] > best_cost:
                best_path = population[i]
                best_cost = fitness[i]

        new_population = [best_path]

        while len(new_population) < population_size:
            parent1, parent2 = selection(population, fitness)
            child = crossover(parent1, parent2)
            child = mutate(child)
            new_population.append(child)

        population = new_population

    return best_path, 1 / best_cost

# 测试

示例
cities = generate_cities(5)
path, cost = solve_tsp_genetic(cities, population_size=10, num_generations=100)
print("Path:", ' -> '.join(cities[i].name for i in path))
print("Total Cost:", cost)

4.3

import random

# 评估路径的总距离
def evaluate_path(cities, path):
    total_distance = 0
    for i in range(len(path)):
        city1 = path[i]
        city2 = path[(i + 1) % len(path)]
        total_distance += calculate_distance(cities[city1], cities[city2])
    return total_distance

# 随机生成初始路径
def generate_initial_path(num_cities):
    path = list(range(num_cities))
    random.shuffle(path)
    return path

# 爬山法求解TSP问题
def solve_tsp_hill_climbing(cities):
    num_cities = len(cities)
    current_path = generate_initial_path(num_cities)
    current_cost = evaluate_path(cities, current_path)

    while True:
        neighbors = []
        for i in range(num_cities):
            for j in range(i + 1, num_cities):
                neighbor = current_path.copy()
                neighbor[i], neighbor[j] = neighbor[j], neighbor[i]
                neighbors.append(neighbor)

        best_neighbor = None
        best_neighbor_cost = float('inf')
        for neighbor in neighbors:
            neighbor_cost = evaluate_path(cities, neighbor)
            if neighbor_cost < best_neighbor_cost:
                best_neighbor = neighbor
                best_neighbor_cost = neighbor_cost

        if best_neighbor_cost < current_cost:
            current_path = best_neighbor
            current_cost = best_neighbor_cost
        else:
            break

    return current_path, current_cost

# 使用MST启发式的A*算法求解TSP问题
def solve_tsp_A_star_MST(cities, start_city):
    # 构建MST
    def build_MST(cities):
        visited = set()
        mst = []

        current_city = start_city
        visited.add(current_city)

        while len(visited) < len(cities):
            min_distance = float('inf')
            nearest_city = None

            for city in cities:
                if city != current_city and city not in visited:
                    distance = calculate_distance(current_city, city)
                    if distance < min_distance:
                        min_distance = distance
                        nearest_city = city

            mst.append((current_city, nearest_city))
            visited.add(nearest_city)
            current_city = nearest_city

        return mst

    # 计算MST的总代价
    def calculate_MST_cost(mst):
        total_cost = 0
        for edge in mst:
            total_cost += calculate_distance(edge[0], edge[1])
        return total_cost

    # 启发式函数:剩余路径的最小生成树代价
    def heuristic(city, visited):
        remaining_cities = set(cities) - visited
        remaining_mst = build_MST(remaining_cities)
        remaining_cost = calculate_MST_cost(remaining_mst)
        return remaining_cost

    # A*算法求解TSP问题
    def solve_tsp_A_star(cities, start_city):
        pq = []
        heapq.heappush(pq, (0, [start_city], set()))

        while pq:
            cost, path, visited = heapq.heappop(pq)
            current_city = path[-1]

            if len(path) == len(cities):
                return path, cost

            for city in cities:
                if city != current_city and city not in visited:
                    new_cost = cost + calculate_distance(current_city, city)
                    h = heuristic(city, visited)
                    heapq.heappush(pq, (new_cost + h, path + [city], visited | {city}))

        return None

    mst = build_MST(cities)
    mst_cost = calculate_MST_cost(mst)
    path, cost = solve_tsp_A_star(cities, start_city)
    return path, cost, mst_cost

# 测试示例
cities = generate_cities(5)
start_city = cities[0]

# 使用爬山法求解TSP问题
hill_climbing_path, hill_climbing_cost = solve_tsp_hill_climbing(cities)

# 使用MST启发式的A*算法求解TSP问题
a_star_path, a_star_cost, mst_cost = solve_tsp_A_star_MST(cities, start_city)

print("Hill Climbing Path:", ' -> '.join(cities[i].name for i in hill_climbing_path))
print("Hill Climbing Cost:", hill_climbing_cost)
print()
print("A* with MST Heuristic Path:", ' -> '.join(cities[i].name for i in a_star_path))
print("A* with MST Heuristic Cost:", a_star_cost)
print("Minimum Spanning Tree (MST) Cost:", mst_cost)


  • 给你找了一篇非常好的博客,你可以看看是否有帮助,链接:TSP路径规划总结(常用解决方案 A*算法,蜂群算法,遗传算法,蚁群及其优化等)
  • 除此之外, 这篇博客: 遗传算法对比模拟退火算法求解TSP问题(C++实现)中的 a.算法的结果 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 结果图表展示:

    次数最优解误差运行时间
    1584.163.57%334.53s
    2590.014.60%332.12s
    3580.632.95%345.20s
    4589.414.50%315.22s
    5589.824.58%350.31s
    6582.493.28%335.41s
    7584.253.54%337.23s
    8582.973.36%340.33s
    9585.353.78%332.96s
    10585.203.75%338.97s

    根据上述十次测试结果可以得出

    最好解:

    路径长度为580.63,参考最优解为564,误差为2.95%。

    最差解:

    路径长度为590.01,参考最优解为564,误差为4.60%。

    平均值:

    路径长度为585.43,参考最优解为564,误差为3.79%

    标准差:

    3.28107

    方差:

    10.76541

    算法的平均速度:

    运行时间为335.8s

    其中一次运行结果的解下降情况,横坐标是繁殖的代数,纵坐标为该代种群中的最优解

    2

    显示TSP路径的收敛情况

    第一代:
    在这里插入图片描述
    最后一代:
    在这里插入图片描述

有用麻烦点个采纳哦
这个博客给了源码,可以参考一下,
https://blog.csdn.net/qq_33950926/article/details/130046741

这是一项比较大的任务,我会给出一些代码示例,但是这个问题可能需要你自己做一些额外的工作和研究。以下是一个简单的Python示例,它生成了TSP问题的实例,并使用遗传算法来求解。这个示例使用了deap库来实现遗传算法。

首先,我们安装需要使用的库:

pip install deap numpy matplotlib

然后,编写TSP问题的实例生成器和遗传算法求解器:

import random
import numpy as np
import matplotlib.pyplot as plt
from deap import algorithms, base, creator, tools

# 创建城市位置
num_cities = 20
cities = [random.sample(range(100), 2) for _ in range(num_cities)]

distances = np.empty((num_cities, num_cities))
for i in range(num_cities):
    for j in range(num_cities):
        # 计算城市间的欧氏距离
        distances[i, j] = np.sqrt((cities[i][0] - cities[j][0]) ** 2 + (cities[i][1] - cities[j][1]) ** 2)

# 创建问题类型
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)

toolbox = base.Toolbox()
toolbox.register("indices", random.sample, range(num_cities), num_cities)
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.indices)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

def evalTSP(individual):
    # 计算旅行路径的总距离
    return sum(distances[individual[i - 1], individual[i]] for i in range(num_cities)),

toolbox.register("mate", tools.cxPartialyMatched)
toolbox.register("mutate", tools.mutShuffleIndexes, indpb=0.05)
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("evaluate", evalTSP)

def main():
    pop = toolbox.population(n=100)
    hof = tools.HallOfFame(1)
    stats = tools.Statistics(lambda ind: ind.fitness.values)
    stats.register("avg", np.mean)
    stats.register("std", np.std)
    stats.register("min", np.min)
    stats.register("max", np.max)
    
    pop, logbook = algorithms.eaSimple(pop, toolbox, cxpb=0.7, mutpb=0.2, ngen=100, 
                                       stats=stats, halloffame=hof, verbose=True)
    
    return pop, logbook, hof

if __name__ == "__main__":
    pop, log, hof = main()
    print("Best individual is: %s\nwith fitness: %s" % (hof[0], hof[0].fitness))
    
    gen, avg, min_, max_ = log.select("gen", "avg", "min", "max")
    plt.plot(gen, avg, label="average")
    plt.plot(gen, min_, label="minimum")
    plt.plot(gen, max_, label="maximum")
    plt.xlabel("Generation")
    plt.ylabel("Fitness")
    plt.legend(loc="lower right")
    plt.show()

这个示例生成了20个城市的位置,然后使用遗传算法来寻找最短的旅行路径。遗传算法的参数可能需要根据问题的具体情况进行调整。

至于A*算法和爬山法,你可能需要自己编写或者寻找现有的实现。这两种算法的实现通常比较复杂,需要理解算法的工作原理,并能够将这些原理转化为有效的代码。我建议你查阅相关的教科书或者在线教程,了解这些算法的工作原理和实现方法。

参考 https://blog.csdn.net/sgsx11/article/details/121482958?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168922039116782425114138%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=168922039116782425114138&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-121482958-null-null.142^v88^control_2,239^v2^insert_chatgpt&utm_term=%E7%94%A8A*%E7%AE%97%E6%B3%95%E3%80%81%E7%88%AC%E5%B1%B1%E6%B3%95%E3%80%81%E9%81%97%E4%BC%A0%E7%AE%97%E6%B3%95%E8%A7%A3%E5%86%B3%E6%97%85%E8%A1%8C%E5%95%86%E9%97%AE%E9%A2%98&spm=1018.2226.3001.4187