DEV Community

Cover image for Python's random.choices is Awesome
Ryan Palo
Ryan Palo

Posted on • Originally published at assertnotmagic.com

Python's random.choices is Awesome

I'm reading through Classic Computer Science Problems in Python (affiliate link) by David Kopec, and I'm working on his Genetic Algorithm examples. He got to the point where he describes the roulette-style selection process.

Some background: this isn't a post about Genetic Algorithms, but imagine this. Assume you've got a group of candidates in a breeding process. The roulette-style selection process means that you create a giant roulette wheel with all of the candidates on it, and the size of each candidate's wedge depends on their "fitness" score: how much of the desired result they have in them. Then, you spin the wheel to randomly select based on these weights.

OK, so back to me.

I read through that description and I was mentally gearing up to implement this. We need to get each candidate's fitness, figure out how they stack up, normalize to a scale from 0 to 1, and then figure out how to randomize that selection. Not impossible to implement, but it would take several lines or more of code to do it. Cool beans.

Then I get to the author's solution.

And I just sat there. Staring at it.

You know that feeling when you see something and it just makes you mad and because of how hard you worked on yours and then somebody comes in and does it the easy way? But at the same time, you're also very impressed because it's awesome?

Dang... But... Alright, that's fair.

Something like that.

Here. Just look at it. I tweaked it a little to show more context here:

from random import choices

def pick_parent_candidates(population):
    fitnesses = [candidate.fitness() for candidate in population]
    return tuple(choices(population, weights=fitnesses, k=2))
Enter fullscreen mode Exit fullscreen mode

It just... It just does the thing.

Anyways, random.choices is pretty cool. In fact, the whole random module has a lot of underrated functions that can save you oodles of time and code.

Top comments (2)

Collapse
 
minterciso profile image
Mateus Interciso

Found this post searching specifically for GA selection techniques, just wanted to say that the choices() is great, but it's really not a roulette selection, it's just selecting 2 candidates with probability being equal to the fitness. In order to make a roulette wheel selection, you have to be a little more complex than that, mainly:

  1. Create the probabilities (or weights) based on the fitness values
  2. Select a random number
  3. Keep accumulating the probability (or weights), until you reach the number
  4. That's your selected candidate

Very simple code:

import numpy as np

fitness = np.random.rand(50)
total_fitness = sum(fitness)
weights = fitness/total_fitness
r = np.random.rand()
acc = 0
idx = -1
while acc < r: 
    idx += 1 
    acc += weights[idx] 
print(idx)
>>> 21

This is a very simple algorithm, and there are other implementations (way faster and better), but it shows the point ;).

Collapse
 
dowenb profile image
Ben Dowen

100%! I have found random.choice is very useful for generating test data.