BlessRNG ё тафтиши RNG барои адолат

BlessRNG ё тафтиши RNG барои адолат

Ҳангоми таҳияи бозӣ, шумо аксар вақт бояд чизеро бо тасодуфӣ пайваст кунед: Unity барои ин Random-и худро дорад ва дар баробари он System.Random мавҷуд аст. Боре дар яке аз лоиҳаҳо ман таассуроте пайдо кардам, ки ҳарду метавонанд ба таври гуногун кор кунанд (гарчанде ки онҳо бояд тақсимоти баробар дошта бошанд).

Сипас онҳо ба тафсилот нагуфтанд - кофӣ буд, ки гузариш ба System.Random ҳамаи мушкилотро ислоҳ кард. Ҳоло мо тасмим гирифтем, ки онро муфассалтар дида бароем ва каме тадқиқот гузаронем: то чӣ андоза RNG-ҳои “ғаразнок” ё пешбинишавандаанд ва кадомашро интихоб кунем. Гузашта аз ин, ман на як маротиба дар бораи "ростқавлӣ"-и онҳо фикрҳои зиддунақизро шунидаам - биёед бифаҳмем, ки натиҷаҳои воқеӣ бо натиҷаҳои эълоншуда чӣ гуна муқоиса мекунанд.

Барномаи мухтасари таълимӣ ё RNG воқеан RNG аст

Агар шумо аллакай бо генераторҳои рақамҳои тасодуфӣ шинос бошед, пас шумо метавонед фавран ба бахши "Санҷиш" гузаред.

Рақамҳои тасодуфӣ (RN) як пайдарпаии ададҳо мебошанд, ки бо истифода аз баъзе равандҳои тасодуфӣ (бетартибӣ), манбаи энтропия тавлид мешаванд. Яъне ин пайдарпаме аст, ки унсурҳои он бо ягон қонуни риёзӣ бо ҳам алоқаманд нестанд - онҳо робитаи сабабу натиҷа надоранд.

Он чизе ки рақами тасодуфиро эҷод мекунад, генератори рақамҳои тасодуфӣ (RNG) номида мешавад. Чунин ба назар мерасад, ки ҳама чиз ибтидоӣ аст, аммо агар мо аз назария ба амалия гузарем, пас дар асл татбиқи алгоритми нармафзор барои тавлиди чунин пайдарпаӣ он қадар осон нест.

Сабаб дар набудани ҳамон бесарусомонӣ дар электроникаи муосири маишӣ мебошад. Бе он, рақамҳои тасодуфӣ тасодуфиро қатъ мекунанд ва генератори онҳо ба вазифаи оддии аргументҳои баръало муайяншуда табдил меёбад. Барои як қатор ихтисосҳои соҳаи ТИ ин мушкили ҷиддӣ аст (масалан, криптография), аммо барои дигарон роҳи ҳалли комилан қобили қабул мавҷуд аст.

Бояд алгоритме нависад, ки ҳарчанд рақамҳои воқеан тасодуфӣ не, балки ба қадри имкон ба онҳо наздик шавад - рақамҳои псевдо-тасодуфӣ (PRN) баргардад. Алгоритм дар ин ҳолат генератори рақамҳои псевдорандом (PRNG) номида мешавад.

Якчанд вариантҳо барои сохтани PRNG вуҷуд доранд, аммо инҳо барои ҳама мувофиқанд:

  1. Зарурати ибтидоии пешакӣ.

    PRNG манбаи энтропия надорад, бинобар ин пеш аз истифода ба он бояд ҳолати аввала дода шавад. Он ҳамчун адад (ё вектор) муайян карда мешавад ва онро тухмӣ (тухми тасодуфӣ) меноманд. Аксар вақт, ҳисобкунаки соати протсессор ё муодили ададии вақти система ҳамчун тухм истифода мешавад.

  2. Таҷдиди пайдарпай.

    PRNG комилан детерминистист, аз ин рӯ тухмие, ки ҳангоми оғозёбӣ нишон дода шудааст, тамоми пайдарпаии рақамҳои ояндаро ба таври беназир муайян мекунад. Ин маънои онро дорад, ки PRNG-и алоҳидаи бо як тухм оғозшуда (дар вақтҳои гуногун, дар барномаҳои гуногун, дар дастгоҳҳои гуногун) як пайдарпаиро тавлид мекунад.

