Подтвердить что ты не робот

Как создать повторяемую последовательность случайных чисел?

Мне нужна функция, которая может генерировать псевдослучайную последовательность значений, но для этой последовательности можно повторять каждый прогон. Данные, которые я хочу, должны быть достаточно хорошо распределены случайным образом в заданном диапазоне, это не должно быть идеальным.

Я хочу написать код, на котором будут выполняться тесты производительности на основе случайных данных. Я бы хотел, чтобы эти данные были одинаковыми для каждого тестового прогона на каждой машине, но я не хочу, чтобы отправлять данные с пробными данными по причинам хранения (это может быть много мегабайт).

Библиотека для модуля random не говорит о том, что одно и то же семя всегда будет давать одну и ту же последовательность на любой машине.

РЕДАКТИРОВАТЬ: Если вы собираетесь предложить мне засеять данные (как я сказал выше), просьба предоставить документацию, в которой говорится, что подход действителен, и будет работать на нескольких машинах/реализациях.

EDIT: CPython 2.7.1 и PyPy 1.7 для Mac OS X и CPython 2.7.1 и CPython 2.52 =.2 Ubuntu, похоже, дает те же результаты. Тем не менее, никаких документов, которые предусматривают это в черно-белом режиме.

Любые идеи?

4b9b3361

Ответ 1

В документации явно не указано, что предоставление семени всегда гарантирует одинаковые результаты, но это гарантируется с реализацией Python случайным образом на основе используемого алгоритма.

Согласно документации, Python использует Mersenne Twister в качестве основного генератора. После того как этот алгоритм посеян, он не получает никакого внешнего выхода, который бы менял последующие вызовы, поэтому дайте ему одно и то же семя, и вы получите те же результаты.

Конечно, вы также можете наблюдать это, устанавливая семя и генерируя большие списки случайных чисел и проверяя, что они одинаковы, но я понимаю, что не хочу доверять этому.

Я не проверял другие реализации Python, кроме CPython, но я очень сомневаюсь, что они будут реализовывать случайный модуль, используя совершенно другой алгоритм.

Ответ 2

Для этой цели я использовал повторяющийся хеш MD5, так как намерение хеширования является кросс-платформенным преобразованием один-к-одному, поэтому оно всегда будет одинаковым на разных платформах.

import md5

def repeatable_random(seed):
    hash = seed
    while True:
        hash = md5.md5(hash).digest()
        for c in hash:
            yield ord(c)

def test():
    for i, v in zip(range(100), repeatable_random("SEED_GOES_HERE")):
        print v

Вывод:

184 207 76 134 103 171 90 41 12 142 167 107 84 89 149 131 142 43 241 211 224 157 47 59 34 233 41 219 73 37 251 194 15 253 75 145 96 80 39 179 249 202 159 83 209 225 250 7 69 218 6 118 30 4 223 205 91 10 122 203 150 202 99 38 192 105 76 100 117 19 25 131 17 60 251 77 246 242 80 163 13 138 36 213 200 135 216 173 92 32 9 122 53 250 80 128 6 139 49 94

По сути, код займет ваше семя (любая допустимая строка) и многократно хеширует его, таким образом генерируя целые числа от 0 до 255.

Ответ 3

Существуют различия в платформе, поэтому, если вы переместите свой код между разными платформами, я бы пошел на метод, описанный DrRobotNinja.

Пожалуйста, взгляните на следующий пример. Python на моем настольном компьютере (64-разрядный Ubuntu с Core i7, Python 2.7.3) дает мне следующее:

> import random
> r = random.Random()
> r.seed("test")
> r.randint(1,100)
18

Но если я запустил тот же код на моей малиновой Pi (Raspbian на ARM11), я получаю другой результат (для той же версии Python)

> import random
> r = random.Random()
> r.seed("test")
> r.randint(1,100)
34

Ответ 4

Укажите семя для генератора случайных чисел. Если вы предоставите одно и то же семя, ваши случайные числа также должны быть одинаковыми.

http://docs.python.org/library/random.html#random.seed

Ответ 5

Также ответ, почему пример из этого ответа производит различный вывод на разных машинах:

Это потому, что при посеве случайного генератора семя должно быть целым числом. Если вы засеете генератор некоторым нецелым, сначала нужно его хэшировать. Функции хэш-функции не являются независимыми от платформы (очевидно, по крайней мере, не все из них, исправьте меня, если вы знаете больше).

Итак, чтобы собрать все это вместе: Python использует генератор псевдослучайных чисел. Поэтому при запуске из одного и того же состояния произведенная последовательность случайных чисел всегда будет одинаковой, независимо от платформы. Это просто детекционистский алгоритм без дальнейшего ввода из внешнего мира.

Это означает: до тех пор, пока вы инициализируете свой случайный генератор с тем же состоянием, он будет производить такую ​​же последовательность чисел. Получение одного и того же состояния может быть выполнено с использованием одного и того же целого семени или путем сохранения и повторного использования старого состояния (random.getstate() и random.setstate()).

Ответ 6

Использование random.seed(...) Вы можете сгенерировать повторяемую последовательность. Демонстрация:

import random

random.seed(321)
list1 = [random.randint(1,10) for x in range(5)]

random.seed(321)
list2 = [random.randint(1,10) for x in range(5)]

assert(list1==list2)

Это работает потому, что random.seed(...) не является по-настоящему случайным: он псевдослучайным, в результате чего последовательные числа создаются путем перестановки какой-либо конечной машины с заданным начальным условием "семя".

Ответ 7

Если качество случайных чисел не так критично, как повторяемость на разных платформах, вы можете использовать один из традиционных линейных конгруэнтных генераторов:

class lcg(object):
    def __init__( self, seed=1 ):
        self.state = seed

    def random(self):
        self.state = (self.state * 1103515245 + 12345) & 0x7FFFFFFF
        return self.state

Поскольку это закодировано в вашей программе с использованием целочисленной арифметики, оно должно быть детерминистически повторяемо на любой разумной платформе.

Ответ 8

Я просто попробовал следующее:

import random
random.seed(1)
random.random()
random.random()
random.random()

random.seed(1)
random.random()
random.random()
random.random()

Я ввел каждую строку в CLI на разных скоростях несколько раз. Производя те же значения каждый раз.