5

I am trying to write a genetic algorithm for homework to solve the travelling salesman problem.

One of the mutation functions that I'm trying is to use random.shuffle on the tour.

When I read the documentation for random.shuffle, I see:

shuffle(self, x, random=None, int=<type 'int'>) method of random.Random instance
x, random=random.random -> shuffle list x in place; return None.

Optional arg random is a 0-argument function returning a random
float in [0.0, 1.0); by default, the standard random.random.

Could someone please explain the function of the "random" parameter in this function? I have read this question, but it doesn't answer my question.

I would especially like to use this function if I can somehow control how random the shuffling would be (if that makes any sense)

Community
  • 1
  • 1
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
  • Can you explain more about "I would especially like to use this function if I can somehow control how random the shuffling would be"? You just want it to be more perfectly random? Why is that? – KobeJohn Jan 31 '12 at 00:52
  • What I mean there is "I want to control how different the shuffled list would be in comparison to the original". I suppose difference can be measured by the number of differing corresponding entries in the list. To be honest, I'm not 100% sure as this is something that I'm quite new to – inspectorG4dget Jan 31 '12 at 00:56
  • I see. It seems like you are looking for the "distance" between the original and the new one. You want to maximize that? Of course, if you do that, it won't be very random at all. If distance is your real target, maybe you need to change the question or ask a new one. I've updated my answer to point you to distance calculations. – KobeJohn Jan 31 '12 at 02:06

3 Answers3

4

The random argument is used for specifying (another) random number generator. it's a function expected to return uniform random numbers in the range 0<=x<1

If the same number is returned twice from the random number generator, the shuffle will be the same. For example,

def mynonrandom():
 return 0.1

q
[1, 2, 3, 4]
random.shuffle(q, mynonrandom)
q
[2, 3, 4, 1]
random.shuffle(q, mynonrandom)
q
[3, 4, 1, 2]

note that in this particular case I got a shift of -1 each time. Exactly what you get for a random input may depend on the implementation of random.shuffle.

For a genetic algorithm you want to be able to have variable sized randomness of the shuffle. That is not done with random.shuffle. You probably need to define some example changes (pairs with distance N swapping for example) and then randomize (with some parameters you'll define) how many of those operations you perform for each new set of genes.

Johan Lundberg
  • 26,184
  • 12
  • 71
  • 97
  • 1
    The Python algorithm works from the far end... choosing a random index from 0 to n-1 to swap with cell n-1, then 0 to n-2 to swap with cell n-2.... Johan's example always swaps with the first cell, hence the shift. If `mynonrandom` returned 0.75 or more, it would always swap with the current cell, and leave things unchanged. – Chris Nash Jan 31 '12 at 01:11
1

As Johan said, the random parameter simply provides the randomness for the shuffle function to use. So you can use the default or provide your own. So if you want it to be more perfectly random, you could go and find a library that does better than the python one.

Based on your reply to my comment, it sounds like you are looking for distance instead of randomness. You might like to take a set of n random shuffles and maximize the distance. To calculate distance, you can use some techniques like these which I haven't looked for implementations of but certainly exist.

KobeJohn
  • 7,390
  • 6
  • 41
  • 62
  • No, you haven't. As I posted (in response to your comment): What I mean there is "I want to control how different the shuffled list would be in comparison to the original". I suppose difference can be measured by the number of differing corresponding entries in the list. To be honest, I'm not 100% sure as this is something that I'm quite new to – inspectorG4dget Jan 31 '12 at 01:01
1

The shuffle library routine lets you provide a source of random numbers (if you don't, it'll use the built-in default). So, in theory, if you have a better source of random numbers - maybe, something connected to a Geiger counter or a "white noise" radio station, or something getting numbers from random.org - you could use that instead. Probably more useful, if you're testing, you could connect a source that returns the same sequence of numbers, which would make sure your test case is repeatable and always generates the same shuffle every time.

You could, in theory, develop a random number routine that will allow you to control exactly how much shuffling the shuffle does; but that means you need to know exactly how shuffle works and exactly what numbers you'd have to return to "guide" your results to where they want to go. In theory... it's not too difficult, the algorithm used is very well-documented (Fisher-Yates), and during the call it generates n-1 random numbers, the first to select an element from index 0 to n-1, to swap with the last element, the second to select an element from 0 to index n-2, to swap with the last-but-one element, and so on. So yes, you could use this to control the shuffle, like @JohanLundberg example which forces the shuffle to shift - but it would be very hard to use that to control the shuffle (since each iteration, all the original data is jumping around).

Short answer, if you need specific constraints on a shuffle, such as "only swap neighboring elements" - you'll be better off implementing your own, perhaps using the shuffle source code as a guide.

Chris Nash
  • 2,941
  • 19
  • 22