

コンピュータの擬似乱数
わたしの旧twitter(X)にはいろいろな技術情報が流れてきます。気になったものはその情報をたどって詳細を確認するのですが、少し前に「乱数をつくる」手法が流れてきました。メカトロの専門の範囲で、また様々な目的で、乱数を使うため関心対象です。生産設備などを動かすときにランダムさは無縁そうに見えますが、ロボット分野では乱数を使う手法が様々ありますし、我々の日常でも乱数のお世話になっています。
乱数、乱数列は、文字通りランダムな数値です。それまでに出てきた数値列から、次に出る数値は予想できません。乱数を得るという作業(サイコロをふるとか、関数の実行など)のたびになにか数値を得ます。一方、一般的なコンピュータの計算にはランダムな要素がないため、コンピュータのプログラムで作り出した乱数は、乱数っぽく見えても何か規則があって、かつ非常に長い周期の繰り返しがあり、擬似乱数と呼ばれます。
擬似乱数にはいくつもの生成方法が提案され、使われています。それら方法を比較するための主な評価指標は、計算の手間と乱数としての性質の良さです。前者については、たまにしか使わないものであれば負担になりませんが、ランダムな信号の生成では使用回数が多くなりますし、ロボット制御分野にもひたすら乱数を使うような手法があり、その場合は簡単な演算で済むに超したことはありません。後者はどのくらい本来の乱数の性質に近いかという観点で、単純にはその繰り返しの周期の長さ、ある程度の数量の乱数を作った時にその列から次の値を予想し得るかどうかなどがあります。
コンピュータの乱数はちょっとしたゲームを作ろうとしたときなどにも(たとえばじゃんけんでも)必須なので、私はプログラムを作るようになった早い段階から触れていました。プログラミング言語標準の乱数ではしばしば、「0~ある上限」までの整数が一様に出てくるため、たとえば、{1,2,3}から一つ出るものが欲しいという場合は、
(得た乱数÷3の余り)+1
のような計算をします。この使い方をしたときにも綺麗な乱数かという観点もあります。
あるとき、画面上で上下左右にランダムに動き回る点をつくろうとしました。4で割った余り(より正確には下位2ビットを使用)の0123で4方向を決めるプログラムを書いて実行したところ、動きません。正確には、上下左右の動きを規則的に繰り返して、小さな往復運動をしていました。当時は乱数とはランダムなもので、このような現象が起き得るという知識はなかったため、移動方向を画面に連続して表示させて現象を特定しても何が悪いのかわかりませんでした。ふと、「5で割って余り0123は移動、4は乱数出し直し」としてみたらランダムっぽく動き回ったので、そのときはそれで良しとしました。擬似乱数の方式によってはこのような問題があることを知ったのは、ずっと後のことでした。
技術全般に「いいところしかない」なら、特許等の制約がないなら、その手法が席巻するはずですが、複数が共存しているのは利点欠点の取捨選択があるためです。冒頭の、流れてきた手法は原理を理解しきれませんでしたが、小型のマイコンで動かすのにも軽そうな方法に見えました。
擬似乱数の再現性と使い道
本来、状況に応じて確定的な動作をして欲しいメカトロの分野でも目的によっては乱数は使われています。たとえば、ロボットに関わる分野で「探索の可能性を増やす」ために乱数を用いる手法があります。迷路のような環境でロボットの経路を考えるときに、数式で解いては答えが直接得られる保証がなく、あり得る全ての可能性を挙げると膨大な数・困難というケースで乱数を併用して、ほどほどの答えをほどほどの時間で求めるという手法があります。また、多くの場合は良好な解が得られる計算法でありながら、ある条件では袋小路で動けなくなるという場合に、乱数によるランダムさを加えることで脱出できるようにするというアイデアもあります。
ほかにも、近年はメカトロで使う通信の暗号化も一般化していますが(たとえば日常的に使うhttpsの”s”はHTTPに暗号化によるsecure、安全の追加)、その鍵を作るために乱数が使われます。これは物としてのドアの鍵も同じですが、ある特定の配列を鍵として使う上で、その配列が何らかのルールで決まっていると、何らかの方法で予測され突破できてしまうわけです。たとえば、集合住宅で部屋ごとの鍵の形に規則性があったら困ります。
前記の擬似乱数は予測しづらいとはいえ規則があって、より本格的な乱数が欲しいときに、たとえば自然の電気的な乱数(抵抗が発する雑音など)や、人間にマウスを適当に動かしてもらって、それを加味するなどの手法もあります(ドアの鍵であれば製造したときには何らかの規則性があったとしても在庫をガラガラかき回していれば、どこの扉にどの鍵が行くかは乱数的といえる)。一方、擬似乱数の規則性が便利なことがあります。
たとえば、何らかの計測信号の処理をしてノイズの除去をする手法の検討をするとします。その評価調整段階で、概ね大丈夫だけど、特定の状況がたまたま出ると対処できない場合がある、のようなケースを扱うとき、純粋な乱数だとそれを再現させることは無理です。しかし、擬似乱数だと種と呼ばれる最初を定める数値が同一なら、その後は同一の乱数列が出るため、再現性のある試験ができて、比較やそれに基づく改善などがやりやすくなります。似たところでは、学生さんに信号処理の宿題を出すのに、一見するとランダムなノイズの処理のように見えて、実は入力された学生番号をもとにしたノイズで、教員側でも同じ物を再現できる、という使い方もあります。
もう一つの事例として、私が運営に関わっているロボットコンテストの競技順の決定にも、擬似乱数の再現性を使っています。運営システムの各種調整や動作試験をした後、まっさらから準備作業のやり直しをすることがあるのですが、そのときに競技順序が変わってしまったら、恣意的な順序の組み直しも可能と解釈できます。そこで、競技順を決定するための手順をプログラム側で確定しておくとともに、乱数の種を大会の日付等で自動的に決まる値にすることで、作業のやり直しをしても同じ順序が再現されるようにするとともに、運営者の恣意性の無さを示せるようにしています。
擬似乱数というと、乱数として大丈夫なのかという点も気になるところですが、それが許容できるかどうかは使う側で判断するとともに、擬似乱数であるが故の利点もあるわけです。
この記事は、会員専用記事です。
有料会員になると、会員限定の有料記事もお読みいただけます。