Python遗传算法解决旅行商问题(TSP)

本文介绍如何使用Python实现遗传算法来解决经典的旅行商问题(TSP)。

1. 问题描述

旅行商问题(TSP)是指:给定一系列城市和每对城市之间的距离,找到访问每个城市一次并返回原始城市的最短路径

2. 解决方案:遗传算法

遗传算法是一种受生物进化启发的元启发式搜索算法。它通过模拟自然选择和遗传机制来寻找问题的最优解。以下是使用遗传算法解决TSP问题的步骤:

  1. 初始化种群: 随机生成一组可行的TSP解,每个解表示为城市的访问顺序。
  2. 计算适应度: 评估每个解的质量,通常使用路径总长度作为适应度函数。路径越短,适应度越高。
  3. 选择: 从当前种群中选择优秀的个体作为父代,用于生成下一代。
  4. 交叉: 将两个父代的基因信息进行组合,生成新的子代解。
  5. 变异: 对子代解进行随机修改,以增加种群的多样性,避免陷入局部最优解。
  6. 进化: 用新生成的子代种群替换旧种群,并重复步骤2-5,直到满足停止条件(例如达到最大迭代次数或找到满意解)。

3. Python代码实现

import random
import math
import matplotlib.pyplot as plt

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

    def distance(self, city):
        x_distance = abs(self.x - city.x)
        y_distance = abs(self.y - city.y)
        return math.sqrt((x_distance ** 2) + (y_distance ** 2))

    def __repr__(self):
        return '(' + str(self.x) + ',' + str(self.y) + ')'

# 定义遗传算法类
class GeneticAlgorithm:
    def __init__(self, population_size, mutation_rate, tournament_size, elitism):
        self.population_size = population_size
        self.mutation_rate = mutation_rate
        self.tournament_size = tournament_size
        self.elitism = elitism

    # 初始化种群
    def initialize_population(self, num_cities):
        population = []
        for _ in range(self.population_size):
            population.append(random.sample(range(num_cities), num_cities))
        return population

    # 计算个体的适应度(路径长度)
    def calculate_fitness(self, individual, cities):
        total_distance = 0
        for i in range(len(individual)):
            from_city = cities[individual[i]]
            to_city = cities[individual[(i + 1) % len(individual)]]
            total_distance += from_city.distance(to_city)
        return total_distance

    # 选择操作(锦标赛选择)
    def selection(self, population, cities):
        tournament = random.sample(population, self.tournament_size)
        best_individual = tournament[0]
        for individual in tournament:
            if self.calculate_fitness(individual, cities) < self.calculate_fitness(best_individual, cities):
                best_individual = individual
        return best_individual

    # 交叉操作(顺序交叉)
    def crossover(self, parent1, parent2):
        child = [-1] * len(parent1)
        start_index = random.randint(0, len(parent1) - 1)
        end_index = random.randint(0, len(parent1) - 1)
        if start_index < end_index:
            for i in range(start_index, end_index + 1):
                child[i] = parent1[i]
        elif start_index > end_index:
            for i in range(end_index, start_index + 1):
                child[i] = parent1[i]
        for i in range(len(parent2)):
            if parent2[i] not in child:
                for j in range(len(child)):
                    if child[j] == -1:
                        child[j] = parent2[i]
                        break
        return child

    # 变异操作(随机交换两个位置的城市)
    def mutation(self, individual):
        if random.random() < self.mutation_rate:
            index1 = random.randint(0, len(individual) - 1)
            index2 = random.randint(0, len(individual) - 1)
            individual[index1], individual[index2] = individual[index2], individual[index1]
        return individual

    # 进化操作
    def evolve(self, population, cities):
        new_population = []
        if self.elitism:
            best_individual = self.selection(population, cities)
            new_population.append(best_individual)
        while len(new_population) < len(population):
            parent1 = self.selection(population, cities)
            parent2 = self.selection(population, cities)
            child = self.crossover(parent1, parent2)
            child = self.mutation(child)
            new_population.append(child)
        return new_population

    # 绘制路径图
    def plot_path(self, best_individual, cities):
        x = []
        y = []
        for city_index in best_individual:
            x.append(cities[city_index].x)
            y.append(cities[city_index].y)
        x.append(cities[best_individual[0]].x)
        y.append(cities[best_individual[0]].y)
        plt.plot(x, y, 'ro-')
        plt.show()

    # 解决TSP问题
    def solve_tsp(self, cities):
        num_cities = len(cities)
        population = self.initialize_population(num_cities)
        best_fitness = float('inf')
        best_individual = []
        for generation in range(1000):
            population = self.evolve(population, cities)
            for individual in population:
                fitness = self.calculate_fitness(individual, cities)
                if fitness < best_fitness:
                    best_fitness = fitness
                    best_individual = individual
            print(f'Generation {generation}: Best fitness = {best_fitness}')
        print('最短路径长度:', best_fitness)
        print('最短路径:', best_individual)
        self.plot_path(best_individual, cities)

# 随机生成50个不同坐标的地点
cities = []
for _ in range(50):
    x = random.randint(0, 100)
    y = random.randint(0, 100)
    cities.append(City(x, y))

# 使用遗传算法解决TSP问题
ga = GeneticAlgorithm(population_size=50, mutation_rate=0.01, tournament_size=5, elitism=True)
ga.solve_tsp(cities)

4. 代码说明

  1. 代码首先定义了City类来表示城市,包含坐标信息和计算城市间距离的方法。
  2. 然后定义了GeneticAlgorithm类,实现了遗传算法的核心步骤:初始化种群、计算适应度、选择、交叉、变异和进化。
  3. solve_tsp方法中,首先初始化种群,然后迭代执行进化操作,并在每一代记录最优解。
  4. 最后,代码随机生成了50个城市,并使用遗传算法寻找最短路径,并将结果打印出来,并绘制路径图。

5. 总结

本文介绍了如何使用Python实现遗传算法来解决TSP问题。遗传算法是一种通用的优化算法,可以应用于各种问题。通过修改代码中的参数和目标函数,可以将其应用于其他组合优化问题。

Python遗传算法解决旅行商问题(TSP)

原文地址: https://www.cveoy.top/t/topic/cyPc 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录