import numpy as np
import matplotlib.pyplot as plt

# 城市坐标
cities = np.array([[16.47, 96.1], [16.47, 94.44], [20.09, 92.54], [22.39, 93.37], [25.23, 97.24],
                   [17.2, 96.29], [16.3, 97.38], [14.05, 98.12], [16.53, 97.38], [21.52, 95.59]])

# 城市数量
num_cities = cities.shape[0]

# 种群数量
num_population = 100

# 迭代次数
max_iter = 500

# 交叉概率
cross_prob = 0.08

# 变异概率
mutate_prob = 0.01

# 初始化种群
population = np.zeros((num_population, num_cities), dtype=np.int32)
for i in range(num_population):
    population[i] = np.random.permutation(num_cities)

# 计算距离矩阵
dist_matrix = np.sqrt((cities[:, np.newaxis, 0] - cities[np.newaxis, :, 0]) ** 2 +
                      (cities[:, np.newaxis, 1] - cities[np.newaxis, :, 1]) ** 2)
np.fill_diagonal(dist_matrix, np.inf)  # 不允许城市到自己的距离为0

# 计算适应度


def fitness(solution):
    total_dist = dist_matrix[solution[-1], solution[0]]
    for i in range(num_cities - 1):
        total_dist += dist_matrix[solution[i], solution[i + 1]]
    return 1 / total_dist  # 距离越短，适应度越高


fitness_values = np.zeros(num_population)
for i in range(num_population):
    fitness_values[i] = fitness(population[i])

# 进化过程
best_fitness = []
for iter in range(max_iter):
    # 选择操作
    idx = np.random.choice(num_population, num_population,
                           p=fitness_values / np.sum(fitness_values))
    parents = population[idx]

    # 交叉操作
    offspring = np.zeros_like(parents)
    for i in range(0, num_population, 2):
        if np.random.rand() < cross_prob:
            a, b = parents[i], parents[i + 1]
            m, n = np.random.randint(num_cities, size=2)
            if m > n:
                m, n = n, m
            child1, child2 = np.full(num_cities, -1), np.full(num_cities, -1)
            child1[m:n+1], child2[m:n+1] = a[m:n+1], b[m:n+1]
            p1, p2 = 0, 0
            for j in range(num_cities):
                if b[(n + j + 1) % num_cities] not in child1:
                    child1[(n + j + 1) %
                           num_cities] = b[(n + j + 1) % num_cities]
                if a[(n + j + 1) % num_cities] not in child2:
                    child2[(n + j + 1) %
                           num_cities] = a[(n + j + 1) % num_cities]
                if p1 < m:
                    if a[j] not in child1:
                        child1[p1] = a[j]
                        p1 += 1
                if p2 < m:
                    if b[j] not in child2:
                        child2[p2] = b[j]
                        p2 += 1
            offspring[i], offspring[i+1] = child1, child2
        else:
            offspring[i], offspring[i+1] = parents[i], parents[i+1]

    # 变异操作
    for i in range(num_population):
        if np.random.rand() < mutate_prob:
            a, b = np.random.randint(num_cities, size=2)
            offspring[i, a], offspring[i, b] = offspring[i, b], offspring[i, a]

    # 更新种群
    population = np.vstack((population, offspring))
    fitness_values = np.zeros(num_population * 2)
    for i in range(num_population * 2):
        fitness_values[i] = fitness(population[i])
    idx = np.argsort(-fitness_values)[:num_population]
    population = population[idx]
    fitness_values = fitness_values[idx]

    # 记录最优解
    best_fitness.append(np.max(fitness_values))

    # 输出进化过程
    if (iter + 1) % 50 == 0:
        print(
            f'Iteration {iter+1}: best fitness = {best_fitness[-1]:.6f}, best solution = {list(population[0])}')

# 绘制适应度进化曲线
plt.plot(best_fitness)
plt.title('Fitness Curve')
plt.xlabel('Iteration')
plt.ylabel('Best Fitness')
plt.show()
plt.savefig('Best Fitness.png')

# 绘制最优解路径图
best_solution = list(population[0])
best_solution.append(best_solution[0])
plt.plot(cities[:, 0], cities[:, 1], 'o')
plt.plot(cities[best_solution, 0], cities[best_solution, 1], '-o')
for i in range(num_cities):
    plt.text(cities[i, 0], cities[i, 1], str(i+1))
plt.title('Best Solution')
plt.show()
plt.savefig('Best Solution.png')
如何将以上代码中最优解路径图，x范围定义在10~30，y定义在90~100