Шумо инчунин бояд донед, ки тақсимоти эҳтимолият, ки PRNG-ро тавсиф мекунад - кадом рақамҳоро тавлид мекунад ва бо кадом эҳтимолият. Аксар вақт ин тақсимоти муқаррарӣ ё тақсимоти яксон аст.
BlessRNG ё тафтиши RNG барои адолат
Тақсимоти муқаррарӣ (аз чап) ва тақсимоти яксон (аз рост)

Фарз мекунем, ки мо як одилона бо 24 тараф дорем. Агар шумо онро партоед, эҳтимолияти ба даст овардани як баробар ба 1/24 хоҳад буд (ба монанди эҳтимолияти гирифтани ягон рақами дигар). Агар шумо бисёр партовҳо анҷом диҳед ва натиҷаҳоро сабт кунед, шумо хоҳед дид, ки ҳама кунҷҳо тақрибан бо ҳамон басомад меафтанд. Аслан, ин бимирад метавонад RNG бо тақсимоти якхела ҳисобида шавад.

Чӣ мешавад, агар шумо якбора 10 ададро партоед ва холҳои умумиро ҳисоб кунед? Оё барои он якрангӣ нигоҳ дошта мешавад? Не. Аксар вақт, маблағ ба 125 нуқта наздик мешавад, яъне ба арзиши миёна. Ва дар натиҷа, ҳатто пеш аз партофтан, шумо метавонед натиҷаи ояндаро тахминан ҳисоб кунед.

Сабаб дар он аст, ки шумораи бештари комбинатсияҳо барои ба даст овардани холҳои миёна мавҷуданд. Чӣ қадаре ки аз он дуртар бошад, ҳамон қадар комбинатсияҳо камтаранд - ва мутаносибан, эҳтимолияти талафот камтар аст. Агар ин маълумот визуалӣ карда шавад, он ба таври норавшан ба шакли занг шабоҳат хоҳад дошт. Аз ин рӯ, бо каме дарозкунӣ, системаи 10 зарро метавон RNG бо тақсимоти муқаррарӣ номид.

Мисоли дигар, танҳо ин дафъа дар ҳавопаймо - тир ба ҳадаф. Тирандоз як RNG хоҳад буд, ки як ҷуфт рақамҳоро (x, y) тавлид мекунад, ки дар график нишон дода шудааст.
BlessRNG ё тафтиши RNG барои адолат
Бо он розӣ шавед, ки вариант дар тарафи чап ба ҳаёти воқеӣ наздиктар аст - ин RNG бо тақсимоти муқаррарӣ аст. Аммо агар ба шумо лозим аст, ки ситораҳоро дар осмони торик пароканда кунед, пас варианти дурусте, ки бо истифода аз RNG бо тақсимоти якхела ба даст оварда шудааст, беҳтар аст. Умуман, генераторро вобаста ба вазифаи дар пеш истода интихоб кунед.

Акнун биёед дар бораи энтропияи пайдарпаии PNG сӯҳбат кунем. Масалан, як пайдарпаие вуҷуд дорад, ки чунин оғоз меёбад:

89, 93, 33, 32, 82, 21, 4, 42, 11, 8, 60, 95, 53, 30, 42, 19, 34, 35, 62, 23, 44, 38, 74, 36, 52, 18, 58, 79, 65, 45, 99, 90, 82, 20, 41, 13, 88, 76, 82, 24, 5, 54, 72, 19, 80, 2, 74, 36, 71, 9, ...

