Він порушений, хоча якщо ви виконаєте достатню кількість перетасовок, це може бути відмінним наближенням (як показали попередні відповіді).
Просто, щоб зрозуміти, що відбувається, подумайте, як часто ваш алгоритм генерує перетасування масиву елементів, у якому зафіксовано перший елемент, . Коли перестановки генеруються з однаковою ймовірністю, це має відбуватися через часу. Нехай є відносною частотою цього явища після перетасовок з вашим алгоритмом. Давайте також будемо щедрі, і припустимо, що ви фактично вибираєте окремі пари індексів рівномірно для своїх перетасовок, так що кожна пара вибирається з вірогідністю =k ≥ 2 1 / k p n n 1 / ( kкk ≥ 21 / кpнн1 / ( к2)2 / ( k ( k - 1 ) ). (Це означає, що "тривіальних" перетасовок немає даремно. З іншого боку, він повністю порушує ваш алгоритм для двоелементного масиву, тому що ви чергуєте між фіксацією двох елементів і заміною їх, тому якщо ви зупинитесь після заздалегідь заданої кількості кроки, випадковості до результату немає!)
Ця частота задовольняє просту повторюваність, тому що перший елемент виявляється у своєму первісному місці після перетасовок двома роз'єднаними способами. Одне полягає в тому, що воно було зафіксовано після переміщення, а наступне переміщення не переміщує перший елемент. Інша полягає в тому, що вона була переміщена після переміщення, але переміщення переміщує її назад. Шанс не переміщення першого елемента дорівнює = , тоді як шанс переміщення першого елемента назад дорівнює = . Звідки:n nn + 1нн( k - 1n + 1с т (k-2)/k1/ ( k( k-12) / ( к2)( k - 2 ) / k 2/(k(k-1))1 / ( к2)2 / ( k ( k - 1 ) )
p0= 1
тому що перший елемент починається на належному місці;
pn + 1= k - 2кpн+ 2k ( k - 1 )( 1 - сн) .
Рішення є
pн= 1 / k + ( k - 3k - 1)нk - 1к.
Віднімаючи , ми бачимо, що частота неправильна . Для великих і хорошим наближенням є . Це показує, що похибка в цій конкретній частоті експоненціально зменшиться з кількістю свопів відносно розміру масиву ( ), що вказує, що з великими масивами буде важко виявити, якщо ви зробили відносно велику кількість свопів - але помилка завжди є.( k - 31 / к knk-1( k - 3k - 1)нk - 1ккнп/кk−1kexp(−2nk−1)n/k
Важко забезпечити всебічний аналіз помилок на всіх частотах. Імовірно, вони будуть поводитись так, як цей, що свідчить про те, що як мінімум вам знадобиться (кількість свопів), щоб бути достатньо великим, щоб помилка була прийнятно малою. Наближене рішенняn
n>12(1−(k−1)log(ϵ))
де має бути дуже малим порівняно з . Звідси випливає, що повинно бути в кілька разів для рівномірних наближених ( тобто , де знаходиться в порядку рази або близько.)1 / k n k ϵ 0,01 1 / kϵ1/knkϵ0.011/k
Все це ставить питання: чому ви вирішили використовувати алгоритм, який не зовсім (але лише приблизно) правильний, використовує точно ті ж методи, що й інший алгоритм, який, очевидно, правильний, але який вимагає більше обчислень?
Редагувати
Коментар Тіло доречний (і я сподівався, що ніхто цього не зазначить, тому я міг би пощадити цю додаткову роботу!). Дозвольте пояснити логіку.
Якщо ви впевнені, що кожен раз генеруєте фактичні замінники, ви повністю закручені. Проблема, яку я вказав для випадку поширюється на всі масиви. Лише половину всіх можливих перестановок можна отримати, застосувавши парну кількість свопів; інша половина виходить шляхом застосування непарної кількості свопів. Таким чином, у цій ситуації ви ніколи не можете генерувати ніде поблизу рівномірного розподілу перестановок (але існує стільки можливих, що симуляційне дослідження для будь-якого значного не зможе виявити проблему). Це справді погано.kk=2k
Тому розумно генерувати свопи навмання, генеруючи дві позиції незалежно навмання. Це означає, що є шанс кожного разу заміняти елемент собою; тобто нічого не робити. Цей процес трохи сповільнює алгоритм: після кроків ми очікуємо, що відбудеться лише приблизно справжніх замінів.n k - 11/knk−1kN<N
Зауважте, що розмір помилки монотонно зменшується з кількістю чітких свопів. Тому проведення менших свопів в середньому також збільшує помилку, в середньому. Але це ціна, яку ви повинні бути готові заплатити, щоб подолати проблему, описану в першій кулі. Отже, моя оцінка помилок є консервативно низькою, приблизно в коефіцієнті .(k−1)/k
Я також хотів зазначити цікавий очевидний виняток: уважний погляд на формулу помилки говорить про те, що у випадку помилки немає . Це не помилка: це правильно. Однак тут я розглянув лише одну статистику, що стосується рівномірного розподілу перестановок. Той факт, що алгоритм може відтворити цю статистику, коли (а саме отримання потрібної частоти перестановок, що фіксують будь-яку задану позицію), не гарантує, що перестановки дійсно розподіляються рівномірно. Дійсно, після фактичних свопів, єдиними можливими перестановками, які можна генерувати, є ,k = 3 2 n ( 123 ) ( 321 ) 2 n + 1 ( 12 ) ( 23 ) ( 13 )k=3k=32n(123)(321)та особи. Тільки остання фіксує будь-яку задану позицію, тому дійсно рівно третина перестановок фіксує позицію. Але половина перестановок відсутня! В іншому випадку, після фактичних свопів, єдиними можливими перестановками є , та . Знову-таки, саме одна з них виправить будь-яку задану позицію, тому ми знову отримаємо правильну частоту перестановок, що фіксують це положення, але знову-таки отримаємо лише половину можливих перестановок.2n+1(12)(23)(13)
Цей невеликий приклад допомагає розкрити основні напрямки аргументу: будучи «щедрими», ми консервативно недооцінюємо показник помилок для однієї конкретної статистики. Оскільки цей показник помилок не є нульовим для всіх , ми бачимо, що алгоритм порушений. Крім того, аналізуючи занепад швидкості помилок для цієї статистики, ми встановлюємо нижню межу щодо кількості ітерацій алгоритму, необхідних для сподівання на рівномірний розподіл перестановок.k ≥ 4