Существуют ли алгоритмы для генерации психологически случайных чисел? - программирование
Подтвердить что ты не робот

Существуют ли алгоритмы для генерации психологически случайных чисел?

Истинные случайные числа часто не кажутся случайными для среднего человека, так как случайно генерируемые последовательности будут интерпретироваться как структура. Существуют ли какие-либо алгоритмы, которые генерируют набор чисел, которые психологически "кажутся" случайными, даже если они не являются?

4b9b3361

Ответ 1

Вот алгоритм:

  • Используйте любой Генератор псевдослучайных чисел, чтобы создать последовательность чисел, которые не являются случайными (поскольку они предварительно определены семенем и алгоритм).

  • Используйте кучу статистических тестов из аккумулятор Diehard (источник), чтобы дисквалифицировать подпоследовательности, которые субъективно и исторически считаются предвзятыми.

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

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

Абстрактный

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

Griffiths, T. L. и Tenenbaum, J. B. (2003). Вероятность, алгоритмическая   сложности и субъективной случайности. В Р. Альтермане и Д. Кирше   (Ред.), Материалы 25-й Ежегодной Конференции Когнитивных   Научного общества (стр. 480-485). Махва, Нью-Джерси: Эрлбаум. [PDF]

Ответ 2

Невозможно

Нет такой вещи, как серия, которая - психологически - выглядит случайной для всех, но это не так.

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

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

Подумайте о кости, где вы всегда перетасовываете 6 чисел (2, 6, 1, 4, 3, 5) и выбираете их в этом порядке, прежде чем снова перетасовать (6, 3, 2, 4, 1, 5) и выбор следующего 6.

Этот подход никогда не приведет к 3-мя идентичным числам в серии, но в некоторых играх это может быть очень полезно, например, 3х6 подряд, и, конечно, со временем будет очевидно, что это никогда не произойдет, просто вы играли в эту игру, и вы знаете, что обычно это происходит 2-3 раза в час.

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

Вывод:

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

Нет общего ожидания, независимо от знания аудитории. Даже, что цифры с 1 по 6 должны - в конечном счете - встречаться примерно одинаково часто, должны быть известны, что неизвестно интуицией.

Из короткой серии никто не может определить, является ли она неисправной или нет. Из более длинных серий будет обнаружен сломанный RNG.

TL;DR

Вся идея намеренно нарушенного ГСЧ, чтобы приспособить его к плохо образованным предрассудкам, ошибочна. Если вам нужно что-то в качестве музыкального шаффлера без слишком раннего повторения, найдите лучшее имя для этой вещи.

Ответ 3

Первое, что нужно учитывать, - это то, как вы используете числа. Перелистывание большого количества монет даст довольно хороший раскол 50/50, где переворачивание двух или трех монет способно дать вам раздражающие неявные случайные 3 головы или хвосты слишком долго. Роллинг кубиков кубиков, ищущих их, даст очень неравномерные результаты, иногда без них, и когда-то половина кубиков будет одной. Здесь будет помогать больше кубиков. Как правило, чем больше чисел вы создадите, тем счастливее будут люди с ними.

Если вы только генерируете несколько чисел, я бы начал с действительно случайных, посмотрим, что вас раздражает, и исправьте. Одна простая вещь - уменьшить вероятность появления числа, исходя из того, как часто это происходит раньше. Или, что еще проще, не возвращайте один и тот же номер дважды. Но часто бывают тонкости. Если вы возвращаете цифры с 1 по 10, но 1-4 отсчета в одну сторону и 5-10, то последовательность 123451234512345 будет очень раздражающей (80% низкая, 20% высокая). Если диапазоны 1-2 и 3-10, это не будет (вы получите ожидаемый 40% низкий, 60% высокий). Хуже того, если у вас есть конкурирующие броски, это относительные результаты, которые имеют значение. Числа из каждой кубики могут выглядеть сами по себе, чтобы быть случайными, но если в 9 раз из 10 один кубик катится выше другого, кости будут казаться загруженными.

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

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

Собственно, я могу представить два общих решения. Один из них: просто не используйте случайные числа. Другая - генерировать огромное количество из них и не позволяет никому смотреть на детали последовательности. Если у вас есть игра с 5000 бойцов на каждой стороне, стреляя друг в друга с вероятностью 10% удара, общий эффект (486 вниз с одной стороны и 512 вниз на другой) будет очень психологически случайным. Просто не позволяйте никому смотреть на результаты, скажем, на 10 отдельных снимков. ( "У меня было 30 выстрелов и ни одного удара!" "У него было 3 удара в 5 выстрелов!" )

Также: Я написал выше, а затем понял, что здесь может быть этическая проблема. Если вы создаете случайную карту или делаете много других вещей, фальсификация результатов генерации случайных чисел может быть очень хорошей идеей. Однако игрок в игре может иметь право на реальное случайное число. Если у вас есть игра в покер, и реальная случайная сделка дает игроку флеш-рояль, ваша программа не имеет никакого бизнеса, решающего, что это слишком экстремально и требует много времени. Игрок из военной игры, решивший совершить атаку с предполагаемым 50-50 шансом на успех, не должен быть ослеплен тем, что, поскольку ранее он выиграл 3 50-50 конкурсов подряд, его реальные шансы теперь составляют только 20-80, Аспект этики здесь, вероятно, мог бы заполнить книгу, на которую у меня нет времени писать, но очень ей это известно.

Ответ 4

В вашем вопросе есть два требования.

  • Психологически кажется случайным
  • Не действительно случайный