Ин рақамҳо дар назари аввал то чӣ андоза тасодуфӣ ҳастанд? Биёед аз тафтиши тақсимот оғоз кунем.
BlessRNG ё тафтиши RNG барои адолат
Он ба либоси ягона наздик ба назар мерасад, аммо агар шумо пайдарпаии ду рақамро хонед ва онҳоро ҳамчун координатҳо дар ҳавопаймо тафсир кунед, шумо инро мегиред:
BlessRNG ё тафтиши RNG барои адолат
Намунаҳо ба таври равшан намоён мешаванд. Ва азбаски маълумот дар пайдарпаӣ ба таври муайян тартиб дода шудааст (яъне он энтропияи паст дорад), ин метавонад ба он "ғараз" оварда расонад. Ҳадди ақал, чунин PRNG барои тавлиди координатҳо дар ҳавопаймо чандон мувофиқ нест.

Боз як пайдарпай:

42, 72, 17, 0, 30, 0, 15, 9, 47, 19, 35, 86, 40, 54, 97, 42, 69, 19, 20, 88, 4, 3, 67, 27, 42, 56, 17, 14, 20, 40, 80, 97, 1, 31, 69, 13, 88, 89, 76, 9, 4, 85, 17, 88, 70, 10, 42, 98, 96, 53, ...

Дар ин ҷо ҳатто дар ҳавопаймо ҳама чиз хуб ба назар мерасад:
BlessRNG ё тафтиши RNG барои адолат
Биёед ба ҳаҷми ҳаҷм назар кунем (дар як вақт се рақамро хонед):
BlessRNG ё тафтиши RNG барои адолат
Ва боз намунаҳо. Дар чор андоза сохтани визуализатсия дигар имконнопазир аст. Аммо намунаҳо метавонанд дар ин андоза ва дар калонтар вуҷуд дошта бошанд.

Дар криптография, ки дар он талаботҳои сахттарин ба PRNG гузошта мешаванд, чунин вазъият комилан қобили қабул нест. Аз ин рӯ, алгоритмҳои махсус барои арзёбии сифати онҳо таҳия карда шудаанд, ки мо ҳоло ба онҳо дахл намекунем. Мавзӯъ васеъ аст ва сазовори мақолаи алоҳида аст.

санҷиши

Агар мо чизеро аниқ надонем, пас бо он чӣ гуна бояд кор кунем? Оё аз роҳ гузаштан меарзад, агар шумо намедонед, ки кадом чароғ ба он иҷозат медиҳад? Оқибатҳо метавонанд гуногун бошанд.

Ҳамин чиз ба тасодуфи маъруф дар Unity дахл дорад. Хуб аст, ки ҳуҷҷатҳо тафсилоти заруриро ошкор кунанд, аммо ҳикояи дар аввали мақола зикршуда маҳз аз сабаби набудани мушаххасоти дилхоҳ рӯй дод.

Ва агар шумо намедонед, ки асбоб чӣ гуна кор мекунад, шумо онро дуруст истифода бурда наметавонед. Умуман, вақти он расидааст, ки санҷиш ва таҷриба гузаронем, то ҳадди аққал дар бораи тақсимот боварӣ ҳосил кунем.

Ҳалли оддӣ ва муассир буд - ҷамъ овардани омор, гирифтани маълумоти объективӣ ва ба натиҷаҳо нигаред.

Мавзӯи омӯзиш

Якчанд роҳҳои тавлиди рақамҳои тасодуфӣ дар Unity вуҷуд доранд - мо панҷ нафарро санҷидем.

  1. System.Random.Next(). Дар доираи додаи арзишҳо ададҳои бутун тавлид мекунад.
  2. System.Random.NextDouble(). Рақамҳои дақиқи дукаратаро дар диапазон аз [0; 1).
  3. UnityEngine.Random.Range(). Дар доираи додаи арзишҳо ададҳои дақиқи ягона (шино) тавлид мекунад.
  4. UnityEngine.Random.value. Дар доираи аз [0; 1).
  5. Unity.Mathematics.Random.NextFloat(). Қисми китобхонаи нави Unity.Mathematics. Дар доираи додаи арзишҳо ададҳои дақиқи ягона (шинокунанда) тавлид мекунад.

