John Won
John Won

Reputation: 65

Python string index out of range error and better ways to implement mating and reproduction in genetic programming

I recently saw a video on Youtube about genetic algorithms and thought it was quite interesting and decided to give it a go. Me, being new to programming and not having experience with any language other than Python, thought C#, which seemed to be the most widely used language for genetic algorithms, was t0o hard and decided to give it a try in Python. And I am currently stuck because of an error, and I can't quite figure out what is wrong with the code.

This is the code:

import random

#Wanted String
STRING_NAME = "this is a genetic algorithm"
LENG = len(STRING_NAME)
#Used Characters
VALID_CHARACTERS = "abcdefghijklmopqrstuvwxyz "
#Generation Size
POPULATION_SIZE = 200
#List of String Objects
POPULATION = []
closest = 100
choiceList = []


#Generating random strings
def randomStringGeneration(size=len(STRING_NAME)):
    return ''.join(random.choice(VALID_CHARACTERS) for _ in range(size))

#string object
class ranString:

    def __init__(self,manualstr=""):
        if manualstr == "":
            self.string = randomStringGeneration()
        else:
            self.string = manualstr
        self.fitness = fitnessCheck(self)

#fitness checking
def fitnessCheck(String):
        result = 0;
        for x in range(0,LENG-1):
            if (String.string[x] == STRING_NAME[x]):
                result += 1
        return result

#order population list by fitness decrementaly
def sortByFitness(Obj):
    Obj.sort(key=lambda x: x.fitness, reverse=True)

#mating two strings
def mate(x,y):
    tempxstr = x.string
    tempystr = y.string
    child1 = tempxstr[0:10]+tempystr[14:20]+tempxstr[21:26]
    child2 = tempystr[0:10]+tempxstr[14:20]+tempystr[21:26]
    ranchild1 = ranString(manualstr = child1)
    ranchild2 = ranString(manualstr = child2)
    POPULATION.append(child1,child2)

#main function
def generatePopulation(num):
    generation = 1
    for x in range(num):
        if (generation == 1):
            for x in range(POPULATION_SIZE):
                f = ranString()
                POPULATION.append(f)
            sortByFitness(POPULATION)
            for x in POPULATION:
                print(x.string + "    " + str(x.fitness))
            generation +=1
        else:
            sortByFitness(POPULATION)
            del POPULATION[100:]
            for x in POPULATION:
                for j in range(x.fitness):
                    choiceList.append(x)
            for j in range(100):
                x = random.choice(choiceList)
                y = random.choice(choiceList)
                mate(x,y)

            print("\n\n\n\nGeneration"+generation)
            for x in POPULATION:
                print(x.string + "    " + str(x.fitness))
            generation += 1

generatePopulation(10)

This is the log(do you call these log files?) file with the error:

egf ukcob uf oyhtuikmdritiz    4
ouaelyf ef wufsjh aqkcyacef    3
rbuwptsdjmwskfzyccsfgzlwdyo    3
fqyg zhhhswesdfetqjy ohrpyj    3
qfirzajzhafdv dicmueavdrguv    3
pxqsxtehe bckbvadapezgrqdkb    3
zvosvvsspgbpmxhadwxkfzkqjhi    3
tfsofiurlpyakhhwqqexoafhtxi    3
qkmslihwskukcecldykkp caiqo    3
fhfh ctluzbr vty skgozgqclg    3
dglsfwimwqfxdhdzx lkcvrraev    3
jbuwaoxua uteissqfpxodciaoa    3
if qpvpcsixe kagmxyludcicwl    3
vspwdxwqkewcaethcs g dxcxao    3
 d jpylld gzuojvccuh gzjxbs    3
pvzsjkxtzrjgjegimalvcaxjbjw    3
zolqfli sdahohjiryerabkvmme    2
ufslbdexaa wrfuscfbkfdulzfr    2
             *
             *  (middle part omitted because it would be too long)
             *
 jcjigwzhyxwwyikfoiyrtolclg    0
srjqfxjbuppfd drlrkjkuqegvb    0
zbsbkedazmxyghrmhzdzjytcqza    0
xqxmtxrkhctqayrmkvefkpy zad    0
waxpeefkvqjjwvylre jfvedyfa    0
udyetsjd lmhuzamrwt rip dqv    0

Traceback (most recent call last):
  File "/Users/Johnwon/Desktop/Genetic String.py", line 80, in <module>
    generatePopulation(10)
  File "/Users/Johnwon/Desktop/Genetic String.py", line 73, in generatePopulation
    mate(x,y)
  File "/Users/Johnwon/Desktop/Genetic String.py", line 48, in mate
    ranchild1 = ranString(manualstr = child1)
  File "/Users/Johnwon/Desktop/Genetic String.py", line 28, in __init__
    self.fitness = fitnessCheck(self)
  File "/Users/Johnwon/Desktop/Genetic String.py", line 34, in fitnessCheck
    if (String.string[x] == STRING_NAME[x]):
IndexError: string index out of range

I've searched the Internet for the out of index error and it seems that I incremented too much or searched for an index that is not existent but I can't find the cause for the error. What is wrong with my code?

Also, currently my mate() function works by adding the strings to a separate list multiplied by their fitness then randomly selecting 2 of them and swapping a third of their 'genes' and popping out 2 babies. This is the only way I could think of to give more fit objects a higher chance to mate but this seems horribly unoptimized as the generations go and fitness levels grow higher. What could be a good way to do this and implement mutation?

I'm a beginner in Python and I'm open to any opinions on how to improve my code. Thanks for reading!

Upvotes: 0

Views: 76

Answers (1)

Kevin
Kevin

Reputation: 76244

child1 = tempxstr[0:10]+tempystr[14:20]+tempxstr[21:26]
child2 = tempystr[0:10]+tempxstr[14:20]+tempystr[21:26]

This doesn't look right to me. These strings will each have a length of 21. But inside fitnessCheck, you're comparing them against STRING_NAME, which has a length of 27. So once x reaches 21 inside fitnessCheck, you'll get an IndexError.

You should change how you create child1 and child2 so that they have the same length as STRING_NAME.

Upvotes: 1

Related Questions