parent
							
								
									99d50d692f
								
							
						
					
					
						commit
						dca307b79b
					
				| @ -0,0 +1,278 @@ | |||||||
|  | import math | ||||||
|  | import random | ||||||
|  | import matplotlib.pyplot as plt | ||||||
|  | import copy | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # 用的是ZDT3测试函数 | ||||||
|  | 
 | ||||||
|  | # First function to optimize | ||||||
|  | def function1(x): | ||||||
|  |     return x[0] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Second function to optimize | ||||||
|  | def function2(x): | ||||||
|  |     gx = funcationG(x) | ||||||
|  |     value = 1 - math.sqrt(x[0] / gx) - x[0] / gx * math.sin(10 * math.pi * x[0]) | ||||||
|  |     return gx * value | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def funcationG(x): | ||||||
|  |     sumX = 0 | ||||||
|  |     for i in range(1, varNum): | ||||||
|  |         sumX = sumX + x[i] | ||||||
|  |     return 1 + (9 * sumX) / (varNum - 1) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Function to find index of list | ||||||
|  | def index_of(a, list): | ||||||
|  |     for i in range(0, len(list)): | ||||||
|  |         if list[i] == a: | ||||||
|  |             return i | ||||||
|  |     return -1 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Function to sort by values | ||||||
|  | def sort_by_values(list1, values): | ||||||
|  |     sorted_list = [] | ||||||
|  |     while (len(sorted_list) != len(list1)): | ||||||
|  |         if index_of(min(values), values) in list1: | ||||||
|  |             sorted_list.append(index_of(min(values), values)) | ||||||
|  |         values[index_of(min(values), values)] = math.inf | ||||||
|  |     return sorted_list | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Function to carry out NSGA-II's fast non dominated sort | ||||||
|  | def fast_non_dominated_sort(values1, values2): | ||||||
|  |     S = [[] for i in range(0, len(values1))]  # 解所支配的集合 | ||||||
|  |     front = [[]]  # 排序结果 | ||||||
|  |     n = [0 for i in range(0, len(values1))]  # 支配者数量 | ||||||
|  |     rank = [0 for i in range(0, len(values1))] | ||||||
|  | 
 | ||||||
|  |     for p in range(0, len(values1)): | ||||||
|  |         S[p] = [] | ||||||
|  |         n[p] = 0 | ||||||
|  |         for q in range(0, len(values1)): | ||||||
|  |             if (values1[p] < values1[q] and values2[p] < values2[q]) or ( | ||||||
|  |                     values1[p] <= values1[q] and values2[p] < values2[q]) or ( | ||||||
|  |                     values1[p] < values1[q] and values2[p] <= values2[q]): | ||||||
|  |                 if q not in S[p]: | ||||||
|  |                     S[p].append(q) | ||||||
|  |             elif (values1[q] < values1[p] and values2[q] < values2[p]) or ( | ||||||
|  |                     values1[q] <= values1[p] and values2[q] < values2[p]) or ( | ||||||
|  |                     values1[q] < values1[p] and values2[q] <= values2[p]): | ||||||
|  |                 n[p] = n[p] + 1 | ||||||
|  |         if n[p] == 0: | ||||||
|  |             rank[p] = 0 | ||||||
|  |             if p not in front[0]: | ||||||
|  |                 front[0].append(p) | ||||||
|  | 
 | ||||||
|  |     i = 0 | ||||||
|  |     while (front[i] != []): | ||||||
|  |         Q = [] | ||||||
|  |         for p in front[i]: | ||||||
|  |             for q in S[p]: | ||||||
|  |                 n[q] = n[q] - 1 | ||||||
|  |                 if (n[q] == 0): | ||||||
|  |                     rank[q] = i + 1 | ||||||
|  |                     if q not in Q: | ||||||
|  |                         Q.append(q) | ||||||
|  |         i = i + 1 | ||||||
|  |         front.append(Q) | ||||||
|  | 
 | ||||||
