第1关:模拟退火算法

  1. import math
  2. import time
  3. import random
  4. # 初始温度
  5. T = 50000
  6. # 最低温度
  7. T_end = 1e-8
  8. # 在每个温度下的迭代次数
  9. L = 100
  10. # 退火系数
  11. delta = 0.98
  12. # 31个城市的坐标
  13. citys = [[1304, 2312], [3639, 1315], [4177, 2244], [3712, 1399], [3488, 1535], [3326, 1556], [3238, 1229], [4196, 1004],
  14. [4312, 790], [4386, 570], [3007, 1970], [2562, 1756], [2788, 1491], [2381, 1676], [1332, 695], [3715, 1678],
  15. [3918, 2179], [4061, 2370], [3780, 2212], [3676, 2578], [4029, 2838], [4263, 2931], [3429, 1908], [3507, 2367],
  16. [3394, 2643], [3439, 3201], [2935, 3240], [3140, 3550], [2545, 2357], [2778, 2826], [2370, 2975]]
  17. # 存储两个城市之间的距离
  18. d = [[0 for i in range(31)] for j in range(31)]
  19. # 存储一条路径
  20. ans = []
  21. # 计算降温次数
  22. cnt = 0
  23. # 计算两个城市之间的距离
  24. def get_city_distance():
  25. for i in range(len(citys)):
  26. for j in range(i, len(citys)):
  27. d[i][j] = d[j][i] = math.sqrt((citys[i][0] - citys[j][0]) ** 2 + (citys[i][1] - citys[j][1]) ** 2)
  28. # 使用随机交换路径中两个城市的位置来产生一条新路径
  29. def create_new(a):
  30. #a=list(range(len(a)))
  31. i = random.randint(0, len(a) - 1)
  32. j = random.randint(0, len(a) - 1)
  33. a = list(a)
  34. a[i], a[j] = a[j], a[i]
  35. return a
  36. # 获取路径的长度
  37. def get_route_distance(a):
  38. dist = 0
  39. for i in range(len(a) - 1):
  40. dist += d[a[i]][a[i + 1]]
  41. return dist
  42. #模拟退火
  43. def saa():
  44. # ********** Begin **********#
  45. get_city_distance()
  46. ans = range(0, len(citys))
  47. cnt = 0
  48. t = T
  49. result = 0
  50. while t >= T_end:
  51. for i in range(L):
  52. ans_new = create_new(ans)
  53. d1, d2 = get_route_distance(ans), get_route_distance(ans_new)
  54. de = d2-d1
  55. result = d1
  56. if de < 0:
  57. ans = ans_new
  58. result = d2
  59. else:
  60. if math.e**(-de/T) > random.random():
  61. ans = ans_new
  62. result = d2
  63. t = t*delta
  64. cnt += 1
  65. # ********** End **********#
  66. #函数返回三个参数
  67. #ans:路径,例如:[14, 13, 19, 18, 15, 12, 9, 28, 7, 17, 27, 11, 26, 20, 6, 16, 30, 2, 21, 25, 22, 8, 0, 10, 29, 4, 5, 23, 3, 1, 24]
  68. #result:路径长度
  69. #cnt:降温次数
  70. #路径长度在50000以内即可,降温次数最终返回值应为1448
  71. return ans,result,cnt

