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