Тақрибан дар ҳама ҷо дар ҳуҷҷатҳо тақсимоти якхела нишон дода шудааст, ба истиснои UnityEngine.Random.value (дар он ҷо тақсимот муайян карда нашуда буд, аммо аз рӯи шабоҳат бо UnityEngine.Random.Range() низ дар назар буд) ва Unity.Mathematics.Random .NextFloat() (ки дар асоси ин алгоритми xorshift аст, яъне боз ба шумо лозим меояд, ки тақсимоти якхеларо интизор шавед).

Бо нобаёнӣ, натиҷаҳои интизоршуда ҳамчун натиҷаҳои дар ҳуҷҷатҳо зикршуда гирифта шуданд.

Методология

Мо як аризаи хурде навиштем, ки бо истифода аз ҳар яке аз усулҳои пешниҳодшуда пайдарпайии рақамҳои тасодуфиро тавлид мекард ва натиҷаҳоро барои коркарди минбаъда нигоҳ медошт.

Дарозии ҳар як пайдарпаӣ 100 000 ададро ташкил медиҳад.
Диапазони рақамҳои тасодуфӣ [0, 100) аст.

Маълумот аз якчанд платформаҳои мақсаднок ҷамъоварӣ карда шуд:

  • Windows
    — Unity v2018.3.14f1, Ҳолати Муҳаррир, Mono, .NET Standard 2.0
  • MacOS
    — Unity v2018.3.14f1, Ҳолати Муҳаррир, Mono, .NET Standard 2.0
    — Unity v5.6.4p4, Ҳолати Муҳаррир, Mono, .NET Standard 2.0
  • андроид
    — Unity v2018.3.14f1, сохтани ҳар дастгоҳ, Mono, .NET Standard 2.0
  • IOS
    — Unity v2018.3.14f1, сохтани ҳар дастгоҳ, il2cpp, .NET Standard 2.0

Реализация

Мо якчанд роҳҳои гуногуни тавлиди рақамҳои тасодуфӣ дорем. Барои ҳар яки онҳо, мо як синфи алоҳидаи бастабандӣ менависем, ки он бояд:

  1. Имконияти муқаррар кардани диапазони арзишҳо [min/max). Тавассути созанда муқаррар карда мешавад.
  2. Усули баргардонидани MF. Биёед шиновариро ҳамчун намуд интихоб кунем, зеро он умумӣтар аст.
  3. Номи усули тавлид барои нишон додани натиҷаҳо. Барои роҳат, мо ҳамчун арзиш номи пурраи синф + номи усулеро, ки барои тавлиди MF истифода мешавад, бармегардонем.

Аввалан, биёед абстраксияеро эълон кунем, ки онро интерфейси IRandomGenerator муаррифӣ мекунад:

namespace RandomDistribution
{
    public interface IRandomGenerator
    {
        string Name { get; }

        float Generate();
    }
}

Амалисозии System.Random.Next()

Ин усул ба шумо имкон медиҳад, ки як қатор арзишҳоро муқаррар кунед, аммо он ададҳои бутунро бармегардонад, аммо шинокунанда лозим аст. Шумо метавонед танҳо ададро ҳамчун шинокунанда тафсир кунед, ё шумо метавонед диапазони арзишҳоро бо якчанд фармоиши миқёс васеъ карда, онҳоро бо ҳар як насли миёна ҷуброн кунед. Натиҷа чизе ба монанди нуқтаи собит бо тартиби дақиқи додашуда хоҳад буд. Мо ин хосиятро истифода хоҳем бурд, зеро он ба арзиши воқеии шинокунанда наздиктар аст.

using System;

namespace RandomDistribution
{
    public class SystemIntegerRandomGenerator : IRandomGenerator
    {
        private const int DefaultFactor = 100000;
        
        private readonly Random _generator = new Random();
        private readonly int _min;
        private readonly int _max;
        private readonly int _factor;


        public string Name => "System.Random.Next()";


        public SystemIntegerRandomGenerator(float min, float max, int factor = DefaultFactor)
        {
            _min = (int)min * factor;
            _max = (int)max * factor;
            _factor = factor;
        }


        public float Generate() => (float)_generator.Next(_min, _max) / _factor;
    }
}

Амалисозии System.Random.NextDouble()