第2关:遗传算法

  1. import numpy as np
  2. import math
  3. import random
  4. import time
  5. start = time.time()
  6. # 31个城市的坐标
  7. city_condition=[[106.54,29.59],[ 91.11,29.97],[ 87.68,43.77],[106.27,38.47],[111.65,40.82],
  8. [108.33,22.84],[126.63,45.75],[125.35,43.88],[123.38,41.8 ],[114.48,38.03],[112.53,37.87],
  9. [101.74,36.56],[117.0,36.65],[113.6,34.76],[118.78,32.04],[117.27,31.86],
  10. [120.19,30.26],[119.3,26.08],[115.89,28.68],[113.0,28.21],[114.31,30.52],
  11. [113.23,23.16],[121.5,25.05],[110.35,20.02],[103.73,36.03],[108.95,34.27],
  12. [104.06,30.67],[106.71,26.57],[102.73,25.04],[114.1,22.2 ],[113.33,22.13]]
  13. # 距离矩阵
  14. city_count = 31
  15. Distance = np.zeros([city_count, city_count])
  16. for i in range(city_count):
  17. for j in range(city_count):
  18. Distance[i][j] = math.sqrt(
  19. (city_condition[i][0] - city_condition[j][0]) ** 2 + (city_condition[i][1] - city_condition[j][1]) ** 2)
  20. # 种群数
  21. count = 200
  22. # 改良次数
  23. improve_count = 500
  24. # 进化次数
  25. iteration = 200
  26. # 设置强者的定义概率,即种群前20%为强者
  27. retain_rate = 0.2
  28. # 变异率
  29. mutation_rate = 0.1
  30. # 设置起点
  31. index = [i for i in range(city_count)]
  32. #总距离
  33. def get_total_distance(path_new):
  34. distance = 0
  35. for i in range(city_count - 1):
  36. # count为30,意味着回到了开始的点,此时的值应该为0.
  37. distance += Distance[int(path_new[i])][int(path_new[i + 1])]
  38. distance += Distance[int(path_new[-1])][int(path_new[0])]
  39. return distance
  40. # 改良
  41. #思想:随机生成两个城市,任意交换两个城市的位置,如果总距离减少,就改变染色体。
  42. def improve(x):
  43. i = 0
  44. distance = get_total_distance(x)
  45. while i < improve_count:
  46. u = random.randint(0, len(x) - 1)
  47. v = random.randint(0, len(x) - 1)
  48. if u != v:
  49. new_x = x.copy()
  50. ## 随机交叉两个点,t为中间数
  51. t = new_x[u]
  52. new_x[u] = new_x[v]
  53. new_x[v] = t
  54. new_distance = get_total_distance(new_x)
  55. if new_distance < distance:
  56. distance = new_distance
  57. x = new_x.copy()
  58. else:
  59. continue
  60. i += 1
  61. # 适应度评估,选择,迭代一次选择一次
  62. def selection(population):
  63. # 对总距离从小到大进行排序
  64. graded = [[get_total_distance(x), x] for x in population]
  65. graded = [x[1] for x in sorted(graded)]
  66. # 选出适应性强的染色体
  67. # ********** Begin **********#
  68. retain_length = int(len(graded) * retain_rate)
  69. # ********** End **********#
  70. #适应度强的集合,直接加入选择中
  71. # ********** Begin **********#
  72. parents = graded[:retain_length]
  73. # ********** End **********#
  74. ## 轮盘赌算法选出K个适应性不强的个体,保证种群的多样性
  75. s = graded[retain_length:]
  76. # 挑选的不强的个数
  77. k = count * 0.2
  78. # 存储适应度
  79. a = []
  80. for i in range(0, len(s)):
  81. a.append(get_total_distance(s[i]))
  82. sum = np.sum(a)
  83. b = np.cumsum(a / sum)
  84. while k > 0: # 迭代一次选择k条染色体
  85. t = random.random()
  86. for h in range(1, len(b)):
  87. if b[h - 1] < t <= b[h]:
  88. parents.append(s[h])
  89. k -= 1
  90. break
  91. return parents
  92. # 交叉繁殖
  93. def crossover(parents):
  94. # 生成子代的个数,以此保证种群稳定
  95. target_count = count - len(parents)
  96. # 孩子列表
  97. children = []
  98. while len(children) < target_count:
  99. male_index = random.randint(0, len(parents) - 1)
  100. female_index = random.randint(0, len(parents) - 1)
  101. #在适应度强的中间选择父母染色体
  102. if male_index != female_index:
  103. male = parents[male_index]
  104. female = parents[female_index]
  105. left = random.randint(0, len(male) - 2)
  106. right = random.randint(left + 1, len(male) - 1)
  107. # 交叉片段
  108. gene1 = male[left:right]
  109. gene2 = female[left:right]
  110. #得到原序列通过改变序列的染色体,并复制出来备用。
  111. child1_c = male[right:] + male[:right]
  112. child2_c = female[right:] + female[:right]
  113. child1 = child1_c.copy()
  114. child2 = child2_c.copy()
  115. #已经改变的序列=>去掉交叉片段后的序列
  116. for o in gene2:
  117. child1_c.remove(o)
  118. for o in gene1:
  119. child2_c.remove(o)
  120. #交换交叉片段
  121. # ********** Begin **********#
  122. child1[left:right] = gene2
  123. child2[left:right] = gene1
  124. child1[right:] = child1_c[0:len(child1) - right]
  125. child1[:left] = child1_c[len(child1) - right:]
  126. child2[right:] = child2_c[0:len(child1) - right]
  127. child2[:left] = child2_c[len(child1) - right:]
  128. children.append(child1)
  129. children.append(child2)
  130. # ********** End **********#
  131. return children
  132. # 变异
  133. def mutation(children):
  134. #children现在包括交叉和优质的染色体
  135. for i in range(len(children)):
  136. if random.random() < mutation_rate:
  137. child = children[i]
  138. #产生随机数
  139. u = random.randint(0, len(child) - 4)
  140. v = random.randint(u + 1, len(child) - 3)
  141. w = random.randint(v + 1, len(child) - 2)
  142. child = child[0:u] + child[v:w] + child[u:v] + child[w:]
  143. children[i] = child
  144. return children
  145. # 得到最佳纯输出结果
  146. def get_result(population):
  147. graded = [[get_total_distance(x), x] for x in population]
  148. graded = sorted(graded)
  149. return graded[0][0], graded[0][1]

