To give a little background, I am coding a genetic algorithm to solve the Traveling Salesman Problem (TSP). In my population, I have an ordered list of paths from shortest to longest (fittest to least fit), and their respective distances, like this:
population = [
[[a, b, c, d], [10.12]],
[[b, c, a, d], [11.33]],
[[d, a, c, b], [11.5]],
[[b, a, d, c], [12.07]]
...]
After the population is ordered by their fitness, I need to kill half of them randomly, but in such a fashion that the fitter the member, the better their chance of surviving.
I've tried using random.choices()
and passing a list with chances of probability (bias) into the weights
parameter, and my desired size of half the original population as k
like this:
# returns something like [0.99, 0.75, 0.65, 0.22...]
bias_weights = [x / len(population) for x in range(len(population))]
random.choices(population, weights=bias_weights, k=len(population) / 2)
The problem with the code above is that it produces duplicates in my list, and it's very messy to get rid of them and keep the population size at 50%.
I've also tried using the np.random.choices()
from the numpy
library, but it requires the list that I am passing to be 1D, and the list of weights and biases to add up to 1.
Is there any other way to do this?
I would still use np.random.choice()
. Solve the first problem by asking np.random.choice()
to choose the index of the path rather than the path itself. Solve the second problem by scaling the weights so they sum to 1.
import numpy as np
a, b, c, d = 1, 2, 3, 4
population = [
[[a, b, c, d], [10.12]],
[[b, c, a, d], [11.33]],
[[d, a, c, b], [11.5]],
[[b, a, d, c], [12.07]]
]
# Build probability array
bias_weights = [x / len(population) for x in range(len(population))]
prob = np.array(bias_weights) / np.sum(bias_weights)
# Get random integers between 0 and len(prob)-1, drawn according to prob
sample_size = 2
choice_indices = np.random.choice(len(prob), size=sample_size, replace=False, p=prob)
# Get corresponding paths
paths = [population[i][0] for i in choice_indices]