Search code examples
pythongenetic-algorithm

My code with in function does not perform the task but does the same while out of it?


Here's my code where I am flipping a bit, crossing over two lists and selecting random elements of lists:

def selRandom(individuals, k):
    return [random.choice(individuals) for i in range(k)]

def cxOnePoint(ind1, ind2):

    size = min(len(ind1), len(ind2))
    cxpoint = random.randint(1, size - 1)
    ind1[cxpoint:], ind2[cxpoint:] = ind2[cxpoint:], ind1[cxpoint:]

    return ind1, ind2

def mutFlipBit(individual, indpb):

    for i in range(len(individual)):
        if random.random() < indpb:
            individual[i] = type(individual[i])(not individual[i])

    return individual,




def operators(selection, crossover, mutation, parent, k, indvpb):

    select = ['randomSelection']
    cx = ['OnePoint']
    mutate = ['flipBitMutate']


    if selection not in select:
        return "invalid"

    else:

        if selection == 'randomSelection':
            (parent) = selRandom(parent, k)

    if crossover not in cx:
        return "invalid"

    else:
        if crossover == 'OnePoint':
            ind = cxOnePoint(parent[0], parent[1])

    if mutation not in mutate:
        return "not valid"
    else:
        if mutation == 'flipBitMutate':
            mutatedIndvidual = mutFlipBit(ind[0], indvpb)


    return parent, ind, mutatedIndvidual

I run this to execute the code:

indv = ([1,0,1,0,1,0,1,1],[0,1,0,1,0,0,0,1],[0,0,1,1,1,1,0,0],[0,1,1,1,0,0,0,1],[1,0,0,0,1,1,1,1])
selection = 'randomSelection'
crossover = 'OnePoint'
mutation = 'flipBitMutate'
selected_parent, ind, mutatedIndvidual = operators(selection = selection , crossover = crossover, mutation = mutation, parent = indv, k = 3, indvpb = 0.1 )
print("Parents:\n",indv)
print("Selected parent to reproduce:\n",selected_parent)
print("Crossover offsprings:\n",ind)
print("Mutated offsprings",mutatedIndvidual)

And get the result:

Parents:
 ([1, 0, 1, 0, 1, 0, 1, 1], [1, 1, 1, 1, 0, 0, 1, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 1, 0, 1, 0, 0, 0, 1], [1, 0, 0, 0, 1, 1, 1, 1])
Selected parent to reproduce:
 [[1, 1, 1, 1, 0, 0, 1, 0], [0, 1, 0, 1, 0, 0, 0, 1], [1, 1, 1, 1, 0, 0, 1, 0]]
Crossover offsprings:
 ([1, 1, 1, 1, 0, 0, 1, 0], [0, 1, 0, 1, 0, 0, 0, 1])
Mutated offsprings ([1, 1, 1, 1, 0, 0, 1, 0],)

So the code is executing but is not functioning. It randomely selects from the tuple and then it does not crossovers (mixes the bits from two lists) or flips the bits. If I test run the code separately (out of the operator method) it works:

a = [1,1,1,1,1,1,1,1]
b = [0,0,0,0,0,0,0,0] 
c = [1,0,0,0,1,1,0,1]
d= (a,b,c)
print("selecting randomely:\n",selRandom(d,1))
print("TESTING CROSSOVER\n", cxOnePoint(a,b))
print("Mutate:\n",mutFlipBit(a,0.4))

and got the proper result:

selecting randomely:
 [[0, 0, 0, 0, 0, 0, 0, 0]]
TESTING CROSSOVER
 ([1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1])
Mutate:
 ([0, 1, 1, 1, 1, 1, 1, 1],) 

What is the logical mistake that I am making here?

Thank you!


Solution

  • To answer my own question:

    1. I have assigned original lists in the mutFlipBit() and cxOnePoint and I changed my 'mutFlipBit()' to:

       def mutation(individual, indp):
           return [not ind if random.random() < indp else ind for ind in individual]
      

    This worked for me