【问题标题】:Problems with genetic algorithm in PythonPython中遗传算法的问题
【发布时间】:2023-04-01 00:55:01
【问题描述】:

我有this 遗传算法应该给我010010010010 或最好的解决方案,突变它工作正常,但是当我尝试添加交叉时,有时它会显示这个错误:'NoneType' object has no attribute 'genes'。我已尝试从头开始重做 3 次,但始终是相同的错误。
调试也不起作用,因为它是随机的,有时它会在找到解决方案之前给出错误,有时没有错误。

半翻译代码(推荐看original 一个,加上一些葡萄牙语):

import random as r

BASE = '010010010010' #solution


class Populacao: #population
    MAX_POPULACAO = 8 #max population
    TAMANHO_TORNEIO = 5 #ignore
    TAXA_UNIFORME = 0.5 #uniform rate
    TAXA_MUTACAO = 0.015 #mutation rate
    elitismo = True #elitism

    #                  solution generate    chromossomes
    def __init__(self, solucao, gerar=True, cromossomos=None):
        self.solucao = solucao
        if gerar == True:
            self.cromossomos = self._gerar()
        else:
            if cromossomos == None:
                self.cromossomos = []
            else:
                self.cromossomos = cromossomos

        for c in self.cromossomos:
            c.calcularaptidao(self.solucao) # calculate fitness

    def setsolucao(self, solucao):
        self.solucao = solucao

    def _gerar(self):
        return [Cromossomo() for cromossomo in range(0, self.MAX_POPULACAO)]

    def setcromossomo(self, index, cromo):
        self.cromossomos[index] = cromo

    #   getbetter
    def getmelhor(self):
        c1 = self.cromossomos[0]
        for c in self.cromossomos:
            if c.aptidao > c1.aptidao: # c.fitness > c1.fitness
                c1 = c
        return c1

    #   getworst
    def getpior(self):
        #                            getindexofworst
        return self.cromossomos[self.getindicepior()]

    #   getindexofworst
    def getindicepior(self):
        indice = 0 #index
        c1 = self.cromossomos[0]
        for i in range(0, len(self.cromossomos)):
            if self.cromossomos[i].aptidao < c1.aptidao:
                c1 = self.cromossomos[i]
                indice = i
        return indice

    def __str__(self):
        return self.cromossomos

    #   mutation
    def mutacao(self, cromo):
        for i in range(0, len(cromo.genes)):
            if r.random() <= self.TAXA_MUTACAO:
                gene = r.choice([0, 1])
                cromo.setgene(i, gene)

    #   rouletteselection
    def selecaoroleta(self):
        somaaptidao = 0  # fitness sum
        for cromo in self.cromossomos:
            somaaptidao += cromo.aptidao

        #start
        comeco = 0
        for cromo in self.cromossomos:
            #porc = percentage
            porc = (cromo.aptidao * 360) / somaaptidao
            cromo.setporcao(porc)
            cromo.calcularintervalo(comeco) # calculate interval
            comeco += cromo.porcao #portion

        numaleatorio = r.randint(0, 360) #random number
        for cromo in self.cromossomos:
            if numaleatorio > cromo.intervalo[0] and numaleatorio <= cromo.intervalo[1]:
                return cromo

    #   evolve        population
    def evoluir(self, pop):
        newPop = Populacao(pop.solucao, True)

        #offset_elitism
        offset_elitismo = 0
        if pop.elitismo:
            #worst = newPop.getindexofworst()
            pior = newPop.getindicepior()
            newPop.cromossomos[pior] = pop.getmelhor()
            offset_elitismo = 1
        else:
            offset_elitismo = 0

        for i in range(offset_elitismo, len(pop.cromossomos)):
            cromo1 = pop.selecaoroleta() # roulette selection
            cromo2 = pop.selecaoroleta()

            newCromo = self.crossover(cromo1, cromo2)
            newCromo.calcularaptidao(pop.solucao)

            newPop.cromossomos.append(newCromo)

        for i in range(offset_elitismo, len(newPop.cromossomos)):
            self.mutacao(newPop.cromossomos[i])
            newPop.cromossomos[i].calcularaptidao(pop.solucao)
        return newPop

    def crossover(self, cromo1, cromo2):
        assert type(cromo1) != 'NoneType'
        assert type(cromo2) != 'NoneType'

        newCromo = cromo1
        for i in range(0, len(cromo1)):              #<--- error usually here
            if r.random() <= self.TAXA_UNIFORME:
                newCromo.setgene(i, cromo1.genes[i])
            else:
                newCromo.setgene(i, cromo2.genes[i])
        return newCromo


