当前位置:   article > 正文

Python实现带不等式约束的NSGAII算法解决cec2021中的RCM01问题_有约束的nsga2

有约束的nsga2

原文章:NSGA2算法原理及python实现_w要变强的博客-CSDN博客_nsga2 python 

算法原理不多说了,网上都有,我是在NSGAII里加上约束违反值计算,实现不等式约束

RCM01问题:

  1. # 这是Kalyanmoy Deb教授流行的NSGA-II算法的python实现
  2. # 导入模块
  3. import math
  4. import random
  5. import matplotlib.pyplot as plt
  6. # 第一个约束函数
  7. def function1(x1, x2, x3, x4):
  8. z1 = 0.0625 * x1
  9. value = 1.7781 * z1 * x3 ** 2 + 0.6224 * z1 * x2 * x4 + 3.1661 * z1 ** 2 * x4 + 19.84 * z1 ** 2 * x3
  10. return value
  11. # 第二个约束函数
  12. def function2(x3, x4):
  13. value = -math.pi * x3 ** 2 * x4 - (4 / 3) * math.pi * x3 ** 3
  14. return value
  15. #计算约束违反值
  16. def CV(x):
  17. z1 = 0.0625 * x[0]
  18. z2 = 0.0625 * x[1]
  19. g1 = 0.00954 * x[2] - z2
  20. g2 = 0.0193 * x[2] - z1
  21. if g1<=0 and g2<=0:
  22. return 0
  23. elif g1<=0 and g2>0:
  24. return g2
  25. elif g2<=0 and g1>0:
  26. return g1
  27. elif g1>0 and g2>0:
  28. return g1+g2
  29. # 查找列表值的索引的函数
  30. def index_of(a, list):
  31. for i in range(0, len(list)):
  32. if list[i] == a:
  33. return i
  34. return -1
  35. # 按序号排序的功能
  36. def sort_by_values(list1, values): # list为下标序列,values为值序列
  37. sorted_list = []
  38. while (len(sorted_list) != len(list1)): # 遍历len(list1)次
  39. if index_of(min(values), values) in list1:
  40. sorted_list.append(index_of(min(values), values)) # 查找该层次中的最小值所在的索引
  41. values[
  42. index_of(min(values), values)] = math.inf # math.inf 浮点正无限(设置最小的(边界))的值为无穷,当找不到的时候设置最后一个为浮点正无限(return -1)
  43. return sorted_list
  44. # 执行NSGA-II快速非支配排序的功能
  45. def fast_non_dominated_sort(values1, values2,cv):
  46. S = [[] for i in range(0, len(values1))] # 生成values1(种群大小)个空列表的二维列表S,S记录被P支配的集合
  47. front = [[]] # 一个空的二维列表
  48. n = [0 for i in range(0, len(values1))] # 生成values1(种群大小)个0的一维列表n,n指p被支配的个数
  49. rank = [0 for i in range(0, len(values1))] # 生成values1(种群大小)个0的以为列表,rank指非支配序
  50. for p in range(0, len(values1)): # p为种群中的每个个体,遍历种群
  51. S[p] = [] # 初始化当前个体p支配的集合
  52. n[p] = 0 # 初始化当前个体p被支配的个数
  53. for q in range(0, len(values1)): # q为种群中的每个个体,遍历种群(两层遍历达到每两两都进行比较)
  54. if cv[p]==0 and cv[q]==0: #当p和q都不违反约束时
  55. if (values1[p] > values1[q] and values2[p] > values2[q]) or (
  56. values1[p] >= values1[q] and values2[p] > values2[q]) or (
  57. values1[p] > values1[q] and values2[p] >= values2[q]): # 如果函数1当前值p大于函数1其他值而且函数2当前值大于函数2其他值
  58. # 或者 函数1当前值p不小于函数1其他值而且函数2当前值大于函数2其他值
  59. # 或者 函数1当前值p大于函数1其他值而且函数2当前值不小于函数2其他值
  60. # (判断条件 使其找到非支配前沿)
  61. if q not in S[p]: # 保证当前p并未在S[p]中(即证明p支配q)
  62. S[p].append(q) # 添加被p支配的集合S[p]
  63. elif (values1[q] > values1[p] and values2[q] > values2[p]) or (
  64. values1[q] >= values1[p] and values2[q] > values2[p]) or (
  65. values1[q] > values1[p] and values2[q] >= values2[p]): # 如果函数1当前值p大于函数1其他值而且函数2当前值大于函数2其他值
  66. # 或者 函数1当前值p不小于函数1其他值而且函数2当前值大于函数2其他值
  67. # 或者 函数1当前值p大于函数1其他值而且函数2当前值不小于函数2其他值
  68. # (判断条件 p受q支配)
  69. n[p] = n[p] + 1 # 使其p被支配个数n[p]加1
  70. elif cv[p]==0 and cv[q]>0: #当p是可行解,而q不可行时
  71. if q not in S[p]: # 保证当前p并未在S[p]中(即证明p支配q)
  72. S[p].append(q) # 添加被p支配的集合S[p]
  73. elif cv[p]>0 and cv[q]==0: #当p时不可行解,而q是可行解时
  74. n[p]=n[p]+1
  75. if n[p] == 0: # 如果p不被其他群体支配
  76. rank[p] = 0 # 则设置其非支配序为0
  77. if p not in front[0]: # 并通过判断将其添加到(第一列)前沿序列Z1中
  78. front[0].append(p)
  79. print(front)
  80. i = 0
  81. while (front[i] != []): # 通过判断前一列序列是否为空(保证不为空) i = 0(即第二步)
  82. Q = [] # 初始化另一个集Q
  83. for p in front[i]: # 遍历当前列序列里面的每个个体
  84. for q in S[p]: # 考察它所支配的个体集s[p]
  85. n[q] = n[q] - 1 # 集合S[p]中的每个个体q的(被支配个数)n[q]减1(因为支配个体q已经加入到当前集front[i],即以不属于下面的序列)
  86. if (n[q] == 0): # (注:在减1之前n[q]不存在为0的个数,以为在之前将n[q]=0的个体已经加入到front[0])
  87. rank[q] = i + 1 # 如果当前个体不再受其他个体支配,设置其该集合相同的非支配序rank值
  88. if q not in Q: # 通过判断将其加入到当前最优集Q
  89. Q.append(q)
  90. i = i + 1 # 继续下一序列集
  91. front.append(Q) # 将其添加到前沿序列
  92. # print(front)
  93. del front[len(front) - 1] # 最后一个序列什么都没有添加元素,即(front[i]==0)循环结束,故删除最后一个空列表
  94. return front # 返回快速非支配排序后的结果,rank为其所在二维列表中所在一维列表的下标
  95. # [[6], [4], [11], [8, 17], [1], [5], [7], [2, 19], [13, 16], [18], [3], [0], [12], [14], [15], [9], [10]]
  96. # 需要注意的是其返回的只是种群个体下标划分的列表集(非值,形式如上)
  97. # 计算拥挤距离
  98. def crowding_distance(values1, values2, front): # 注意:此处front是一维列表形式,每个层次序号
  99. distance = [0 for i in range(0, len(front))] # 初始化该层个体距离集合,且初值为0
  100. sorted1 = sort_by_values(front, values1[:]) # 返回函数1该层最小的索引(并设置好了无穷)
  101. sorted2 = sort_by_values(front, values2[:]) # 返回函数2该层最小的索引(并设置好了无穷)
  102. distance[0] = 4444444444444444 # 初始化(正无穷)
  103. distance[len(front) - 1] = 4444444444444444 # 初始化(正无穷)
  104. for k in range(1, len(front) - 1): # 求函数1的拥挤度
  105. distance[k] = distance[k] + (values1[sorted1[k + 1]] - values2[sorted1[k - 1]]) / (max(values1) - min(values1))
  106. for k in range(1, len(front) - 1): # 加上函数2的拥挤度
  107. distance[k] = distance[k] + (values1[sorted2[k + 1]] - values2[sorted2[k - 1]]) / (max(values2) - min(values2))
  108. return distance # 返回改层拥挤距离集
  109. # 执行交叉
  110. def crossover(a, b):
  111. answer=[]
  112. for i in range(len(a)):
  113. r = random.random()
  114. if r > 0.5: # 算术交叉(由两个个体的线性组合而产生两个新的个体,该操作对象一般由浮点数编码表示的个体)
  115. answer.append(mutation((a[i] + b[i]) / 2,min_xi[i],max_xi[i]))
  116. else:
  117. answer.append(mutation((a[i] - b[i]) / 2,min_xi[i],max_xi[i]))
  118. # return mutation((a - b) / 2)
  119. return answer
  120. # 执行变异算子
  121. def mutation(solution,minx,maxx):
  122. mutation_prob = random.random()
  123. if mutation_prob < 1:
  124. solution = minx + (maxx - minx) * random.random()
  125. return solution
  126. # 生成初始种群
  127. def init(min_xi, max_xi, num):
  128. i = 0
  129. solution = [] # 存放结果种群数组,里面存放的每个元素格式为[x1,x2,x3……]
  130. while (i < num):
  131. x=[0]*len(min_xi)
  132. #随机生成x值
  133. for j in range(len(min_xi)):
  134. x[j]=min_xi[j] + (max_xi[j] - min_xi[j]) * random.random()
  135. #计算约束值
  136. z1=0.0625*x[0]
  137. z2=0.0625*x[1]
  138. g1=0.00954*x[2]-z2
  139. g2=0.0193*x[2]-z1
  140. if(g1<0 and g2<0):
  141. solution.append(x)
  142. i+=1
  143. return solution
  144. # 主程序从这里开始
  145. pop_size = 30
  146. max_gen = 1000
  147. # 初始化
  148. min_xi = [1, 1, 10, 10]
  149. max_xi = [99, 99, 200, 200]
  150. solution=init(min_xi,max_xi,pop_size) #solution的结构为[[x1,x2,x3,x4],[x1,x2,x3,x4]]
  151. print("solution:")
  152. print(solution)
  153. gen_no = 0
  154. while (gen_no < max_gen): # 循环921代,即每次循环为一个繁殖
  155. # 将产生的20个种群个体分别运用到function1 和function2
  156. # 即function1_values和function2_values为不同函数的计算值列表
  157. function1_values = [function1(solution[i][0],solution[i][1],solution[i][2],solution[i][3]) for i in range(0, pop_size)]
  158. function2_values = [function2(solution[i][2],solution[i][3]) for i in range(0, pop_size)]
  159. cv=[CV(solution[i]) for i in range(0,pop_size)]
  160. # print(function2_values[:])
  161. # 运行快速非支配排序法非支配排序解集合 (在python中使用列表切片[:]既可以复制原列表,复制后又不会改变原列表)
  162. non_dominated_sorted_solution = fast_non_dominated_sort(function1_values[:], function2_values[:],cv)
  163. print("第", gen_no, "代最优的点集是:") # 开始输出结果
  164. for valuez in non_dominated_sorted_solution[0]: # 遍历最优解集合(存储的只是下标)
  165. print([round(solution[valuez][0], 3),round(solution[valuez][1], 3),round(solution[valuez][2], 3),round(solution[valuez][3], 3)], end=" ") # round() 返回浮点数x的四舍五入值
  166. print("\n")
  167. print("第", gen_no, "代最优的解是:") # 开始输出结果
  168. result=[]
  169. print(len(non_dominated_sorted_solution[0]))
  170. for valuez in non_dominated_sorted_solution[0]: # 遍历最优解集合(存储的只是下标)
  171. print([function1_values[valuez],function2_values[valuez]],end=" ")
  172. result.append([function1_values[valuez],function2_values[valuez]]) # round() 返回浮点数x的四舍五入值
  173. print("\n")
  174. # print(len(result))
  175. crowding_distance_values = [] # 定义拥挤距离值
  176. for i in range(0, len(non_dominated_sorted_solution)): # 遍历快速非支配排序法产生的分级结果集
  177. crowding_distance_values.append(crowding_distance(function1_values[:], function2_values[:],
  178. non_dominated_sorted_solution[i][
  179. :])) # 计算拥挤距离 (高级用法[:]( ̄▽ ̄)~*)
  180. # 求出每层的拥挤距离值并集中到crowding_distance_values
  181. solution2 = solution[:] # (在python中使用列表切片[:]既可以复制原列表,复制后又不会改变原列表)
  182. # 产生后代
  183. while (len(solution2) != 2 * pop_size): # 使产生的后代后种群大小为2N
  184. a1 = random.randint(0, pop_size - 1) # random.randint(a,b)
  185. b1 = random.randint(0, pop_size - 1) # 随机产生[a,b]中的一个数
  186. solution2.append(crossover(solution[a1], solution[b1])) # 通过交叉变异产生一个新的后代
  187. # 将产生的2N个种群个体分别运用到function1 和function2
  188. # 即function1_values2和function2_values2为不同函数的计算值列表
  189. function1_values2 = [function1(solution2[i][0],solution2[i][1],solution2[i][2],solution2[i][3]) for i in range(0, 2 * pop_size)]
  190. function2_values2 = [function2(solution2[i][2],solution2[i][3]) for i in range(0, 2 * pop_size)]
  191. cv2=[CV(solution2[i]) for i in range(0,2*pop_size)]
  192. non_dominated_sorted_solution2 = fast_non_dominated_sort(function1_values2[:], function2_values2[:],cv2) # 再次求快速非支配排序法
  193. crowding_distance_values2 = []
  194. for i in range(0, len(non_dominated_sorted_solution2)):
  195. crowding_distance_values2.append(
  196. crowding_distance(function1_values2[:], function2_values2[:], non_dominated_sorted_solution2[i][:]))
  197. # 求出每层的拥挤距离值并集中到crowding_distance_values2
  198. new_solution = [] # 初始化新解集
  199. for i in range(0, len(non_dominated_sorted_solution2)): # 遍历拥挤距离集层
  200. non_dominated_sorted_solution2_1 = [
  201. index_of(non_dominated_sorted_solution2[i][j], non_dominated_sorted_solution2[i]) for j in
  202. range(0, len(non_dominated_sorted_solution2[i]))] #
  203. front22 = sort_by_values(non_dominated_sorted_solution2_1[:], crowding_distance_values2[i][:])
  204. front = [non_dominated_sorted_solution2[i][front22[j]] for j in
  205. range(0, len(non_dominated_sorted_solution2[i]))]
  206. front.reverse() # 将前沿解集进行翻转
  207. for value in front: # 遍历前沿解集
  208. new_solution.append(value) # 添加到新的解集合
  209. if (len(new_solution) == pop_size):
  210. break
  211. if (len(new_solution) == pop_size): # 保证新的种群个数仍然为N
  212. break
  213. solution = [[solution2[i][0],solution2[i][1],solution2[i][2],solution2[i][3]] for i in new_solution]
  214. gen_no = gen_no + 1
  215. f = open("k1.txt", "a")
  216. f.writelines(str(result))
  217. f.writelines('\n')
  218. f.close()
  219. # 绘制图形
  220. function1 = [i * -1 for i in function1_values]
  221. function2 = [j * -1 for j in function2_values]
  222. plt.xlabel('Function 1', fontsize=10)
  223. plt.ylabel('Function 2', fontsize=10)
  224. plt.scatter(function1, function2)
  225. plt.savefig('image1/20.jpg')
  226. plt.show()

结果图:

 也测试了RCM25,结果图如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/150474?site
推荐阅读
相关标签
  

闽ICP备14008679号