遗传算法似乎并不乐观

问题描述 投票:0回答:1

我有一个简单的问题来测试我的GA,但似乎没有收敛或收敛到看似随机的值。我看过其他有类似问题的帖子,并修改了我所看到的帖子中存在的问题(如果相关),但它似乎仍未收敛。我不确定这是否只是需要处理诸如突变率等变量,还是我做错了什么。它试图优化的问题非常简单:在-1

代码:

    #####################################################################################################
################################# Genetic Algorithm Class (Attempt) #################################
#####################################################################################################

#####################################################################################################
########################################## Relevant Imports ##########################################
#####################################################################################################

import numpy as np
import matplotlib.pyplot as plt
import random
from qutip import *

class GA:


#####################################################################################################
################################## Fitness and Selection Function ###################################
############# Detects how well the pulse sequence works and selects the top x sequences #############
#####################################################################################################

    def fitness(self, population):

        n = np.linspace(0,len(population)-1,len(population)) # creates list for indices for loop

        f = np.zeros(int(len(n))) # defines empty array for fitness values

        # runs a loop to obtain the fitness values of all members in the population and add each 
        # fitness for each population to array f
        for i in n:


            f[int(i)] = population[int(i)]*np.sin(10*np.pi*population[int(i)])+1

        # finds the total fitness to obtain percentage values to allow for biased selection
        total_f = sum(f)
        percentage_f = [x + abs(min(f)) for x in f]
        percentage_f = [x/sum(percentage_f) for x in percentage_f]

        return [f, percentage_f]

#####################################################################################################
############################################ Cross Over #############################################
################## "Breeds" two ideal solutions to try and obtain a better solution #################
#####################################################################################################

    def crossover(self,a,b):

        new_a = (a+b)/2

        return new_a 

#####################################################################################################
############################################### Mutate ###############################################
########################################## Mutates a member ##########################################
#####################################################################################################    
    def mutate(self,a, mutationrate):


        check = np.random.choice(['mutate','dont mutate'], 1, p = [mutationrate,1-mutationrate])

        if check == 'mutate':
            new_a = 0
            while new_a < -1 or new_a > 2:
                new_a = a + random.uniform(-1,1)

            return new_a
        else:
            return a

        return

#####################################################################################################
######################################### Create New Member #########################################
################################ Creates a new random pulse sequence ################################
#####################################################################################################

    def create_new_member(self,min_val = -1, max_val = 2):

        member = random.uniform(min_val,max_val)

        return member


#####################################################################################################
##################################### Create Initial Population #####################################
################################ Creates an initial array of members ################################
#####################################################################################################

    def create_initial_population(self,size):

        population = [] # define empty population array

        #loops over desired size to append each member into the population array
        for i in range(0,size): 

            population.append(self.create_new_member())

        return population

#####################################################################################################
###################################### Create Next Generation #######################################
####################### Runs a loop to create a number of new pulse sequences #######################
#####################################################################################################

    def create_next_generation(self, population, percentage_f, size):

        #################################### Biased selection ####################################

        # selects a number of members (defined by input size) in the population, taking
        # into consideration the probability distribution percentage_f where each index of 
        # the probability distribution corresponds to the same indexed member in the population
        # The key word replace defines whether, once a member is chosen, it is removed or kept
        # in for the next choice
        new_population = np.random.choice(population, size, p=percentage_f, replace = True)                 

        return new_population

#####################################################################################################
############################################### Main ################################################
##################################### Main body of the program ######################################
#####################################################################################################

    def main(self, number_of_itterations, size, mutations, crossovers):

        bestf = []
        avgf = []

        # creates the initial population
        population = self.create_initial_population(size)

        # creates interger list to loop over for the number of desired itterations
        generations = np.linspace(1, number_of_itterations, number_of_itterations)

        ################################ Start of optimisation loop ################################
        for i in generations:


            p = np.linspace(1, crossovers, crossovers)
            index_p = np.linspace(0,len(population)-1,len(population))  # redefines index array to
                                                                        # to include all members again            
            for k in p:
                # Selects 2 random index values for the population to crossover and removes them
                # from the index array
                r1 = random.choice(index_p)
                np.delete(index_p,int(r1))
                r2 = random.choice(index_p)
                np.delete(index_p,int(r1))

                children = self.crossover(population[int(r1)], population[int(r2)]) # creates the children
                                                                          # members
                population = np.hstack((population,children)) # extends the child members into the population array



            ######### Mutates a random member for the number of times defined by mutations ########
            m = np.linspace(1, len(population), len(population))        # itterations for number of mutations
            index_p = np.linspace(0,len(population)-1,len(population)) # index values of population
            mutationrate = 1/len(population)
            for j in m:

                r1 = random.choice(index_p) # chooses random index in population to mutate
                population[int(r1)] = self.mutate(population[int(r1)],mutationrate) # mutates member in population at
                                                             # index r1                
                np.delete(index_p,int(r1)) # removes index r1 from index array to prevent the same member
                                # being mutated twice

            [f, percentage_f] = self.fitness(population) # evaluates the fitness of each member in 
                                                         # the population

            bestf.append(max(f))
            avgf.append(np.mean(f))

            # Overwrites the population array by creating the next generation
            population = self.create_next_generation(population, percentage_f, size)

        plt.plot(generations,bestf)
        plt.plot(generations,avgf)
        plt.title('Final Plot')
        plt.xlabel('Generation')
        plt.ylabel('Y-value (fitness)')
        plt.savefig('Final plot.png')
        plt.show()

        return

为清楚起见,绘制了两个图:

enter image description hereenter image description here

编辑:忘了加上图例,在每张图中,橙色线代表人口的平均适合度,蓝色线代表每一代最佳成员的适合度。

python genetic-algorithm convergence
1个回答
0
投票

在此示例中,最好使用精确的解决方案,即仅检查x的所有可能值并返回您的解决方案。

遗传算法是为解决大型问题而设计的。使用遗传算法的目的是减少那些无法评估所有可能解决方案的大问题中要评估的解决方案的数量。

© www.soinside.com 2019 - 2024. All rights reserved.