Як ефективно генерувати відсортовані рівномірно розподілені значення в інтервалі?


12

Скажімо, я хочу генерувати набір випадкових чисел з інтервалу (a, b). Створена послідовність також повинна мати властивість її сортування. Я можу придумати два способи цього досягти.

Нехай nбуде довжина послідовності, яка буде створена.

1-й алгоритм:

Let `offset = floor((b - a) / n)`
for i = 1 up to n:
   generate a random number r_i from (a, a+offset)
   a = a + offset
   add r_i to the sequence r

2-й алгоритм:

for i = 1 up to n:
    generate a random number s_i from (a, b)
    add s_i to the sequence s
sort(r)

Моє запитання полягає в тому, чи алгоритм 1 створює такі ж послідовності, настільки ж хороші, як ті, що генеруються алгоритмом 2?


Rkn[a,b]rand_array <- replicate(k, sort(runif(n, a, b))

Відповіді:


18

Перший алгоритм виходить з ладу з двох причин:

  1. (ab)/nba<n

  2. na=0b=1(11/n)n1/e37%11/n1100%Шанс, що максимум буде в цьому інтервалі. Для деяких цілей ця суперрівномірність є хорошою, але загалом це жахлива помилка, оскільки (а) багато статистики буде зіпсовано, але (б) визначити, чому це може бути дуже важко.

  3. n+1(0,1)1(a,b)

1000n=100

Більше багатьох (кумедних) способів моделювання незалежних рівномірних змінних див. У розділі Моделювання креслень з рівномірного розподілу за допомогою малюнків із звичайного розподілу .

Фігура: гістограми

Ось Rкод, який створив фігуру.

b <- 1
a <- 0
n <- 100
n.iter <- 1e3

offset <- (b-a)/n
as <- seq(a, by=offset, length.out=n)
sim.1 <- matrix(runif(n.iter*n, as, as+offset), nrow=n)
sim.2 <- apply(matrix(runif(n.iter*n, a, b), nrow=n), 2, sort)
sim.3 <- apply(matrix(rexp(n.iter*(n+1)), nrow=n+1), 2, function(x) {
  a + (b-a) * cumsum(x)[-(n+1)] / sum(x)
})

par(mfrow=c(1,3))
hist(sim.1, main="Algorithm 1")
hist(sim.2, main="Algorithm 2")
hist(sim.3, main="Exponential")

Що ви думаєте про алгоритм (заснований на статистиці порядку рангів) у моїй відповіді? ;-)
Має QUIT - Anonymous-Mousse

@Anonymous Це менш ефективна версія мого алгоритму 3. (Здається, у вас є багато непотрібного масштабування.) Ви генеруєте експоненціальні змінні, приймаючи журнали обмундирування, що є стандартним.
whuber

6

Перший алгоритм виробляє занадто рівномірно розташовані числа

Дивіться також серію з низькою невідповідністю .

[0;1]

(Як зазначалося, це може бути бажаною властивістю, наприклад, для стратифікації. Серії з низькою невідповідністю, як Халтон і Собель , мають свої випадки використання.)

Правильний, але дорогий підхід (для реальних цінностей)

... полягає у використанні бета-розподілених випадкових чисел. Статистика рангового порядку рівномірного розподілу розподіляється бета-версією. Ви можете використовувати це, щоб випадковим чином намалювати найменший , потім другий найменший, ... повторити.

[0;1]Beta[1,n]n1XBeta[n,1]ln(1X)Exponential[n]ln(U[0;1])n

ln(1x)=ln(1u)n1x=u1nx=1u1n

Що дає такий алгоритм:

x = a
for i in range(n, 0, -1):
    x += (b-x) * (1 - pow(rand(), 1. / i))
    result.append(x) 

Можуть бути задіяні чисельні нестабільності, і обчислення powта поділ для кожного об'єкта можуть виявитися повільнішими, ніж сортування.

Для цілих значень вам може знадобитися використовувати інший розподіл.

Сортування неймовірно дешеве, тому просто використовуйте його

O(nlogn)


1
Можуть бути причини, щоб уникнути сортування. Одне з них полягає в тому, що ви хочете генерувати величезну кількість випадкових змінних, стільки, що звичайна процедура сортування не може обробити їх.
whuber

Я думаю, що чисельні проблеми з сумами з використанням математики з плаваючою комою стають проблемою набагато раніше. (І проблеми з циклічними візерунками в псевдовипадкових числах!) Досить легко масштабувати підхід до сортування до терабайт і до екзабайтів на розподілених системах.
Мав QUIT - Anonymous-Mousse

1012

Гаразд, не потрібно зберігати їх - це аргумент. Але тоді вам знадобиться мій підхід, ваш варіант 3 з використанням сукупної суми не буде працювати.
Мав QUIT - Anonymous-Mousse

Це відмінний момент. Тепер я бачу чесноту додаткових розрахунків! (+1)
блуд

5

Це також залежить від того, що ви робите з випадковими числами. Для проблем з числовою інтеграцією метод один (коли виправляється видаленням оператора підлоги) створив би кращий набір точок. Те, що ви робите, - це форма стратифікованого відбору проб, і вона має ту перевагу, що вона уникає скупчення. неможливо отримати, наприклад, усі ваші значення в діапазоні 0- (ba) / n. Це говорить про інші програми, це може бути дуже погано, це залежить від того, що ви хочете зробити з цим.


2
+1 Я думаю, що це корисний внесок у питання, особливо характеризуючи Алгоритм 1 з точки зору стратифікації.
whuber
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.