多目标优化中的非支配排序算法

多目标优化中的非支配排序算法
以NSGA-II为例
多目标优化指的是针对多个目标函数,去寻找一组最优解,形式如下:
在这里插入图片描述其中*fi(x)*是各单一的目标函数
但是多目标优化问题通常面临多个目标函数无法同时达到最优,为了解决这一问题,提出了pareto-Optimality的概念,
针对pareto-Optimality,有几个概念:
1.非支配解:假设任何二解S1 及S2 对所有目标而言,S1均优于S2,则我们称S1 支配S2,若S1 的解没有被其他解所支配,则S1 称为非支配解(不受支配解),也称Pareto解
支配解:若解S2的所有目标均劣于S1,则称S1优于S2,也称S1支配S2,S2为受支配解。
因此现在的首要任务是寻找解空间里面所有的Pareto解,找到所有Pareto解之后,这些解组成的平面叫做Pareto前沿面(Non-dominated front)。在目标函数较多时,前沿面通常为超曲面。
非支配解排序(Non-dominated Sorting)

  1. 设所有解的集合为S,现从中找出非支配解集合,记为F1

  2. 令S=S-F1,从S中再找出非支配解集合,记为F2

  3. 重复第二步,直到S为空集

将每次找出的非支配解进行排序如下:

{F1,F2,…,Fn}
例如:有两个目标函数Time(f1(x)),Cost(f2(x)),通过求解,我们获得了一组pareto解集,如下图所示:
在这里插入图片描述
对这个解集进行排序:
第一轮:我们发现A,B,D,F不能被其他解所支配,则这是第一组非支配解集;
然后我们针对剩余解集,C,E,G,H,I进行排序,C,E,G不能被其他解所支配,组成第二组非支配解集;
剩余的H,I,不能彼此支配,所以组成第三组非支配解集。
通过这个过程我们发现,非支配排序实际上就是“不断的剔除非支配解集,将目标值大的保留下来,然后进一步处理”。
matlab代码实现过程:

clear all
close all
functionvalue=[2 7.5;3 6;3 7.5;4 5;4 6.5;5 4.5;5 6;5 7;6 6.5];%当前的非支配解集
fnum=0;                                             %当前分配的前沿面编号,就是上述的第一轮,第二轮,第三轮
cz=false(1,size(functionvalue,1));                  %记录个体是否已被分配编号
frontvalue=zeros(size(cz));                         %每个个体的前沿面编号
[functionvalue_sorted,newsite]=sortrows(functionvalue);    %对种群按第一维目标值大小进行排序,第一位目标值相同,
%就对第二维目标进行排序
 while ~all(cz)
              fnum=fnum+1;
              d=cz;
              for i = 1:size(functionvalue,1)
                  if ~d(i)
                     for j=i+1:size(functionvalue,1)
                        if ~d(j)
                          k=1;
                          for m=2:size(functionvalue,2)
                                if functionvalue_sorted(i,m)>functionvalue_sorted(j,m)%将目标值大的解保留下来,来进行下一次排序,
%该过程通过d(j)=true实现
                                    k=0;
                                    break
                                end
                            end
                            if k
k
                                d(j)=true;
                            end
                         end
                    end
                    frontvalue(newsite(i))=fnum;
                    cz(i)=true;
                end
            end                                     
         endhon

