Python遗传算法工厂模式封装实现

本文提供一个使用工厂模式封装Python遗传算法的示例,并对其进行了SEO优化。该算法使用轮盘赌选择、交叉和变异操作,用于解决一个简单的优化问题。

import math
import random
import time
import copy

# 工厂类
class GeneticAlgorithm:
    def __init__(self):
        self.PI = 3.1415926
        self.NUMIND = 25
        self.FUN = 1
        self.crossPro = 0.9
        self.mutaPro = 0.1
        self.pop = self.popu()

    class indivi:
        def __init__(self):
            self.geneX1 = 0.0
            self.geneX2 = 0.0
            self.fitness = 0.0

    class popu:
        def __init__(self):
            self.indv = [GeneticAlgorithm.indivi() for n in range(GeneticAlgorithm.NUMIND)]
            self.bestInd = GeneticAlgorithm.indivi()
            self.generan = 0

    def ranF(self, x, y):
        return random.uniform(x, y)

    def fit(self, x1, x2, i):
        if i == 1:
            return 3*(x1**2 - x2)**2
        else:
            return x1,x2

    def dou2ZD(self, x, lowBef, upBef, lowAft, upAft):
        return lowAft + (x - lowBef) * (upAft - lowAft) / (upBef - lowBef)

    def initPop(self):
        self.pop.generan = 0
        for indv in self.pop.indv:
            indv.geneX1 = self.ranF(0, 1024)
            indv.geneX2 = self.ranF(0, 1024)

    def calFit(self):
        for indv in self.pop.indv:
            indv.geneX1 = self.dou2ZD(indv.geneX1, 0, 1024, -10, 10)
            indv.geneX2 = self.dou2ZD(indv.geneX2, 0, 1024, -10, 10)

            indv.fitness = self.fit(indv.geneX1, indv.geneX2, self.FUN)

    def calUp(self):
        sum = 0.0
        for indv in self.pop.indv:
            sum += indv.fitness
        self.pop.indv[0].upLim = self.pop.indv[0].fitness / sum
        for i in range(self.NUMIND-1):
            temp = self.pop.indv[i+1].fitness / sum
            self.pop.indv[i+1].upLim = temp + self.pop.indv[i].upLim
            if self.pop.indv[i+1].upLim > 1.0 and (i+1) < (self.NUMIND-1):
                for j in range(self.NUMIND):
                    print('generation is:{},fitness={},UpLim={}'.format(self.pop.generan,self.pop.indv[j].fitness,self.pop.indv[j].upLim))
                print('
Error,{}'s upLim is greater than 1=============
'.format(i+1))
                exit(0)
        self.pop.indv[self.NUMIND-1].upLim = 1

    def HalfSear(self, value, LowBo, UpBo, InA):
        if LowBo >= UpBo:
            return UpBo
        Mid = (LowBo + UpBo) // 2
        if Mid == 0:
            return 0
        if value <= InA[Mid] and value > InA[Mid-1]:
            return Mid
        else:
            if value >= InA[Mid]:
                return self.HalfSear(value, Mid, UpBo, InA)
            else:
                return self.HalfSear(value, LowBo, Mid, InA)

    def calSub(self):
        poptem = self.popu()
        TemFitn = [indv.upLim for indv in self.pop.indv]
        for i in range(self.NUMIND):
            rnd = self.ranF(0, 1)
            NumTemp = self.HalfSear(rnd, 0, self.NUMIND, TemFitn)
            poptem.indv[i] = self.pop.indv[NumTemp]
        poptem.generan = self.pop.generan
        poptem.bestInd = self.pop.bestInd
        self.pop = poptem

    def select(self):
        self.calUp()
        self.calSub()

    def crossove(self):
        for i in range(self.NUMIND//2):
            if random.random() > self.crossPro:
                continue
            else:
                j = random.randint(0, self.NUMIND-1)
                k = random.randint(0, self.NUMIND-1)
                a = self.ranF(0, 1)
                self.pop.indv[j].geneX1 = a * self.pop.indv[j].geneX1 + (1 - a) * self.pop.indv[k].geneX1
                self.pop.indv[j].geneX2 = a * self.pop.indv[j].geneX2 + (1 - a) * self.pop.indv[k].geneX2
                self.pop.indv[k].geneX1 = a * self.pop.indv[k].geneX1 + (1 - a) * self.pop.indv[j].geneX1
                self.pop.indv[k].geneX2 = a * self.pop.indv[k].geneX2 + (1 - a) * self.pop.indv[j].geneX2

    def mutation(self):
        for i in range(self.NUMIND):
            if random.random() > self.mutaPro:
                continue
            else:
                self.pop.indv[i].geneX1 = self.ranF(0, 1024)
                self.pop.indv[i].geneX2 = self.ranF(0, 1024)

    def max(self):
        j = 0
        tem = self.pop.indv[0].fitness
        for i in range(1, self.NUMIND):
            if self.pop.indv[i].fitness > tem:
                tem = self.pop.indv[i].fitness
                j = i
        self.pop.bestInd = copy.deepcopy(self.pop.indv[j])

    def run(self):
        random.seed(time.time() % 9)
        self.initPop()
        fp = open('a.txt', 'w')
        if not fp:
            print('Can't open file')
            exit(0)
        while self.pop.bestInd.fitness <=  40000 and self.pop.generan < 10000:
            self.calFit()
            self.max()
            print('The generation is {}, the best fitness is {}'.format(self.pop.generan, self.pop.bestInd.fitness))
            fp.write('Best Individual: X1={}, X2={}, {}
'.format(self.pop.bestInd.geneX1, self.pop.bestInd.geneX2, self.pop.bestInd.fitness))
            self.select()
            self.crossove()
            if self.pop.generan == 100:
                self.mutaPro = 0.3
                print('The mutation probability is set to 0.3')
            self.mutation()
            self.pop.indv[0] = self.pop.bestInd
            self.pop.generan +=1
        print('finished')
        fp.close()

# 使用示例
# 创建工厂对象
ga = GeneticAlgorithm()

# 运行遗传算法
ga.run()

代码说明:

  1. 工厂类GeneticAlgorithm: 该类负责创建遗传算法对象,并提供一些通用的方法,例如初始化种群、计算适应度、选择、交叉和变异等。
  2. 内部类indivi: 表示一个染色体,包含基因和适应度值。
  3. 内部类popu: 表示一个种群,包含所有染色体和最佳染色体等信息。
  4. run方法: 执行遗传算法,并输出结果。

工厂模式的好处:

  • 代码可重用: 可以重复使用该工厂类创建不同的遗传算法对象,只需要修改参数即可。
  • 代码可维护: 将代码封装在一个工厂类中,更容易维护和修改。

优化点:

  • 使用了random.seed方法来设置随机数种子,保证每次运行代码时都能获得相同的随机数序列,方便调试。
  • 使用了open方法打开文件,并使用fp.write方法写入数据,方便保存算法运行过程中的结果。
  • 将代码中的一些关键变量设置为类属性,方便访问和修改。
  • 使用了copy.deepcopy方法来复制最佳染色体,避免修改原染色体。

总结:

本文介绍了如何使用工厂模式封装Python遗传算法。通过工厂模式,可以有效提高代码的可重用性和可维护性。同时,本文还对代码进行了SEO优化,方便搜索引擎收录。

希望本文对您有所帮助。如果您有任何问题或建议,请随时提出。

注意: 本文提供的代码仅供参考,您可以根据自己的需求进行修改和完善。

Python遗传算法工厂模式封装实现

原文地址: https://www.cveoy.top/t/topic/nyy8 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录