遗传算法

    由于工作的需要,花了3天时间,彻底学习了一下遗传算法。遗传算法的算法思想还是比较好理解的。算法主要由四部分组成:初始化算法引擎及种群、选择、交叉和变异过程。

     对于程序的结束条件,可以设置确定的迭代代数generation,也可以根据算法的收敛情况,自动结束。直接上Python代码:

# -*- coding: utf-8 -*-  
from __future__ import division
import random
import math
import copy
import numpy as np
import matplotlib.pyplot as plt

class Genome:
    def __init__(self):
        self.genomeList = [] #一条染色体
        self.fitness = 0
        
    def init(self, chromoLength, leftPoint, rightPoint):
        for idx in range(0, chromoLength):
            self.genomeList.append(random.random()*(rightPoint - leftPoint) + leftPoint)
            self.fitness = ObjectFunction(self.genomeList[0])
            
class GenAlg:    
    def __init__(self, popSize, chromoLength, mutationRate, crossoverRate, maxPerturbation, leftPoint, rightPoint, generation):
        self.popSize = popSize              #种群数量
        self.chromoLength = chromoLength    #基因的总数目
        self.mutationRate = mutationRate    #基因突变概率,一般介于0.05和0.3
        self.crossoverRate = crossoverRate  #基因交叉的概率一般设为0.7
        self.maxPerturbation = maxPerturbation #最大变异步长
        self.leftPoint = leftPoint
        self.rightPoint = rightPoint
        self.generation = generation         #迭代代数
        self.totalFitness = 0                #所有个体适应性评分的综合
        self.popList = []                    #初始化种群
        self.allGenerationPop = []     #种群的适应值,保存了所有代的种群适应值
        self.allGenerationFitResult = []
        
    def initPop(self):
        self.popList = [] #清空list
        for idx in range(0, self.popSize):
            genome = Genome()
            genome.init(self.chromoLength, self.leftPoint, self.rightPoint)
            self.popList.append(genome)
            
    #进行选择交叉、变异,根据选择函数进行选择,然后进行交叉、变异
    def chosen(self):
        """选择
            输入:上一代的种群,种群的适应值
            输出:下一代的种群
            两代种群的数量相同,在选择新种群时,选择N(N=种群的大小)次,每次采用轮盘法,选择一条基因到下一代种群中去
            适应值高的会有更大的可能性被选入下一代
        """
        beChosenIdx = []
        beChosen = []
        #计算累计概率
        fitResult = self.allGenerationFitResult[len(self.allGenerationFitResult) - 1]
        totalFitness = sum(fitResult)
        
        ratio = []
        for idx in range(0, self.popSize):
            ratio.append(sum(fitResult[:idx+1]) / totalFitness)
                    
        for i in range(0, self.popSize):
            randValue = random.random()
            for idx in range(0, self.popSize):
                if ratio[idx] > randValue:
                    beChosenIdx.append(idx)
                    break
        for idx in range(0, len(beChosenIdx)):
            beChosen.append(self.popList[beChosenIdx[idx]])
                                
        return beChosen
        
    def crossOver(self):
        """交叉
        交叉(crossover),群体中的每个个体之间都以一定的概率 pc 交叉,即两个个体从各自字符串的某一位置  
        (一般是随机确定)开始互相交换,这类似生物进化过程中的基因分裂与重组。
        例如,假设2个父代个体x1,x2为: x1=0100110 x2=1010001 
            从每个个体的第3位开始交叉,交又后得到2个新的子代个体y1,y2分别为: y1=0100001 y2=1010110  
        这样2个子代个体就分别具有了2个父代个体的某些特征。利用交又我们有可能由父代个体在子代组合成具有更高适合度的个体。 
        事实上交又是遗传算法区别于其它传统优化方法的主要特点之一。
        
        二进制编码的交叉伪代码如下:
        for idx = 0; idx <popSize; idx += 2 
            if rand < pc
                随机生成交换位置cPoint,在cPoint之后的进制数进行交换
                idx 与 idx+1 下标的染色体进行交叉
            if rand > pc
                不进行交叉,将idx与idx+1直接赋值给新的染色体
                
        实数编码,如何进行交叉呢,且看下面代码?
        将相邻的两个染色体进行加权
        """
        #Reference http://www.docin.com/p-112399856.html
        for idx in range(0, self.popSize - 1, 2): #每两组取出来一次
            if (random.random() < self.crossoverRate):
                crossOverPosition = random.randint(0, len(self.popList[idx].genomeList) - 1)
                alpha = random.random()
                beta = random.random()
                               
                genomeA = copy.deepcopy(self.popList[idx])
                genomeB = copy.deepcopy(self.popList[idx + 1])
                
                for i in range(crossOverPosition, self.chromoLength - 1):
                    valA = alpha * genomeA.genomeList[i] + (1 - alpha)*genomeB.genomeList[i]
          
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值