2017-10-19 14 views
1

既存の乱数ベースのデータジェネレータ(Pythonで)をハッシュベースのデータジェネレータに置き換えて、this articleからインスパイアされたように、すべてを順番に生成する必要がなくなりたいと考えています。PRNGベースの生成からハッシュベースの手続き生成に移行するにはどうすればよいですか?

ハッシュの整数バージョンを取得し、ハッシュの最大値で割ることで、0から1までのfloatを作成できます。

フロートをとり、フラットレンジで乗算することで、フラットな整数レンジを作成できます。私はおそらくモジュロを使用してバイアスをかけて生きることができます。ハッシュ範囲は広く、フラット範囲は小さいからです。

ハッシュを使用してガウス分布または正規分布の浮動小数点値を作成するにはどうすればよいですか?

これらのすべての場合、私は新しいrandom.Randomオブジェクトの種として自分のハッシュを使用し、そのクラスの関数を使用して自分の数値を生成し、分布特性を正しく得ることができます?

瞬間

、私のコードは次のように構成されています

num_people = randint(1,100) 
people = [dict() for x in range(num_people)] 
for person in people: 
    person['surname'] = choice(surname_list) 
    person['forename'] = choice(forename_list) 

問題は、与えられた種子が矛盾しないようにするために、私は同じ順序ですべての人々を生成する必要があり、私が持っているということです姓の後に姓を生成します。 2つの間にミドルネームを追加すると、生成されたforenamesが変更され、すべての後続の人物の名前が変更されます。

私はこのようなコードを構築したい:

h1_groupseed=1 

h2_peoplecount=1 
h2_people=2 

h4_surname=1 
h4_forename=2 

num_people = pghash([h1_groupseed,h2_peoplecount]).hashint(1,100) 
people = [dict() for x in range(num_people)] 
for h3_index, person in enumerate(people,1): 
    person['surname'] = surname_list[pghash([h1_groupseed,h2_people,h3_index,h4_surname]).hashint(0, num_of_surnames - 1)] 
    person['forename'] = forename_list[pghash([h1_groupseed,h2_people,h3_index,h4_forename]).hashint(0, num_of_forenames - 1)] 

これは、ハッシュを生成するためにpghashに渡された値を使用して、何とか擬似乱数結果を作成するために、そのハッシュを使用します。

+0

あなたがこれを行うにはしたくないのはなぜ? –

+0

Box Muller変換を使用して、一様分布の変数を通常のものに変更することができます。 https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform – WNG

+0

@ReblochonMasque属性の生成順序の変更に対してデータ生成器を堅牢にしたいからです。 – PhilHibbs

答えて

1

まず、大きな注意点:独自のCRYPTOを使用しないでください。 セキュリティ上の目的でこれを行う場合は、しないでください。

次に、すなわち通常のいずれかにランダムに均一な変数を変換し、あなたがやりたいことには、いくつかの方法を示していますこの質問をチェックアウト: Converting a Uniform Distribution to a Normal Distribution

+0

私は質問を編集して、正規分布の質問とは区別しました。 – PhilHibbs

1

あなたがあなた自身の娯楽のためか、としてこれをやっている場合を除き私の非常に強いアドバイスはであり、これをしないでください