```python
本文的数据来源于https://zhuanlan.zhihu.com/p/125161075,感谢该博客的指导

  • 7
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
多目标优化算法支配排序遗传算法Ⅱ(NSGA-II)是一种常用的多目标优化算法,它是对支配排序遗传算法(NSGA)的改进。NSGA-II在保留NSGA的支配排序和拥挤度距离计算的基础上,引入了快速支配排序和精英策略,以提高算法的收敛速度和搜索能力。 以下是NSGA-II算法的主要步骤: 1. 初始化种群,包括个体的编码方式和初始值。 2. 计算每个个体的适应度值,即目标函数值。 3. 进行支配排序,将种群的个体按照支配等级进行排序。 4. 计算每个个体的拥挤度距离,以保证种群的多样性。 5. 选择新的种群,包括精英策略和锦标赛选择策略。 6. 对新的种群进行交叉和变异操作,生成下一代种群。 7. 重复步骤2-6,直到满足停止条件。 以下是NSGA-II算法的Python实现示例: ```python # 引入相关库 import random import numpy as np # 定义目标函数 def obj_func(x): f1 = x[0]**2 + x[1]**2 f2 = (x[0]-1)**2 + x[1]**2 return [f1, f2] # 定义种群类 class Individual: def __init__(self, x): self.x = x self.obj = obj_func(x) self.rank = None self.crowding_distance = None # 定义NSGA-II算法类 class NSGA2: def __init__(self, pop_size, n_generations, p_crossover, p_mutation, n_obj): self.pop_size = pop_size self.n_generations = n_generations self.p_crossover = p_crossover self.p_mutation = p_mutation self.n_obj = n_obj self.population = None # 初始化种群 def initialize_population(self): self.population = [] for i in range(self.pop_size): x = np.random.uniform(-5, 5, size=self.n_obj) self.population.append(Individual(x)) # 计算支配排序 def non_dominated_sort(self, population): fronts = [[]] for individual in population: individual.domination_count = 0 individual.dominated_solutions = [] for other_individual in population: if individual.obj[0] < other_individual.obj[0] and individual.obj[1] < other_individual.obj[1]: individual.dominated_solutions.append(other_individual) elif individual.obj[0] > other_individual.obj[0] and individual.obj[1] > other_individual.obj[1]: individual.domination_count += 1 if individual.domination_count == 0: individual.rank = 0 fronts[0].append(individual) i = 0 while len(fronts[i]) > 0: next_front = [] for individual in fronts[i]: for dominated_individual in individual.dominated_solutions: dominated_individual.domination_count -= 1 if dominated_individual.domination_count == 0: dominated_individual.rank = i + 1 next_front.append(dominated_individual) i += 1 fronts.append(next_front) return fronts[:-1] # 计算拥挤度距离 def crowding_distance(self, front): n = len(front) for individual in front: individual.crowding_distance = 0 for m in range(self.n_obj): front = sorted(front, key=lambda individual: individual.obj[m]) front[0].crowding_distance = np.inf front[-1].crowding_distance = np.inf for i in range(1, n-1): front[i].crowding_distance += (front[i+1].obj[m] - front[i-1].obj[m]) / (front[-1].obj[m] - front[0].obj[m]) # 选择新的种群 def selection(self, fronts): new_population = [] n = 0 while len(new_population) < self.pop_size: if len(fronts[n]) < self.pop_size - len(new_population): new_population += fronts[n] n += 1 else: self.crowding_distance(fronts[n]) fronts[n] = sorted(fronts[n], key=lambda individual: individual.crowding_distance, reverse=True) new_population += fronts[n][:self.pop_size - len(new_population)] self.population = new_population # 变异操作 def mutation(self, individual): for i in range(self.n_obj): if random.random() < self.p_mutation: individual.x[i] += np.random.normal(0, 1) individual.x[i] = max(min(individual.x[i], 5), -5) individual.obj = obj_func(individual.x) # 交叉操作 def crossover(self, parent1, parent2): if random.random() < self.p_crossover: child1 = Individual(np.zeros(self.n_obj)) child2 = Individual(np.zeros(self.n_obj)) alpha = np.random.uniform(0, 1, size=self.n_obj) for i in range(self.n_obj): child1.x[i] = alpha[i] * parent1.x[i] + (1 - alpha[i]) * parent2.x[i] child2.x[i] = alpha[i] * parent2.x[i] + (1 - alpha[i]) * parent1.x[i] child1.obj = obj_func(child1.x) child2.obj = obj_func(child2.x) return child1, child2 else: return parent1, parent2 # 进化 def evolve(self): self.initialize_population() for i in range(self.n_generations): fronts = self.non_dominated_sort(self.population) self.selection(fronts) offspring_population = [] while len(offspring_population) < self.pop_size: parent1 = random.choice(self.population) parent2 = random.choice(self.population) child1, child2 = self.crossover(parent1, parent2) self.mutation(child1) self.mutation(child2) offspring_population.append(child1) if len(offspring_population) < self.pop_size: offspring_population.append(child2) self.population += offspring_population # 运行NSGA-II算法 nsga2 = NSGA2(pop_size=100, n_generations=100, p_crossover=0.9, p_mutation=0.1, n_obj=2) nsga2.evolve() # 输出最终种群 for individual in nsga2.population: print(individual.obj) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值