I have the following function in python used to generate the children of a genetic algorithm
def cruce(padres):
mitadHerencia = len(padres[0])//2
hijo1 = np.concatenate((padres[0][:mitadHerencia], padres[1][mitadHerencia:]))
hijo2 = np.concatenate((padres[1][:mitadHerencia], padres[0][mitadHerencia:]))
hijo3 = np.concatenate((padres[0][:mitadHerencia], padres[2][mitadHerencia:]))
hijo4 = np.concatenate((padres[2][:mitadHerencia], padres[0][mitadHerencia:]))
hijo5 = np.concatenate((padres[1][:mitadHerencia], padres[2][mitadHerencia:]))
return hijo1, hijo2, hijo3, hijo4, hijo5
where padres can be defined as
padres=np.array([[1,0,0,0,1,0],[0,1,1,1,1,0],[1,0,1,0,1,1],[0,1,1,0,1,0],[0,0,0,0,1,0],[1,0,0,0,0,0],[1,1,1,0,1,0],[0,0,1,1,0,0],[0,1,1,0,1,0],[1,0,1,0,1,0]],np.int32)
This is the particular case of a genetic algorithm in which I cross the first element with the second to produce two children, the same with the first and third and so on. I would like to do this using a loop, but I haven't found a way to do this. Can someone please offer me some guidance?
You can generate a list of tuples for the indices of padres
and create a list of all hijo
which can be unpacked when the function returns:
def cruce(padres):
mitadHerencia = len(padres[0])//2
num_offspring = len(padres)//2
parts = []
i, j = 0, 0
while len(parts) < num_offspring:
i += 1
if i >= j:
i = 0
j += 1
parts.extend([(i, j), (j, i)])
parts = parts[:num_offspring]
hijo = [np.concatenate((padres[x][:mitadHerencia], padres[y][mitadHerencia:])) for x, y in parts]
return hijo
While I think there exists a cleaner solution to create the parts list, I was unable to. This method iteratively appends the combinations in order and slices it at the end to account for uneven numbers of offspring.
The loop ranges over j
and increments i
up to it. If it is equal or greater, it moves on to the next parent. This may be more clear when I show you the output:
(0, 1) | (0, 2), (1, 2) | (0, 3), (1, 3), (2, 3) | (0, 4), ...
And of course, we also add the pairs in flipped order.