Дар ин ҷо диапазони собит арзишҳо [0; 1). Барои проексия кардани он ба арифметикаи дар конструктор нишондодашуда, мо арифметикаи оддиро истифода мебарем: X * (макс - min) + min.

using System;

namespace RandomDistribution
{
    public class SystemDoubleRandomGenerator : IRandomGenerator
    {
        private readonly Random _generator = new Random();
        private readonly double _factor;
        private readonly float _min;


        public string Name => "System.Random.NextDouble()";


        public SystemDoubleRandomGenerator(float min, float max)
        {
            _factor = max - min;
            _min = min;
        }


        public float Generate() => (float)(_generator.NextDouble() * _factor) + _min;
    }
}

Амалисозии UnityEngine.Random.Range()

Ин усули синфи статикии UnityEngine.Random ба шумо имкон медиҳад, ки як қатор арзишҳоро муқаррар кунед ва навъи шинокунандаро баргардонед. Ба шумо лозим нест, ки ягон тағироти иловагӣ анҷом диҳед.

using UnityEngine;

namespace RandomDistribution
{
    public class UnityRandomRangeGenerator : IRandomGenerator
    {
        private readonly float _min;
        private readonly float _max;


        public string Name => "UnityEngine.Random.Range()";


        public UnityRandomRangeGenerator(float min, float max)
        {
            _min = min;
            _max = max;
        }


        public float Generate() => Random.Range(_min, _max);
    }
}

Амалисозии UnityEngine.Random.value

Хосияти арзиши синфи статикии UnityEngine.Random навъи шинокунандаро аз диапазони собит арзишҳо бармегардонад [0; 1). Биёед онро ба диапазони додашуда ҳамон тавре ки ҳангоми татбиқи System.Random.NextDouble() тарҳрезӣ кунем.

using UnityEngine;

namespace RandomDistribution
{
    public class UnityRandomValueGenerator : IRandomGenerator
    {
        private readonly float _factor;
        private readonly float _min;


        public string Name => "UnityEngine.Random.value";


        public UnityRandomValueGenerator(float min, float max)
        {
            _factor = max - min;
            _min = min;
        }


        public float Generate() => (float)(Random.value * _factor) + _min;
    }
}

Амалисозии Unity.Mathematics.Random.NextFloat()

Усули NextFloat()-и синфи Unity.Mathematics.Random нуқтаи шинокунандаи навъи floatро бармегардонад ва ба шумо имкон медиҳад, ки як қатор арзишҳоро муайян кунед. Ягона нозуки дар он аст, ки ҳар як мисоли Unity.Mathematics.Random бояд бо баъзе тухмиҳо оғоз карда шавад - бо ин роҳ мо аз тавлиди пайдарпайҳои такрорӣ худдорӣ мекунем.

using Unity.Mathematics;

namespace RandomDistribution
{
    public class UnityMathematicsRandomValueGenerator : IRandomGenerator
    {
        private Random _generator;
        private readonly float _min;
        private readonly float _max;


        public string Name => "Unity.Mathematics.Random.NextFloat()";


        public UnityMathematicsRandomValueGenerator(float min, float max)
        {
            _min = min;
            _max = max;
            _generator = new Random();
            _generator.InitState(unchecked((uint)System.DateTime.Now.Ticks));
        }


        public float Generate() => _generator.NextFloat(_min, _max);
    }
}

Амалисозии MainController

Якчанд татбиқи IRandomGenerator омодаанд. Баъдан, шумо бояд пайдарпайҳоро тавлид кунед ва маҷмӯи додаҳои натиҷашударо барои коркард захира кунед. Барои ин, мо дар Unity як саҳна ва скрипти хурди MainController эҷод мекунем, ки ҳамаи корҳои заруриро иҷро мекунад ва ҳамзамон барои ҳамкорӣ бо UI масъул аст.

Биёед андозаи маҷмӯи додаҳо ва диапазони арзишҳои MF-ро муқаррар кунем ва инчунин усулеро гирем, ки массиви генераторҳои конфигуратсияшуда ва ба кор омодаро баргардонад.

namespace RandomDistribution
{
    public class MainController : MonoBehaviour
    {
        private const int DefaultDatasetSize = 100000;