PRNGは、詳細が大きく異なる場合でも同じ一般的な構造を持ちます。彼らは、いくつかの関数fを介して初期状態Sにシード値Sをマッピング:S← F(S)を、彼らは、その後、いくつかの変換Hを介して状態を繰り返す; H(S IS I + 1&LEFTARROW。そして最後に、それらは、いくつかの関数gを介して出力Uの状態をマップ:U I← G(S Iを)。 (単純なPRNGの場合、f()またはg()はしばしば同一性関数です。メルセンヌツイスターなどのより洗練されたジェネレーターについては、より多くが関わっています。)

状態遷移関数h()は、状態空間全体に均一に新しい状態を分散するように設計されています。言い換えれば、すでにハッシュ関数ですが、広範に受け入れられているジェネレータでは、統計的な振る舞いが優れていると専門家が厳しく吟味しているという利点があります。

メルセンヌツイスター、PythonのデフォルトのPRNGは、数学的にK-タプルが共同で均一あなたがこのような主張をすることはできません選択したものは何でも、ハッシュ関数であること、私は推測しているすべてのk ≤ 623のために配布される持つことが証明されています。さらに、畳み込み関数g()は、結果の均一性を保つ必要があります。 「ハッシュの整数バージョンを使用して、モジュラスを取るだけでフラットな数値範囲を作成できる」と提案しました。一般的にはmodulo biasが導入されますので、一様に分散した結果は得られません。

内蔵のPRNGを貼り付けると、組み込みのガウスジェネレータを使用しない理由はありません。あなた自身の娯楽のためにそれをしたいならば、ユニフォームをGaussiansにマップする方法を教える多くのリソースがあります。よく知られた方法は、Box-Muller方法、Marsaglia's polar method、およびziggurat方法を含む。


UPDATE

あなたがあなたの質問に提供してきました追加情報を考えると、私はあなたが欲しい答えがrandomのためにPythonのドキュメントのこのセクションに含まれていると思う:

機能が付属このモジュールでは、実際にはrandom.Randomクラスの非表示インスタンスの のメソッドにバインドされています。 自身のインスタンスをランダムにインスタンス化して、状態を共有しないジェネレータを取得することができます。この は、スレッドごとに異なる インスタンスを作成し、jumpahead()メソッド を使用して、各スレッドによって表示される生成されたシーケンスが重複しないようにするために、マルチスレッドプログラムに特に便利です。あなたは互いに独立してまたはrandom.jumpahead()文書で説明したように、同期が、広く分離状態を接種した各personについてRandomの別々のインスタンスを、望むよう

が鳴ります。これは、シミュレーションモデラーが1950年代初頭から使用してきた手法の1つで、2つ以上のシステムを公正な方法で直接比較するように構成間で再現性を維持することができます。 this articleの2番目のページ、またはthis book chapterの8ページから始まる「同期」についての議論をチェックするか、ほとんどの大学図書館で利用可能な数十のシミュレーション教科書のいずれかを拾い読みし、「一般的な乱数」のセクションを読んでください。 (。それがこのトピックにほとんどの詳細を提供していないので、私はウィキペディアに向けてあなたを指していないよ)

はここRandomの複数のインスタンスを作成示す明確な例です:

import random as rnd 

print("two PRNG instances with identical seeding produce identical results:") 
r1 = rnd.Random(12345) 
r2 = rnd.Random(12345) 
for _ in range(5): 
    print([r1.normalvariate(0, 1), r2.normalvariate(0, 1)]) 

print("\ndifferent seeding yields distinct but reproducible results:") 
r1 = rnd.Random(12345) 
r2 = rnd.Random(67890) 
for _ in range(3): 
    print([r1.normalvariate(0, 1), r2.normalvariate(0, 1)]) 
print("\nresetting, different order of operations") 
r1 = rnd.Random(12345) 
r2 = rnd.Random(67890) 
print("r1: ", [r1.normalvariate(0, 1) for _ in range(3)]) 
print("r2: ", [r2.normalvariate(0, 1) for _ in range(3)]) 
+0

だから、私は組み込みのランダムモジュールを使うべきですが、毎回フレッシュシードとしてハッシュを使用しますか?それは理にかなっている。毎回新しいランダムインスタンスを作成するコストがそれほど高くないことを願っています。 – PhilHibbs

+0

@PhilHibbsいいえ!良好な分布特性は、播種からではなく、PRNGに組み込まれたh()およびg()変換から生じる。シーディングはMersenne Twisterにとっては高価です。繰り返し行うことで、PRNGのデザイナーがあなたに与えることが困難な分布特性に実際に害を及ぼす可能性があります。 (なぜ「ランダムに同じ価値を与え続けるのか」のすべてのタイプを検索してください。)あなたがやっていることを本当に本当に知っていない限り、それを行うことは非常に正当な理由があるのでなければ、 – pjs

+0

私の[正当な理由](https://blogs.unity3d.com/2015/01/07/a-primer-on-repeatable-random-numbers/)は、私がすべてを生成する必要はないということです毎回まったく同じシーケンスでデータを収集します。私が追加した私のコード例を見てみましょう。後続のすべての人々が与えられたランダムなシードに対して全く異なる名前を持たない限り、どのように "ミドルネーム"属性を追加しますか? – PhilHibbs

0

私は先に行って、簡単なを作成しましたrandom.Randomクラスの機能のいくつかのハッシュベースの交換:

from __future__ import division 
import xxhash 
from numpy import sqrt, log, sin, cos, pi 

def gaussian(u1, u2): 
    z1 = sqrt(-2*log(u1))*cos(2*pi*u2) 
    z2 = sqrt(-2*log(u1))*sin(2*pi*u2) 
    return z1,z2 

class pghash: 
    def __init__(self, tuple, seed=0, sep=','): 
     self.hex = xxhash.xxh64(sep.join(tuple), seed=seed).hexdigest() 

    def pgvalue(self): 
     return int(self.hex, 16) 

    def pghalves(self): 
     return self.hex[:8], self.hex[8:] 

    def pgvalues(self): 
     return int(self.hex[:8], 16), int(self.hex[8:], 16) 

    def random(self): 
     return self.value()/2**64 

    def randint(self, min, max): 
     return int(self.random() * max + min) 

    def gauss(self, mu, sigma): 
     xx = self.pgvalues() 
     uu = [xx[0]/2**32, xx[1]/2**32] 
     return gaussian(uu[0],uu[1])[0] 

次のステップは、私のコードを通過し、pghashオブジェクトとはrandom.Randomメソッドへのすべての呼び出しを置き換えることです。

私はいくつかの点では、PyPIにアップロードすることを期待され、モジュールにこれを作っています https://github.com/UKHomeOffice/python-pghash

関連する問題