NSGA-II的python带注释的代码
时间: 2023-11-12 10:11:30 浏览: 86
nsga_2.zip_NSGA-II_zip
以下是NSGA-II算法的Python代码(附有注释):
```python
import random
import numpy as np
# 定义一个类来表示每个个体
class Individual:
def __init__(self, x, y):
self.x = x
self.y = y
self.rank = None
self.crowding_distance = None
# 计算个体的适应度函数值
def evaluate(self):
self.fitness = [self.x**2, self.y**2]
# 初始化种群
def initialize_population(pop_size):
population = []
for i in range(pop_size):
x = random.uniform(-5, 5)
y = random.uniform(-5, 5)
individual = Individual(x, y)
individual.evaluate()
population.append(individual)
return population
# 计算支配关系
def dominates(x, y):
return all(x_i >= y_i for x_i, y_i in zip(x.fitness, y.fitness)) and any(x_i > y_i for x_i, y_i in zip(x.fitness, y.fitness))
# 计算非支配排序
def non_dominated_sort(population):
# 存储支配个体的数量
domination_count = [0] * len(population)
# 存储每个个体被哪些个体支配
dominated_individuals = [[] for _ in range(len(population))]
# 存储每个个体支配的个体
dominating_individuals = [[] for _ in range(len(population))]
# 存储每个个体的等级
ranks = [None] * len(population)
# 第一层中的个体没有被任何个体支配
front_1 = []
for i, individual in enumerate(population):
for j, other_individual in enumerate(population):
if i == j:
continue
if dominates(individual, other_individual):
# i 支配 j
dominating_individuals[i].append(j)
dominated_individuals[j].append(i)
elif dominates(other_individual, individual):
# i 被 j 支配
domination_count[i] += 1
if domination_count[i] == 0:
ranks[i] = 1
front_1.append(i)
fronts = [front_1]
current_front = 0
while True:
next_front = []
for i in fronts[current_front]:
for j in dominating_individuals[i]:
domination_count[j] -= 1
if domination_count[j] == 0:
ranks[j] = current_front + 2
next_front.append(j)
if not next_front:
break
fronts.append(next_front)
current_front += 1
for i, individual in enumerate(population):
individual.rank = ranks[i]
return fronts
# 计算拥挤度
def crowding_distance(front):
distances = [0] * len(front)
# 对每个目标函数都进行排序
for i in range(2):
front.sort(key=lambda individual: individual.fitness[i])
distances[0] = distances[-1] = float('inf')
fitness_range = front[-1].fitness[i] - front[0].fitness[i]
# 计算每个个体的拥挤度
for j in range(1, len(front) - 1):
distances[j] += (front[j+1].fitness[i] - front[j-1].fitness[i]) / fitness_range
for i, individual in enumerate(front):
individual.crowding_distance = distances[i]
# 计算新的种群
def reproduce(fronts, pop_size):
new_population = []
current_size = 0
front_index = 0
# 按照等级从前往后遍历每一层
while current_size < pop_size and front_index < len(fronts):
# 如果加入这一层的所有个体总数小于等于种群大小,则全部加入新种群
if current_size + len(fronts[front_index]) <= pop_size:
for individual_index in fronts[front_index]:
new_population.append(population[individual_index])
current_size += 1
front_index += 1
else:
# 否则,按照拥挤度选择部分个体加入新种群
crowding_distances = [individual.crowding_distance for individual in fronts[front_index]]
sort_order = np.argsort(crowding_distances)[::-1]
for i in sort_order:
new_population.append(population[fronts[front_index][i]])
current_size += 1
if current_size == pop_size:
break
front_index += 1
return new_population
# 初始化种群
population = initialize_population(100)
# 迭代次数
num_generations = 50
# 进化
for generation in range(num_generations):
fronts = non_dominated_sort(population)
for front in fronts:
crowding_distance(front)
population = reproduce(fronts, len(population))
# 输出 Pareto 最优解
pareto_front = non_dominated_sort(population)[0]
for index in pareto_front:
print(population[index].fitness)
阅读全文