遗传算法不收敛

时间:2019-03-25 10:59:38

标签: python genetic-algorithm

因此,我正在尝试使用遗传算法创建路径查找器。因此,在我的代码中,我创建了尺寸为10x10的正方形,我希望它向右移动,同时避开目标也是10x10的障碍。但是,无论何时我运行代码,生成的适应度都不会增加,因此我的遗传算法不会收敛。我该怎么做才能优化我的代码并使算法收敛?我正在使用pygame绘制路径板。在基因组阵列达到600个大小之后,我也停止生成基因组。

这是我的代码 '''python

import random
import sys


class Genome:

def __init__(self):
    self.genome_array = []
    self.fitness = 0
    self.x_position = 50
    self.y_position = 250
    self.genome_size = 50
    self.total_size = 0
    self.goal_x = 500
    self.goal_y = 250
    self.vel = 10

def generateGenome(self):
    i = 0
    while i < self.genome_size:
        print("GenerateGenome")
        position = self.generatePosition(self.x_position, self.y_position)
        self.genome_array.append(position)
        self.x_position += position[0]
        self.y_position += position[1]
        (self.fitness, endGame) = self.calcfitness(
            [self.x_position, self.y_position])
        if endGame:
            return (endGame, self.fitness)
        i += 1
    self.total_size += self.genome_size
    return (endGame, self.fitness)

def calcfitness(self, player_position):
    # x position
    if player_position[0] > self.goal_x:
        pos_x = player_position[0] - self.goal_x
        fitnessX = pos_x / self.goal_x
        fitnessX = 1 - fitnessX

    else:
        fitnessX = player_position[0] / self.goal_x

    # y position
    if player_position[1] > self.goal_y:
        pos_y = player_position[1] - self.goal_y
        fitnessY = pos_y / self.goal_y
        fitnessY = 1 - fitnessY
    else:
        fitnessY = player_position[0] / self.goal_y

    result = (abs(fitnessX * fitnessY) + .02)
    print("FITNESS == {}".format(result))
    if result == 1.02:
        return (result, True)
    else:
        return (result, False)

def generatePosition(self, pos_x, pos_y):
    if pos_x < 10 or pos_y < 10:
        sys.exit("NEGATIVE NUMBER ERROR in GENERATE POSITION")
    print(pos_x)
    print(pos_y)
    tempx = pos_x
    tempy = pos_y
    x_vel = 0
    y_vel = 0
    goodNum = False
    while not goodNum:
        randNum = random.randint(1, 8)
        print("random number = {}".format(randNum))
        print("GeneratePosition")
        if randNum == 1:  # right
            pos_x += self.vel
            x_vel += self.vel

        elif randNum == 2:  # diagonal up right
            pos_x += self.vel
            pos_y -= self.vel

            x_vel += self.vel
            y_vel -= self.vel

        elif randNum == 3:  # up
            pos_y -= self.vel
            y_vel -= self.vel

        elif randNum == 4:  # diagonal up left
            pos_x -= self.vel
            pos_y -= self.vel

            x_vel -= self.vel
            y_vel -= self.vel

        elif randNum == 5:  # left
            pos_x -= self.vel
            x_vel -= self.vel

        elif randNum == 6:  # diagonal down left
            pos_x -= self.vel
            pos_y += self.vel

            x_vel -= self.vel
            y_vel += self.vel

        elif randNum == 7:  # down
            pos_y += self.vel
            y_vel += self.vel

        else:  # diagonal down right
            pos_x += self.vel
            pos_y += self.vel

            x_vel += self.vel
            y_vel += self.vel

        if (pos_x >= 290 and pos_x <= 320) and (pos_y >= 70 and pos_y <= 480):
            pos_x = tempx
            pos_y = tempy
            x_vel = 0
            y_vel = 0
            print("x = {} y = {}".format(pos_x,pos_y))
            continue

        elif (pos_x < 10 or pos_x >= 590) or (pos_y < 10 or pos_y >= 590):
            pos_x = tempx
            pos_y = tempy
            x_vel = 0
            y_vel = 0
            print("x = {} y = {}".format(pos_x,pos_y))
            continue

        else:
            goodNum = True
            return [x_vel, y_vel]


class Population:
population_array = []
population_size = 100
mutationRate = .7
maxPopulationFitness = -1000
maxFitness = -1000

def __init__(self):
    i = 0
    while i < self.population_size:
        genome = Genome()
        self.population_array.append(genome)
        i += 1

def generatePopulation(self):
    i = 0
    self.maxPopulationFitness = -1000
    while i < self.population_size:
       (endgame, maxFit) = self.population_array[i].generateGenome()

       if maxFit > self.maxFitness:
           self.maxFitness = maxFit

       if maxFit > self.maxPopulationFitness:
           self.maxPopulationFitness = maxFit

       if endgame:
           return (True, i)
       i += 1

    return (False, None)

def calcFitness(self):
    i = 0
    self.maxPopulationFitness = -1000
    while i < self.population_size:
        pos_x = self.population_array[i].x_position
        pos_y = self.population_array[i].y_position
        (result, endGame) = self.population_array[i].calcfitness([pos_x,pos_y])
        print("*****Fitness = {}******".format(result))
        self.population_array[i].fitness = result

        if result > self.maxFitness:
            self.maxFitness = result

        if result > self.maxPopulationFitness:
            self.maxPopulationFitness = result

        if endGame:
            return (endGame, i)
        i += 1    
    return (False, None)

def selection(self):
    while True:
        index = random.randint(0,self.population_size - 1)
        bestFitness = random.uniform(0,self.maxPopulationFitness)
        print("bestFitness = {}".format(bestFitness))
        parent = self.population_array[index]
        print("parentFitness = {}".format(parent.fitness))
        if (bestFitness < parent.fitness):
            return parent

def randomSelection(self):
    print("RandomSelection")
    i = 0
    new_population = []
    while i  < self.population_size:
        parent_one = self.selection()
        parent_two = self.selection()
        print("Step {}".format(i))
        child_one = self.crossover(parent_one,parent_two)
        (valid,xpos,ypos) = self.checkPath(child_one.genome_array)
        if not valid:
            continue
        new_population.append(child_one)
        child_one.x_position = xpos
        child_one.y_position = ypos

        i += 1
    self.population_array = new_population

def crossover(self,parent_one, parent_two):
    randPosition = random.randint(0,parent_one.total_size - 1)
    i = 0
    child_one = Genome()
    child_one.total_size = parent_one.total_size

    while i < parent_one.total_size:
        if i > randPosition:
            child_one.genome_array.append(parent_one.genome_array[i])
            position = parent_one.genome_array[i]

        else:
            child_one.genome_array.append(parent_two.genome_array[i])
            position = parent_two.genome_array[i]

        i += 1

    i = 0
    while i < parent_one.total_size:
        randMutate =  random.random()

        if randMutate < self.mutationRate:   
            position = child_one.genome_array[i]
            position[0] = self.mutateChild(position[0])
            position[1] = self.mutateChild(position[1])

        i += 1

    return child_one

def mutateChild(self,pos):
    if pos == 0:
        randNum = random.randint(0,1)
        if not randNum:
            return -10
        else:
            return 10
    else:
        return pos * -1

def checkPath(self,genomeArray):
    xpos = 50
    ypos = 250
    for path in genomeArray:
        xpos += path[0]
        ypos += path[1]

        if (xpos >= 290 and xpos <= 320) and (ypos >= 70 and ypos <= 480):
            return (False, None, None)

        elif (xpos < 10 or xpos >= 590) or (ypos < 10 or ypos >= 590):
            return (False, None, None)

    return (True, xpos, ypos)

def checkValidPosition(self,pos_x,pos_y):

    if (pos_x >= 290 and pos_x <= 320) and (pos_y >= 70 and pos_y <= 480):
        return False

    elif (pos_x < 10 or pos_x >= 590) or (pos_y < 10 or pos_y >= 590):
        return False

    else:
        return True

'''

0 个答案:

没有答案