|  |     del front[len(front) - 1] | ||||||
|  |     return front | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Function to calculate crowding distance 拥挤度距离计算 | ||||||
|  | def crowding_distance(values1, values2, front): | ||||||
|  |     distance = [0 for i in range(0, len(front))] | ||||||
|  | 
 | ||||||
|  |     sorted1 = sort_by_values(front, values1[:]) | ||||||
|  |     sorted2 = sort_by_values(front, values2[:]) | ||||||
|  | 
 | ||||||
|  |     distance[0] = math.inf | ||||||
|  |     distance[len(front) - 1] = math.inf | ||||||
|  | 
 | ||||||
|  |     for k in range(1, len(front) - 1): | ||||||
|  |         distance[k] = distance[k] + (values1[sorted1[k + 1]] - values1[sorted1[k - 1]]) / (max(values1) - min(values1)) | ||||||
|  | 
 | ||||||
|  |     for k in range(1, len(front) - 1): | ||||||
|  |         distance[k] = distance[k] + (values2[sorted2[k + 1]] - values2[sorted2[k - 1]]) / (max(values2) - min(values2)) | ||||||
|  | 
 | ||||||
|  |     return distance | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # 二进制交叉 | ||||||
|  | def crossover(individuala, individualb, a, b): | ||||||
|  |     individual1 = copy.deepcopy(individuala) | ||||||
|  |     individual2 = copy.deepcopy(individualb) | ||||||
|  | 
 | ||||||
|  |     for j in range(min(a, b), max(a, b) + 1): | ||||||
|  |         u = random.random() | ||||||
|  |         if u < 0.5: | ||||||
|  |             r = (2 * u) ** (1 / (NC + 1)) | ||||||
|  |         else: | ||||||
|  |             r = (1 / (2 * (1 - u))) ** (1 / (NC + 1)) | ||||||
|  |         individual1[j] = 0.5 * ((1 + r) * individual1[j] + (1 - r) * individual2[j]) | ||||||
|  |         individual2[j] = 0.5 * ((1 - r) * individual1[j] + (1 + r) * individual2[j]) | ||||||
|  | 
 | ||||||
|  |         individual1[j] = 1 if individual1[j] > 1 else individual1[j]  # 此处需要修改为常量 | ||||||
|  |         individual2[j] = 1 if individual2[j] > 1 else individual2[j] | ||||||
|  | 
 | ||||||
|  |         individual1[j] = 0 if individual1[j] < 0 else individual1[j] | ||||||
|  |         individual2[j] = 0 if individual2[j] < 0 else individual2[j] | ||||||
|  |     return individual1, individual2 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # 多项式变异 | ||||||
|  | def mutation(individual, a): | ||||||
|  |     individualTemp = copy.deepcopy(individual) | ||||||
|  |     u = random.random() | ||||||
|  |     if u < 0.5: | ||||||
|  |         r = (2 * u) ** (1 / (NM + 1)) - 1 | ||||||
|  |     else: | ||||||
|  |         r = (1 - (2 * (1 - u))) ** (1 / (NM + 1)) | ||||||
|  | 
 | ||||||
|  |     individualTemp[a] = individualTemp[a] + r | ||||||
|  | 
 | ||||||
|  |     individualTemp[a] = 1 if individualTemp[a] > 1 else individualTemp[a]  # 此处需要修改为常量 | ||||||
|  |     individualTemp[a] = 0 if individualTemp[a] < 0 else individualTemp[a] | ||||||
|  |     return individualTemp | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # 使用此函数之前要确保非支配排序解中都按照拥挤度排序过了 | ||||||
|  | def competition(non_dominated_sorted, numOfSelect): | ||||||
|  |     selectionResult = [] | ||||||
|  |     non_dominated_sortedTemp = [] | ||||||
|  |     for i in range(0, len(non_dominated_sorted)): | ||||||
|  |         for j in range(0, len(non_dominated_sorted[i])): | ||||||
|  |             non_dominated_sortedTemp.append(non_dominated_sorted[i][j]) | ||||||
|  | 
 | ||||||