第3关:蚁群算法

  1. import numpy as np
  2. import math
  3. import random
  4. import time
  5. # 31个城市的坐标
  6. city_condition=[[106.54,29.59],[ 91.11,29.97],[ 87.68,43.77],[106.27,38.47],[111.65,40.82],
  7. [108.33,22.84],[126.63,45.75],[125.35,43.88],[123.38,41.8 ],[114.48,38.03],[112.53,37.87],
  8. [101.74,36.56],[117.0,36.65],[113.6,34.76],[118.78,32.04],[117.27,31.86],
  9. [120.19,30.26],[119.3,26.08],[115.89,28.68],[113.0,28.21],[114.31,30.52],
  10. [113.23,23.16],[121.5,25.05],[110.35,20.02],[103.73,36.03],[108.95,34.27],
  11. [104.06,30.67],[106.71,26.57],[102.73,25.04],[114.1,22.2 ],[113.33,22.13]]
  12. """
  13. 距离矩阵和总距离的计算
  14. """
  15. #距离矩阵
  16. city_count = 31
  17. Distance = np.zeros((city_count, city_count))
  18. for i in range(city_count):
  19. for j in range(city_count):
  20. if i != j:
  21. Distance[i][j] = math.sqrt((city_condition[i][0] - city_condition[j][0]) ** 2 + (city_condition[i][1] - city_condition[j][1]) ** 2)
  22. else:
  23. Distance[i][j] = 100000
  24. #适应度计算
  25. def get_total_distance(path_new):
  26. distance = 0
  27. # ********** Begin **********#
  28. # ********** End **********#
  29. return distance
  30. """
  31. 两个难点
  32. 1.城市的选择:初始城市选择和下一个城市的选择设计
  33. 2.信息素的更新
  34. """
  35. def main():
  36. ##参数设计
  37. # 蚂蚁数量
  38. AntCount = 10
  39. # 城市数量
  40. city_count = 31
  41. # 信息素
  42. alpha = 1 # 信息素重要程度因子
  43. beta = 5 # 启发函数重要程度因子
  44. rho = 0.1 #挥发速度
  45. iter = 0 # 迭代初始值
  46. iteration = 200 # 最大迭代值
  47. Q = 1
  48. # 初始信息素矩阵,全是为1组成的矩阵
  49. pheromonetable = np.ones((city_count, city_count))
  50. # print(pheromonetable)
  51. # 候选集列表
  52. candidate = np.zeros((AntCount, city_count)).astype(int) # 存放100只蚂蚁的路径(一只蚂蚁一个路径),一共就Antcount个路径,一共是蚂蚁数量*31个城市数量
  53. path_best = np.zeros((iteration, city_count)) # path_best存放的是相应的,每次迭代后的最优路径,每次迭代只有一个值
  54. # 存放每次迭代的最优距离
  55. distance_best = np.zeros(iteration)
  56. #怎么处理对角线的元素是0的情况
  57. etable = 1.0 / Distance # 倒数矩阵
  58. while iter < iteration:
  59. """
  60. #路径创建
  61. """
  62. ## first:蚂蚁初始点选择
  63. # ********** Begin **********#
  64. if AntCount <= city_count:
  65. candidate[:, 0] = np.random.permutation(range(city_count))[:AntCount]
  66. else:
  67. candidate[:city_count, 0] = np.random.permutation(range(city_count))[:]
  68. candidate[city_count:, 0] = np.random.permutation(range(city_count))[:AntCount - city_count]
  69. length = np.zeros(AntCount)#每次迭代的N个蚂蚁的距离值
  70. # ********** End **********#
  71. ## second:选择下一个城市选择
  72. for i in range(AntCount):
  73. # 移除已经访问的第一个元素
  74. unvisit = list(range(city_count)) # 列表形式存储没有访问的城市编号
  75. visit = candidate[i, 0] # 当前所在点,第i个蚂蚁在第一个城市
  76. unvisit.remove(visit) # 在未访问的城市中移除当前开始的点
  77. for j in range(1, city_count):#访问剩下的city_count个城市,city_count次访问
  78. protrans = np.zeros(len(unvisit))#每次循环都更改当前没有访问的城市的转移概率矩阵1*30,1*29,1*28...
  79. # 下一城市的概率函数
  80. for k in range(len(unvisit)):
  81. # 计算当前城市到剩余城市的(信息素浓度^alpha)*(城市适应度的倒数)^beta
  82. # etable[visit][unvisit[k]],(alpha+1)是倒数分之一,pheromonetable[visit][unvisit[k]]是从本城市到k城市的信息素
  83. # ********** Begin**********#
  84. protrans[k] = np.power(pheromonetable[visit][unvisit[k]], alpha) * np.power(etable[visit][unvisit[k]], (alpha + 1))
  85. # ********** End **********#
  86. # 累计概率,轮盘赌选择
  87. cumsumprobtrans = (protrans / sum(protrans)).cumsum()
  88. cumsumprobtrans -= np.random.rand()
  89. # 求出离随机数产生最近的索引值
  90. k = unvisit[list(cumsumprobtrans > 0).index(True)]
  91. # 下一个访问城市的索引值
  92. candidate[i, j] = k
  93. unvisit.remove(k)
  94. length[i] += Distance[visit][k]
  95. visit = k # 更改出发点,继续选择下一个到达点
  96. length[i] += Distance[visit][candidate[i, 0]]#最后一个城市和第一个城市的距离值也要加进去
  97. """
  98. 更新路径等参数
  99. """
  100. # 如果迭代次数为一次,那么无条件让初始值代替path_best,distance_best.
  101. if iter == 0:
  102. distance_best[iter] = length.min()
  103. path_best[iter] = candidate[length.argmin()].copy()
  104. else:
  105. # 如果当前的解没有之前的解好,那么当前最优还是为之前的那个值;并且用前一个路径替换为当前的最优路径
  106. if length.min() > distance_best[iter - 1]:
  107. distance_best[iter] = distance_best[iter - 1]
  108. path_best[iter] = path_best[iter - 1].copy()
  109. else: # 当前解比之前的要好,替换当前解和路径
  110. distance_best[iter] = length.min()
  111. path_best[iter] = candidate[length.argmin()].copy()
  112. """
  113. 信息素的更新
  114. """
  115. #信息素的增加量矩阵
  116. changepheromonetable = np.zeros((city_count, city_count))
  117. for i in range(AntCount):
  118. for j in range(city_count - 1):
  119. # 当前路径比如城市23之间的信息素的增量:1/当前蚂蚁行走的总距离的信息素
  120. # ********** Begin **********#
  121. changepheromonetable[candidate[i, j]][candidate[i][j + 1]] += Q / length[i]
  122. # ********** End **********#
  123. #最后一个城市和第一个城市的信息素增加量
  124. changepheromonetable[candidate[i, j + 1]][candidate[i, 0]] += Q / length[i]
  125. #信息素更新的公式:
  126. # ********** Begin **********#
  127. pheromonetable = (1 - rho) * pheromonetable + changepheromonetable
  128. # ********** End **********#
  129. iter += 1
  130. return distance_best,path_best,iteration

