間隔で並べ替えられた均一に分布した値を効率的に生成する方法は?


12

間隔から乱数のセットを生成したいとしましょう(a, b)。生成されたシーケンスには、ソートされるというプロパティも必要です。これを実現する方法は2つ考えられます。

ましょn生成するシーケンスの長さ。

最初のアルゴリズム:

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によって生成されたものと同じくらい良いシーケンスを生成するのですか?


ところで、ソートされた乱数のリストをで生成するのは非常に簡単Rです。一定の間隔で乱数のセットの配列を生成するには、次のコードが機能します。n [ a b ]kn[a,b]rand_array <- replicate(k, sort(runif(n, a, b))
RobertF 2016

回答:


18

最初のアルゴリズムは、次の2つの理由で失敗します

  1. のフロアを取ると、大幅に削減できます。実際、、それはゼロになり、値がすべて同じであるセットを提供します。b a < n(ab)/nba<n

  2. フロアをとらない場合、結果の値は均等に分散されます。 たとえば、 iid均一変量の単純なランダムサンプル(たとえば、と)では、確率で最大はからまでの上部間隔にはありません。アルゴリズム1の場合、最大値がその間隔内になる確率はです。いくつかの目的では、この超均一性は良好ですが、(a)多くの統計が台無しになるが、(b)理由を判断するのが非常に難しいため、一般にひどいエラーです。= 0 、B = 1 1 - 1 / N N1 / E 37 1 - 1 / N 1 100 na=0b=1(11/n)n1/e37%11/n1100%

  3. ソートを避けたい場合は、代わりに独立した指数分布変量を生成します。合計で割ることにより、それらの累積合計を範囲正規化します。最大値を削除します(常になります)。範囲再スケーリングします。0 1 1 A B n+1(0,1)1(a,b)

3つのアルゴリズムすべてのヒストグラムが表示されます。(それぞれ、値の独立したセットの累積結果を示しています。)アルゴリズム1のヒストグラムに目に見える変動がないことは、そこに問題があることを示しています。他の2つのアルゴリズムのバリエーションは、期待されるものであり、乱数ジェネレーターに必要なものです。n = 1001000n=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あり-Anony-Mousse 2015年

@Anonyこれは、私のアルゴリズム3の効率の悪いバージョンです(あなたのアルゴリズムには、不必要な再スケーリングがたくさん含まれているようです)。
whuber

6

最初のアルゴリズムは、余りにも等間隔の数値を生成します

低差異シリーズもご覧ください。

[0;1]

(Asこれは層化のための所望の特性などもあり、指摘。ハルトンとソーベルなどの低食い違いシリーズがない彼らのユースケースを持っています。)

適切だが高価なアプローチ(実際の値の場合)

...ベータ分布の乱数を使用することです。一様分布の順位統計はベータ分布です。これを使用して、最小のものをランダムに、次に2番目に小さいものをランダムに描画します。

[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
ソートを回避する理由がある場合があります。1つは、膨大な数のランダムな変量を生成する必要がある場合で、標準のソートルーチンでは処理できないほど多くの変量があります。
whuber

浮動小数点演算を使用した合計に関する数値の問題は、はるかに早く問題になると思います。(そして、疑似乱数の循環パターンの問題!)ソート方式をテラバイトや分散システムのエクサバイトに拡張するのはかなり簡単です。
QUITあり-Anony-Mousse 2015

1012

OK、それらを保存する必要がないことは議論です。しかし、その後、私のアプローチが必要になります。累積合計を使用するバリアント3は機能しません。
QUITあり-Anony-Mousse 2015

それは素晴らしい点です。今、私は余分な計算の美徳を見ます!(+1)
whuber

5

また、乱数をどのように処理するかによっても異なります。数値積分問題の場合、方法1(フロアオペレーターを削除して修正した場合)は優れたポイントセットを生成します。あなたがやっていることは、層別サンプリングの形式であり、凝集を回避できるという利点があります。たとえば、0-(ba)/ nの範囲ですべての値を取得することは不可能です。それは他のアプリケーションではこれは非常に悪いことだと言いました、それはあなたがそれで何をしたいかによります。


2
+1これは、特にアルゴリズム1を層別化の観点から特徴付けることによって、この質問に対する有用な貢献だと思います。
whuber
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.