mardi 30 octobre 2018

random.sample(my_set, 1) appears not to be deterministic over multiple runs with the same seed

When writing simulation code, I always print out the random seed and maintain provision to specify it in a future run. That way, if anything unusual occurs during a run, I can duplicate that exact run to figure out what is going on.

I have found that when my current code involves random.sample() from a set, multiple runs using the same seed do not follow the same trajectory.

A minimal code example appears here and also below. In this code, I use random.sample() on a list and on a set. The random.samples from the set fail in the described manner.

It is also of interest that for sampling from a set, the results vary considerably when printing is done to the screen vs. redirecting stdout from the shell to a file. When output is redirected to a file, sampling from the set gives less variation over multiple invocations than when output is sent to the screen.

Here is what I see in a file ('rm foo', then 'python rantest.py >> foo', repeatedly). Each pair in parenthesis is the single line printed by an invocation of the program. The first number printed is the sample from the set; the second is the sample from the list:

(6 0) (0 0) (0 0) (7 0) (6 0) (6 0) (7 0) (0 0) (0 0) (0 0)

And here are the the results from the screen ('python rantest.py', repeatedly):

(7 0) (7 0) (7 0) (7 0) (7 0) (7 0) (7 0) (8 0) (7 0) (7 0)

I am on MacOS 10.14, running Python Python 3.7.0 (Anaconda).

import random

random.seed(12345)

class Texs():
    ''' Create x objects and keep track of the collection within the class '''

    all_my_xs_set = set()
    all_my_xs_list = []
    nxs = 0

    @classmethod
    def add_x(cls):
        ''' Create a new x and add it to the collection '''
        x = cls()
        cls.all_my_xs_set.add(x)
        cls.all_my_xs_list.append(x)
        cls.nxs += 1

    def __init__(self):
        self.i = Texs.nxs

for i in range(10):
    Texs.add_x()

x = random.sample(Texs.all_my_xs_set, 1)[0]
y = random.sample(Texs.all_my_xs_list, 1)[0]

print(x.i, y.i)




Aucun commentaire:

Enregistrer un commentaire