#     chromossomes
class Cromossomo:
    MAX_GENES = 12   #max genes
    aptidao = 0      #fitness
    porcao = 0       #portion
    intervalo = []   #interval

    def __init__(self, genes=None):
        self.genes = genes or self._gerar()

    def _gerar(self):
        cromo = []
        for i in range(0, self.MAX_GENES):
            cromo.append(r.choice([0, 1]))
        return ''.join(map(str, cromo))

    def calcularaptidao(self, solucao):
        apt = 0
        for i in range(0, self.MAX_GENES):
            if self.genes[i] == solucao[i]:
                apt += 1
        self.aptidao = apt

    def setporcao(self, porc):
        self.porcao = porc

    def calcularintervalo(self, comeco):
        self.intervalo = [comeco, comeco + self.porcao]

    def setgene(self, index, gene):
        s = ''
        for i in range(len(self.genes)):
            if i == index:
                s += str(gene)
            else:
                s += self.genes[i]
        self.genes = s

    def __str__(self):
        return self.genes

    def __len__(self):
        return len(self.genes)


if __name__ == '__main__':
    pop = Populacao(BASE, True)
    geracoes = 0              #generations
    geracoes_max = 100        #max generations

    melhor = None             #best chromossomes
    while pop.getmelhor().aptidao < len(BASE) and geracoes < geracoes_max:
        geracoes += 1
        pop = pop.evoluir(pop)
        melhor = pop.getmelhor()

        print('GENERATION ' + str(geracoes) + ', BEST: ' + str(melhor) +
              ', FITNESS: ' + str(melhor.aptidao))

    print('')
    if melhor.aptidao < len(BASE):
        print('BEST SOLUTION: ' + str(melhor))
    else:
        print('SOLUTION FOUND IN ' + str(geracoes) + ' GENERATIONS: ' +
              str(melhor))

    print('FITNESS: ' + str(melhor.aptidao))

【问题讨论】:

  • 好吧,你有一堆检查cromo1是否为None,但在代码中,cromo2为None并导致错误。
  • @JayCalamari 我更改了代码并运行了几次,cromo1 有时也是 None。

标签: python python-3.x genetic-algorithm


【解决方案1】:

似乎当错误发生时,selecaoreleta 运行但最后一个 for 循环没有返回任何内容。例如,如果你输入

for cromo in self.cromossomos:
    if numaleatorio > cromo.intervalo[0] and numaleatorio <= cromo.intervalo[1]:
        return cromo
else:
    print('no cromo found')

当错误发生时它会打印'no cromo found'。 (是的,您可以输入else 来指示如果for 循环在没有中断的情况下完成时该怎么办:p。)我不知道您正在检查什么条件,因为它是葡萄牙语,但不管它是什么,有时它是对流行的cromossomos中的任何cromo都不满意。

这不是一个完整的答案,但希望它有助于查明问题。

PS,您的断言可能无法正常工作。尝试在交叉函数中使用assert (cromo1 is not None) and (cromo2 is not None) 之类的东西,而不是使用type(cromo1) == 'NoneType'。那么 AssertionErrors 应该会更好地弹出。

编辑:

所以再次在 selecaoroleta 中,在使用随机 numaleatorio 的最后一个循环内,使用print(numaleatorio, cromo.intervalo) 打印出 numaleatorio 和间隔显示当 numaleatorio 为 0...或 360 时总是发生错误。但是选择的条件由于&gt;,如果numaleatorio 为0,即使intervalo[0] 也是0,cromo if numaleatorio &gt; cromo.intervalo[0] and numaleatorio &lt;= cromo.intervalo[1]: 也会失败。另一件事,最重要的是,打印出区间显示有时最高的区间是 359.9999999,因此 360 的 numaleatorio 也会失败。因此,解决方法可能是将 numaleatorio 更改为 numaleatorio = r.randint(1, 359)。或者,为了保持随机性,我可以使用numaleatorio = r.randint(0, 359),然后从&gt;&lt;= 切换到使用&gt;=&lt;。整个最后一个循环可能看起来像

numaleatorio = r.randint(0, 359)
for cromo in self.cromossomos:
    if numaleatorio >= cromo.intervalo[0] and numaleatorio < cromo.intervalo[1]:
        return cromo
else:
    raise ValueError('Intervalo was bad. No cromo found!')

else 再次与for 循环处于同一级别。它是for (blank in blank): ... else: (do stuff here if the for loop finished without being interrupted)。你可以随心所欲地做。) 这样,您的代码输出:

MELHOR SOLUCAO: 010010011010
APTIDAO: 11

我希望我知道这意味着什么。

【讨论】:

  • 哇,我什至没有想到错误可能在轮盘选择中,谢谢!我去看看。
  • 我再次更改了代码,所以现在每个染色体至少打印一次“cromo found”,循环用于检查间隔中的 cromo,所以它应该只返回一个克罗莫。
  • 您好,抱歉回复晚了。这有帮助,我想我明白了。不过,您现在可能已经这样做了:p(我编辑了我的答案)
  • 你说得对,它确实奏效了,谢谢你,很抱歉我不能翻译得更好,我在大学里有很多事情要做,而且时间不多。顺便说一句,如果你想玩,我会把算法放在那个链接里,我很快就会翻译它。
  • 听起来很酷。而且不用担心翻译。我只是喜欢巴西,真希望我能多了解葡萄牙语,呵呵。
猜你喜欢
  • 2016-06-23
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
  • 2019-02-23
相关资源
最近更新 更多