经典多目标优化算法MOEA/D的Python实现

International Journal of Complexity in Applied Science and Technology,收录进化计算,机器学习和大数据方面的论文, 网址:https://www.inderscience.com/jhome.php?jcode=ijcast 

python
Copy code
from exceptions import NotImplementedError
from deap import tools

import random
import math
from copy import deepcopy

class MOEAD(object):

    def __init__(self, population, toolbox, mu, cxpb, mutpb, ngen=0, maxEvaluations=0,
                 T=20, nr=2, delta=0.9, stats=None, halloffame=None, verbose=__debug__, dataDirectory="weights"):
        # 初始化MOEAD算法的参数和变量

        self.populationSize_ = int(0)  # 种群大小初始化为0

        # 引用DEAP的工具箱
        self.toolbox = toolbox

        # 存储种群
        self.population = []

        if population:
            self.population = population
            fitnesses = self.toolbox.map(self.toolbox.evaluate, self.population)
            for ind, fit in zip(self.population, fitnesses):
                ind.fitness.values = fit
            
            self.populationSize_ = mu  # 设置种群大小

        # 重复引用工具箱
        self.toolbox = toolbox

        # 初始化Z向量(理想点)
        self.z_ = []  # 浮点数列表

        # 初始化Lambda向量(权重向量)
        self.lambda_ = []  # 浮点数列表的列表

        # 邻域大小
        self.T_ = int(0)

        # 邻域
        self.neighbourhood_ = []  # 整数列表的列表

        # 父代选择从邻域中选择的概率
        self.delta_ = delta

        # 每个子代最大替换个体数
        self.nr_ = nr
        
        self.indArray_ = list()  # 个体列表
        self.functionType_ = str()
        self.evaluations_ = int()

        # 操作符(变异和交叉)
        try:
            self.toolbox.mate
            self.toolbox.mutate
        except Exception as e:
            print "Error in MOEAD.__init__: toolbox.mutate or toolbox.mate is not assigned."
            raise e                     

        # 额外变量
        self.n_objectives = len(self.population[0].fitness.values)
        self.cxpb = cxpb
        self.mutpb = mutpb
        self.ngen = ngen
        self.paretoFront = halloffame
        
        self.maxEvaluations = -1
        if maxEvaluations == ngen == 0:
            print "maxEvaluations or ngen must be greater than 0."
            raise ValueError
        if ngen > 0:
            self.maxEvaluations =  ngen * self.populationSize_
        else:
            self.maxEvaluations = maxEvaluations
        
        self.dataDirectory_ = dataDirectory
        self.functionType_ = "_TCHE1"
        self.stats = stats
        self.verbose = verbose

        # 代码从execute函数上移
        self.T_ = T
        self.delta_ = delta
        
    def execute(self):
        print "Executing MOEA/D"

        logbook = tools.Logbook()
        logbook.header = ['gen', 'evals'] + (self.stats.fields if self.stats else [])
        
        self.evaluations_ = 0
        print "POPSIZE:", self.populationSize_
    
        self.indArray_ = [ self.toolbox.individual() for _ in range(self.n_objectives) ]

        # 初始化二维列表(种群大小 x 邻域大小)
        self.neighbourhood_ = [[None] * self.T_] * (self.populationSize_)  

        # 初始化理想点列表
        self.z_ = self.n_objectives * [None]
        
        # 初始化权重向量列表
        self.lambda_ = [[None for _ in range(self.n_objectives)] for i in range(self.populationSize_)]

        # 第一步:初始化
        self.initUniformWeight()
        self.initNeighbourhood()
        self.initIdealPoint()
        
        record = self.stats.compile(self.population) if self.stats is not None else {}
        
        logbook.record(gen=self.ngen , evals=self.evaluations_, **record)
        if self.verbose: print logbook.stream
        
        while self.evaluations_ < self.maxEvaluations:
            permutation = [None] * self.populationSize_  # 整数列表
            self.randomPermutations(permutation, self.populationSize_)

            for i in xrange(self.populationSize_):
                n = permutation[i]
                type_ = int()
                rnd = random.random()

                # 第二步:基于概率的选择
                if rnd < self.delta_:
                    type_ = 1
                else:
                    type_ = 2

                p = list()  # 整数列表
                self.matingSelection(p, n, 2, type_)

                # 第二步:交配
                child = None
                children = []
                parents = [None] * 3

                candidates = list(self.population[:])
                parents[0] = deepcopy(candidates[p[0]])
                parents[1] = deepcopy(candidates[p[1]])

                children = self.toolbox.mate(parents[0], parents[1])                
                
                # 变异
                children = [self.toolbox.mutate(child) for child in children]
                # 评价
                offspring = []

                for child in children:
                    fit = self.toolbox.evaluate(child[0])
                    self.evaluations_ += 1
                    child[0].fitness.values = fit
                    offspring.append(child[0])

                # 第二步:更新理想点
                for child in offspring:
                    self.updateReference(child)

                    # 第二步:更新解
                    self.updateProblem(child, n, type_)
                            
                record = self.stats.compile(self.population) if self.stats is not None else {}

                logbook.record(gen=self.ngen, evals=self.evaluations_, **record )

                if self.verbose: print logbook.stream

                
        return self.population

    # 初始化权重向量
    def initUniformWeight(self):
        if self.n_objectives == 2: 
            for n in xrange(self.populationSize_):
                a = 1.0 * float(n) / (self.populationSize_ - 1)
                self.lambda_[n][0] = a
                self.lambda_[n][1] = 1 - a
        elif self.n_objectives == 3:
            m = self.populationSize_

            self.lambda_ = list()
            for i in xrange(m):
                for j in xrange(m):
                    if i+j <= m:
                        k = m - i - j
                        try:
                            weight_scalars = [None] * 3
                            weight_scalars[0] = float(i) / (m)
                            weight_scalars[1] = float(j) / (m)
                            weight_scalars[2] = float(k) / (m)
                            self.lambda_.append(weight_scalars)
                        except Exception as e:
                            print "Error creating weight with 3 objectives at:"
                            print "count", count
                            print "i", i
                            print "j", j
                            print "k", k
                            raise e
            # 修剪权重向量以适应种群大小
            self.lambda_ = sorted((x for x in self.lambda_), key=lambda x: sum(x), reverse=True)
            self.lambda_ = self.lambda_[:self.populationSize_]
        else:
            dataFileName = "W" + str(self.n_objectives) + "D_" + str(self.populationSize_) + ".dat"
            file_ = self.dataDirectory_ + "/" + dataFileName
            try:
                with open(file_, 'r') as f:
                    numberOfObjectives = 0
                    i = 0
                    for aux_ in f:
                        j = 0
                        aux = aux_.strip()
                        tokens = aux.split(" ")
                        n_objectives = len(tokens)
                        try:
                            for value in tokens:
                                self.lambda_[i][j] = float(value)
                                j += 1
                        except Exception as e:
                            print "Error loading floats as weight vectors"
                            print "tokens", tokens
                            print "value:",  value
                            print "lambda_", len(self.lambda_),"*",len(self.lambda_[0])
                            print i, j, aux_
                            print e
                            raise e
                        i += 1
                f.close()
            except Exception as e:
                print "initUniformWeight: failed when reading for file:", file_
                print e
                raise e

    # 初始化邻域
    def initNeighbourhood(self):
        x = [None] * self.populationSize_  # 浮点数列表
        idx = [None] * self.populationSize_  # 整数列表

        for i in xrange(self.populationSize_):
            for j in xrange(self.populationSize_):
                x[j] = self.distVector(self.lambda_[i], self.lambda_[j])
                idx[j] = j

            self.minFastSort(x, idx, self.populationSize_, self.T_)
            self.neighbourhood_[i][0:self.T_] = idx[0:self.T_]

    # 初始化种群
    def initPopulation(self):
        for i in xrange(self._populationSize):
            if True:
                continue
            # 生成解
            # 评价解
            self.evaluations_ += 1
            # 将解加入种群           
        raise NotImplementedError

    # 初始化理想点
    def initIdealPoint(self):
        for i in range(self.n_object

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MOEA/D (Multi-Objective Evolutionary Algorithm Based on Decomposition)是一种多目标优化算法。它将多目标优化问题转化为多个单目标优化问题,并通过分解技术来解决这些单目标优化问题。下面是用Python实现MOEA/D的简单步骤: 1. 定义目标函数和变量范围。 2. 初始化种群,并为每个个体分配权重向量。 3. 计算每个个体的适应度值,并根据适应度值对种群进行排序。 4. 选择父代,并根据父代生成子代。 5. 对生成的子代进行修剪,保留最优的子代。 6. 更新参考点和权重向量,并将新的参考点和权重向量用于下一代进化。 下面是一个简单的Python代码示例: ```python import numpy as np # 定义目标函数 def obj_func(x): f1 = x**2 + x**2 f2 = (x-1)**2 + x**2 return [f1, f2] # 定义变量范围 x_min = np.array([-5, -5]) x_max = np.array([5, 5]) # 初始化种群和权重向量 pop_size = 100 num_obj = 2 pop = np.random.uniform(low=x_min, high=x_max, size=(pop_size, len(x_min))) weights = np.random.uniform(low=0, high=1, size=(pop_size, num_obj)) weights = weights / np.sum(weights, axis=1)[:, None] # 进行进化迭代 num_generations = 100 for gen in range(num_generations): # 计算适应度值并排序 fitness = np.array([obj_func(x) for x in pop]) ranks = np.argsort(np.argsort(-fitness.dot(weights.T), axis=0), axis=0) # 选择父代并生成子代 parents = np.random.choice(pop_size, size=pop_size) children = np.zeros_like(pop) for i in range(pop_size): parent1 = parents[i] parent2 = parents[(i+1) % pop_size] child = pop[parent1] + 0.5*(pop[parent2]-pop[parent1]) child += 0.01*np.random.normal(size=len(x_min)) child = np.clip(child, x_min, x_max) children[i] = child # 修剪子代并更新参考点和权重向量 fitness_children = np.array([obj_func(x) for x in children]) ranks_children = np.argsort(np.argsort(-fitness_children.dot(weights.T), axis=0), axis=0) pop_new = np.zeros_like(pop) for i in range(pop_size): if ranks_children[i] <= ranks[i]: pop_new[i] = children[i] else: pop_new[i] = pop[i] pop = pop_new weights = np.clip(weights + 0.01*np.random.normal(size=(pop_size, num_obj)), 0, 1) weights = weights / np.sum(weights, axis=1)[:, None] ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值