Вам нужно определить оба этих требования намного лучше. Я предлагаю определить такие требования, как это:

  • Пользователь всегда сможет находить последовательности в наборе случайных чисел, если набор достаточно длинный. Можно даже математически доказать, что вы можете найти любую заданную подпоследовательность чисел в случайном потоке данных. Поэтому пользователь почти наверняка найдет случайную подпоследовательность.
  • Однако вы не хотите, чтобы поток был действительно случайным. Это означает, что вы хотите, чтобы компьютер мог предсказать следующий номер.

Я предлагаю следующий алгоритм:

NEXT = RandomStartingNumber
X = empty list
loop {
   NEXT = HASH(NEXT)
   add NEXT to X
}

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

Ответ 5

Код RNG ниже (написанный в С#) генерирует некоторые очень случайные числа:

public class Randomizer
{
    /// <summary>
    /// An array of unsigned integers containing 100 pre-rolled randomly generated numbers.
    /// </summary>
    private uint[] randBuf = new uint[100];

    /// <summary>
    /// The index of the last read number out of the <see cref="Atlana.Random.Randomizer.randBuf">randBuf</see> array.
    /// </summary>
    private uint index = 0;

    /// <summary>
    /// Original value of the seed used to initialize the number array.
    /// </summary>
    private uint origSeed;

    /// <summary>
    /// Initializes a new instance of the Randomizer class. Uses <paramref name="seed">seed</paramref> to initialize the number array.
    /// </summary>
    /// <param name="seed">Integer value used to seed the number array.</param>
    public Randomizer(int seed)
    {
        this.origSeed = (uint)seed;
        this.Initialize((uint)seed);
    }

    /// <summary>
    /// Invokes the randomizer to refresh the list of random values.
    /// </summary>
    public void ReRoll()
    {
        this.Roll();
    }

    /// <summary>
    /// Generates a random unsigned integer number value between the specified range of <paramref name="min">min</paramref> and <paramref name="max">max</paramref>.
    /// </summary>
    /// <param name="min">An unsigned integer representing the minimum value of the return value.</param>
    /// <param name="max">An unsigned integer representing the maximum value of the return value.</param>
    /// <returns>An unsigned integer containing a number between <paramref name="min">min</paramref> and <paramref name="max">max</paramref>.</returns>
    public uint Range(uint min, uint max)
    {
        uint y = this.Random();
        if (y < min)
        {
            y = y * min;
        }

        if (y > max)
        {
            y = y % (max + 1);
        }

        return y;
    }

    /// <summary>
    /// Generates a random integer number value between the specified range of <paramref name="min">min</paramref> and <paramref name="max">max</paramref>.
    /// </summary>
    /// <param name="min">An integer representing the minimum value of the return value.</param>
    /// <param name="max">An integer representing the maximum value of the return value.</param>
    /// <returns>An integer containing a number between <paramref name="min">min</paramref> and <paramref name="max">max</paramref>.</returns>
    public int Range(int min, int max)
    {
        return Convert.ToInt32(this.Range(Convert.ToUInt32(min), Convert.ToUInt32(max)));
    }

    /// <summary>
    /// Generates a random number between 0 and 100.
    /// </summary>
    /// <returns>A randomly generated integer value between 0 and 100.</returns>
    public int Percent()
    {
        return this.Range(0, 100);
    }

    /// <summary>
    /// Retrieves a value from the random number array.
    /// </summary>
    /// <returns>A randomly generated unsigned integer</returns>
    private uint Random()
    {
        if (this.index == 0)
        {
            this.Roll();
        }

        uint y = this.randBuf[this.index];
        y = y ^ (y >> 11);
        y = y ^ ((y << 7) + 3794);
        y = y ^ ((y << 15) + 815);
        y = y ^ (y >> 18);
        this.index = (this.index + 1) % 100;
        return y;
    }

    /// <summary>
    /// Initializes the number array from a seed provided by <paramref name="seed">seed</paramref>.
    /// </summary>
    /// <param name="seed">Unsigned integer value used to seed the number array.</param>
    private void Initialize(uint seed)
    {
        this.randBuf[0] = seed;
        for (uint i = 1; i < 100; i++)
        {
            this.randBuf[i] = (uint)(this.randBuf[i - 1] >> 1) + i;
        }
    }

    /// <summary>
    /// Checks to prevent <see cref="System.ArithmeticException">ArithmeticException</see>.
    /// </summary>
    private void OverflowCheck()
    {
        foreach (uint u in this.randBuf)
        {
            if (u > (uint.MaxValue / 3794))
            {
                this.Initialize(this.origSeed + this.index);
                break;
            }
        }
    }

    /// <summary>
    /// Refreshes the list of values in the random number array.
    /// </summary>
    private void Roll()
    {
        this.OverflowCheck();
        for (uint i = 0; i < 99; i++)
        {
            uint y = this.randBuf[i + 1] * 3794U;
            this.randBuf[i] = (((y >> 10) + this.randBuf[i]) ^ this.randBuf[(i + 399) % 100]) + i;
            if ((this.randBuf[i] % 2) == 1)
            {
                this.randBuf[i] = (this.randBuf[i + 1] << 21) ^ (this.randBuf[i + 1] * (this.randBuf[i + 1] & 30));
            }
        }
    }
}

Вот пример серии чисел между 0-50, используя вышеприведенный класс:

7 2 6 4 17 1 48 18 46 14 44 32 37 12 48 12 14 47 15 10 5 12 15 9 9 15 27 47 5 5
2 16 20 48 50 22 31 39 40 20 41 27 35 50 46 21 8 34 24 6