        public float MinValue = 0f;
        public float MaxValue = 100f;

        ...

        private IRandomGenerator[] CreateRandomGenerators()
        {
            return new IRandomGenerator[]
            {
                new SystemIntegerRandomGenerator(MinValue, MaxValue),
                new SystemDoubleRandomGenerator(MinValue, MaxValue),
                new UnityRandomRangeGenerator(MinValue, MaxValue),
                new UnityRandomValueGenerator(MinValue, MaxValue),
                new UnityMathematicsRandomValueGenerator(MinValue, MaxValue)
            };
        }

        ...
    }
}

Акнун биёед маҷмӯи додаҳо эҷод кунем. Дар ин ҳолат тавлиди маълумот бо сабти натиҷаҳо ба ҷараёни матн (дар формати csv) якҷоя карда мешавад. Барои нигоҳ доштани арзишҳои ҳар як IRandomGenerator, сутуни алоҳидаи он ҷудо карда мешавад ва сатри аввал Номи генераторро дар бар мегирад.

namespace RandomDistribution
{
    public class MainController : MonoBehaviour
    {
        ...
		
        private void GenerateCsvDataSet(TextWriter writer, int dataSetSize, params IRandomGenerator[] generators)
        {
            const char separator = ',';
            int lastIdx = generators.Length - 1;

            // write header
            for (int j = 0; j <= lastIdx; j++)
            {
                writer.Write(generators[j].Name);
                if (j != lastIdx)
                    writer.Write(separator);
            }
            writer.WriteLine();

            // write data
            for (int i = 0; i <= dataSetSize; i++)
            {
                for (int j = 0; j <= lastIdx; j++)
                {
                    writer.Write(generators[j].Generate());
                    if (j != lastIdx)
                        writer.Write(separator);
                }

                if (i != dataSetSize)
                    writer.WriteLine();
            }
        }

        ...
    }
}

Танҳо даъват кардани усули GenerateCsvDataSet ва захира кардани натиҷа ба файл ё фавран интиқол додани маълумот тавассути шабака аз дастгоҳи ниҳоӣ ба сервери қабулкунанда боқӣ мемонад.

namespace RandomDistribution
{
    public class MainController : MonoBehaviour
    {
        ...
		
        public void GenerateCsvDataSet(string path, int dataSetSize, params IRandomGenerator[] generators)
        {
            using (var writer = File.CreateText(path))
            {
                GenerateCsvDataSet(writer, dataSetSize, generators);
            }
        }


        public string GenerateCsvDataSet(int dataSetSize, params IRandomGenerator[] generators)
        {
            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
            {
                GenerateCsvDataSet(writer, dataSetSize, generators);
                return writer.ToString();
            }
        }

        ...
    }
}

Сарчашмаҳои лоиҳа дар Гуглаб.

натиҷаҳои

Ягон мӯъҷизае рӯй надодааст. Он чизе ки онҳо интизор буданд, он чизест, ки онҳо ба даст оварданд - дар ҳама ҳолатҳо, тақсимоти баробар бидуни ишораи тавтиъа. Ман нуқтаи гузоштани графикҳои алоҳида барои платформаҳоро намебинам - ҳамаи онҳо тақрибан як натиҷаро нишон медиҳанд.

Воқеият ин аст:
BlessRNG ё тафтиши RNG барои адолат

Намоиши пайдарпаӣ дар як ҳавопаймо аз ҳамаи панҷ усули насл:
BlessRNG ё тафтиши RNG барои адолат

Ва визуализатсия дар 3D. Ман танҳо натиҷаи System.Random.Next()-ро мегузорам, то як миқдори мундариҷаи якхеларо тавлид накунам.
BlessRNG ё тафтиши RNG барои адолат

Ҳикояе, ки дар муқаддима дар бораи тақсимоти муқаррарии UnityEngine.Random нақл карда шуда буд, такрор нашуд: ё он дар аввал хато буд, ё баъдан чизе дар муҳаррик тағир ёфтааст. Аммо ҳоло мо боварӣ дорем.

Манбаъ: will.com

Илова Эзоҳ