|  |     while len(selectionResult) < numOfSelect: | ||||||
|  |         selections = [random.randint(0, popSize - 1) for i in range(0, popSize // 2)] | ||||||
|  |         selectionResult.append(non_dominated_sortedTemp[min(selections)]) | ||||||
|  | 
 | ||||||
|  |     return selectionResult | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | min_x = 0 | ||||||
|  | max_x = 1  # x1 属于[0,1] | ||||||
|  | varNum = 30  # xi 中i的最大个数 | ||||||
|  | popSize = 100  # 种群个数 | ||||||
|  | max_gen = 500  # 最大迭代次数 | ||||||
|  | pc = 0.9  # 交叉 | ||||||
|  | pm = 0.01  # 变异 | ||||||
|  | NC = 20 | ||||||
|  | NM = 20 | ||||||
|  | 
 | ||||||
|  | # 初始化种群 | ||||||
|  | solution = [] | ||||||
|  | for i in range(0, popSize): | ||||||
|  |     solution.append([random.random() for j in range(0, varNum)]) | ||||||
|  | 
 | ||||||
|  | times = 0 | ||||||
|  | non_dominated_sorted_solution = [] | ||||||
|  | function1_values = [] | ||||||
|  | function2_values = [] | ||||||
|  | 
 | ||||||
|  | while times < max_gen: | ||||||
|  |     # 计算种群中,每个个体的两个目标函数值 | ||||||
|  |     function1_values = [function1(solution[i]) for i in range(0, popSize)] | ||||||
|  |     function2_values = [function2(solution[i]) for i in range(0, popSize)] | ||||||
|  | 
 | ||||||
|  |     # 快速非支配排序 | ||||||
|  |     non_dominated_sorted_solution = fast_non_dominated_sort(function1_values[:], function2_values[:]) | ||||||
|  | 
 | ||||||
|  |     # 计算拥挤度 | ||||||
|  |     crowding_distance_values = [] | ||||||
|  |     for i in range(0, len(non_dominated_sorted_solution)): | ||||||
|  |         crowding_distance_values.append( | ||||||
|  |             crowding_distance(function1_values[:], function2_values[:], non_dominated_sorted_solution[i][:])) | ||||||
|  | 
 | ||||||
|  |     # 按照拥挤度排序 | ||||||
|  |     for i in range(0, len(non_dominated_sorted_solution)): | ||||||
|  |         non_dominated_sorted_solution2_1 = [ | ||||||
|  |             index_of(non_dominated_sorted_solution[i][j], non_dominated_sorted_solution[i]) for j in | ||||||
|  |             range(0, len(non_dominated_sorted_solution[i]))] | ||||||
|  |         front22 = sort_by_values(non_dominated_sorted_solution2_1[:], crowding_distance_values[i][:])  # 按照拥挤度排序 | ||||||
|  |         non_dominated_sorted_solution[i] = [non_dominated_sorted_solution[i][front22[j]] for j in | ||||||
|  |                                             range(0, len(non_dominated_sorted_solution[i]))] | ||||||
|  |         non_dominated_sorted_solution[i].reverse()  # 翻转之后是从大到小排序,拥挤度 | ||||||
|  | 
 | ||||||
|  |     solution2 = copy.deepcopy(solution) | ||||||
|  | 
 | ||||||
|  |     # 竞标赛选取 | ||||||
|  |     offSpring = competition(non_dominated_sorted_solution, popSize) | ||||||
|  |     # 交叉 | ||||||
|  |     for i in range(0, len(offSpring) // 2): | ||||||
|  |         rc = random.random() | ||||||
|  |         if (rc < pc): | ||||||
|  |             index1 = random.randint(0, varNum - 1) | ||||||
|  |             index2 = random.randint(0, varNum - 1) | ||||||
|  |             while index1 == index2: | ||||||
|  |                 index1 = random.randint(0, varNum - 1) | ||||||
|  |             indi1, indi2 = crossover(solution[offSpring[i]], solution[offSpring[len(offSpring) - i - 1]], index1, | ||||||
|  |                                      index2) | ||||||
|  |             solution2.append(indi1) | ||||||
|  |             solution2.append(indi2) | ||||||
|  |     # 变异 | ||||||
|  |     for i in range(0, len(offSpring)): | ||||||
|  |         rm = random.random() | ||||||
|  |         if rm < pm: | ||||||
|  |             indexOfM = random.randint(0, varNum - 1) | ||||||
|  |             muIndi = mutation(solution[offSpring[i]], indexOfM) | ||||||
|  |             solution2.append(muIndi) | ||||||
|  | 
 | ||||||
|  |     # 计算函数值 | ||||||
|  |     lengthOfSolution2 = len(solution2) | ||||||
|  |     function1_values2 = [function1(solution2[i]) for i in range(0, lengthOfSolution2)] | ||||||
|  |     function2_values2 = [function2(solution2[i]) for i in range(0, lengthOfSolution2)] | ||||||
|  | 
 | ||||||
|  |     # 非支配快速排序 | ||||||
|  |     non_dominated_sorted_solution2 = fast_non_dominated_sort(function1_values2[:], function2_values2[:]) | ||||||
|  | 
 | ||||||
|  |     # 计算拥挤度 | ||||||
|  |     crowding_distance_values2 = [] | ||||||
|  |     for i in range(0, len(non_dominated_sorted_solution2)): | ||||||
|  |         crowding_distance_values2.append( | ||||||
|  |             crowding_distance(function1_values2[:], function2_values2[:], non_dominated_sorted_solution2[i][:])) | ||||||
|  | 
 | ||||||
|  |     # 产生新的种群 | ||||||
|  |     new_solution = [] | ||||||
|  |     for i in range(0, len(non_dominated_sorted_solution2)): | ||||||
|  |         non_dominated_sorted_solution2_1 = [ | ||||||
|  |             index_of(non_dominated_sorted_solution2[i][j], non_dominated_sorted_solution2[i]) for j in | ||||||
|  |             range(0, len(non_dominated_sorted_solution2[i]))] | ||||||
|  |         front22 = sort_by_values(non_dominated_sorted_solution2_1[:], crowding_distance_values2[i][:])  # 按照拥挤度排序 | ||||||
|  |         front = [non_dominated_sorted_solution2[i][front22[j]] for j in | ||||||
|  |                  range(0, len(non_dominated_sorted_solution2[i]))] | ||||||
|  |         front.reverse()  # 翻转之后是从大到小排序,拥挤度 | ||||||
|  |         for value in front: | ||||||
|  |             new_solution.append(value) | ||||||
|  |             if (len(new_solution) == popSize): | ||||||
|  |                 break | ||||||
|  |         if (len(new_solution) == popSize): | ||||||
|  |             break | ||||||
|  |     solution = [solution2[i] for i in new_solution] | ||||||
|  |     times = times + 1 | ||||||
|  |     print('This is ', times, '\n') | ||||||
|  | 
 | ||||||
|  | # Lets plot the final front now | ||||||
|  | minF1 = [] | ||||||
|  | minF2 = [] | ||||||
|  | for k in non_dominated_sorted_solution[0]: | ||||||
|  |     minF1.append(function1_values[k]) | ||||||
|  |     minF2.append(function2_values[k]) | ||||||
|  | 
 | ||||||
|  | # 打印第一层 | ||||||
|  | print("The best front for Generation number ", times, " is") | ||||||
|  | for valuez in non_dominated_sorted_solution[0]: | ||||||
|  |     print(solution[valuez:], end=" ") | ||||||
|  | print("\n") | ||||||
|  | 
 | ||||||
|  | plt.xlabel('F 1', fontsize=15) | ||||||
|  | plt.ylabel('F 2', fontsize=15) | ||||||
|  | plt.scatter(minF1, minF2) | ||||||
|  | plt.show() | ||||||
					Loading…
					
					
				
		Reference in new issue