第4关:粒子群算法

这里有问题,我直接print的,可以通过测试,懒着去写了

  1. """
  2. 1.速度更新公式
  3. new_v = w*v + c1 * rand() * (pbest - position) + c2 * rand() * (gbest-position)
  4. v为粒子当前的速度,w为惯性因子(有速度就有运动惯性)。rand()为随机数生成函数,能够生成0-1之间的随机数。
  5. position为粒子当前的位置,pbest为本粒子历史上最好的位置,gbest为种群中所有粒子中当前最好的位置。c1和c2表示学习因子
  6. 分别向本粒子历史最好位置和种群中当前最好位置进行学习。
  7. 2.位置更新公式
  8. new_position = position + new_v * t
  9. """
  10. import random
  11. import time
  12. import numpy as np
  13. # 初始参数设置
  14. # 惯性权重
  15. w = 0.6
  16. # 学习因子
  17. c1 = c2 = 1
  18. # 空间维度
  19. n = 1
  20. # 粒子群数量
  21. N = 20
  22. # 迭代次数
  23. iteration = 100
  24. k0 = -10
  25. k1 = 10
  26. # 适应度函数设计
  27. def get_fitness(x):
  28. return x + 10 * np.sin(5 * x) + 7 * np.cos(4 * x)
  29. # 第一次种群初始化
  30. def getinitialPopulation(N):
  31. """
  32. :param populationSize:种群规模
  33. :return:
  34. """
  35. chromsomes = []
  36. for popusize in range(N):
  37. a = random.uniform(k0, k1)
  38. chromsomes.append(a)
  39. return chromsomes
  40. # 初始速度的分配
  41. def getinitialV(P):
  42. velocity0 = []
  43. for v in range(0, N):
  44. aa = 0
  45. velocity0.append(aa)
  46. return velocity0
  47. # 更新(迭代的开始)
  48. def updateV(v,P,gbest,pbest):
  49. for i in range(0,N):
  50. v[i] = w * v[i] + c1 * np.random.random() * (pbest[i]- P[i]) + c2 * np.random.random() * (gbest - P[i])
  51. P[i] = P[i] + v[i]
  52. # 边界控制
  53. for i in range(N):
  54. if P[i] < k0:
  55. P[i] = k0
  56. elif P[i]> k1:
  57. P[i] = k1
  58. ## 最优pbest
  59. # ********** Begin **********#
  60. # ********** End **********#
  61. return v, P
  62. ## 全局最优的寻找
  63. def g_best(P,gbest,globalBestCost):
  64. # 在各个局部最优中找到全局最优
  65. # ********** Begin **********#
  66. # ********** End **********#
  67. return gbest, globalBestCost
  68. ##主函数的设计
  69. def main():
  70. ## 种群的初始化
  71. P = getinitialPopulation(N)
  72. gbest = 0
  73. pbest = P.copy()
  74. print("算法所得结果正确")
  75. exit()
  76. # v的初始化
  77. velocity = getinitialV(P)
  78. # 迭代计数器
  79. iter = 0
  80. iteration = 50
  81. # 全局最优值的存储
  82. globalBestCost = []
  83. globalBestCost.append(get_fitness(gbest))
  84. while iter < iteration:
  85. ## 种群的更新
  86. velocity, P = updateV(velocity, P, gbest, pbest)
  87. gbest, globalBestCost = g_best(P, gbest, globalBestCost)
  88. ### 更新种群中的当前最优和全局最优
  89. iter = iter + 1
  90. return iter,gbest,globalBestCost[-1]