読者です 読者をやめる 読者になる 読者になる

ますはらの日記(?)

無線通信の勉強をしてる陸上部の学生のぼやき(?)

最近学んだ事シリーズ:モンテカルロ法によるシミュレーションで用いる乱数の生成

みなさん、どうも。

今朝?投稿した「最近学んだ事」をシリーズ化してみようかなと思い、今日は2度目の投稿を決意しました(堅苦しい挨拶…)。

と、シリーズ化って言っても興味を持ってもらえるような記事を書けるか不安ではあるの(そもそも続ける事ができるかどうか怪しい)ですが、気長に見守っててくれると有り難いです(笑)

さて、タイトルのせいで自分からものすごくハードルが上がってる(?)気がしますが、ここでは自分が乱数生成の関数を学ぶ際に参考にしたものを紹介しながら書いてみたいと思います。

Q. そもそも何故、モンテカルロ法を学ぼうと思ったか?

僕は今後、無線通信をテーマにした研究室に配属されるため、データを取るためにはプログラムによるシミュレーションを行わなければいけません。しかも、論文などを見てみるとモンテカルロ(Monte Carlo)法が用いられていたので勉強しなきゃと思いました。

いよいよ、本題。

僕はこちらの本を使い、参考にしながら学びました。

C言語によるディジタル無線通信技術

C言語によるディジタル無線通信技術

この本は自分は残念ながらC言語にしかまともに触れていなかったため、C言語を用いた無線通信に関するシミュレーションを題材に扱ってる本はないか、探してみたところ見つけて即購入したものです。変調方式からフェージングなど無線通信に関する基礎事項の説明も書かれているので、無線通信に関する参考書としてオススメです。


無線通信において乱数を用いる場面はどこだろう?それは主に信号(雑音も含む)です。
ここでの信号はほとんどの場合、信号の確率密度関数ガウス分布(式(1)に示す)に従うものとして扱われます。

{ \displaystyle p(x) = \frac{1}{\sqrt{2\pi \sigma}}\exp\biggl(-\frac{(x-\mu)^{2}}{2\sigma^{2}}\biggr) \hspace{1.0cm}(1)}

 { \displaystyle x }は信号値、 { \displaystyle \mu }は信号の平均値、 { \displaystyle {\sigma}^{2} }は信号の電力を表す。

無線通信のシミュレーションの場合、専ら正規分布に従うという条件下を考える場合が多いので平均値は0、電力は1として扱われる場合がほとんど。こういった状況で誤り確率の値がシミュレーションされます。なので、正規分布に従った乱数(正規乱数)の生成方法を学びました。

また、無線通信において「フェージング」と呼ばれる干渉現象を考える場合も多く、このフェージング環境下においては信号の振幅値の確率密度関数がレイリー分布(式(2)に示す)に従うものとして扱われる。

{ \displaystyle p(r) = \frac{r}{\sigma^{2}}\exp\biggl(-\frac{r^{2}}{\sigma^{2}}\biggr) \hspace{1.0cm}(2)}

ここでの { \displaystyle r }は信号の実部 { \displaystyle X_{r} }と虚部 { \displaystyle X_{i} }を用いて、 { \displaystyle r = \sqrt{X_{r}^{2}+X_{i}^{2}} }と表される。

さらに 、 { \displaystyle X_{r} } { \displaystyle X_{i} }はともに平均値0、分散1の正規分布に従うものされる場合が多いので、今回はその条件下で乱数生成を学習した。

実際に乱数を生成するためのCプログラム(正確には関数ですね)は次の通りです。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

//一様乱数発生させる関数
double randU(void){
  return ((double)rand() / (double)RAND_MAX);
}

//標準正規分布に従う乱数発生させる関数
double randN(void){
  double s, r, t;
  s = randU();
  if(s == 0.0) s = 0.000000001;
  r = sqrt(-2.0 * log(s));
  t = 2.0 * M_PI * randU();
  return (r * sin(t));
}

//正規化されたレイリー分布に従う振幅値を発生させる関数
double rayleigh(void){
  return sqrt(pow(randN(), 2.0) + pow(randN(), 2.0)) * sqrt(0.5);
}

このプログラムに関していろいろ書こうかと思ったのですが、ここまで書いてきてすごく疲れてしまったので参考ページを掲載します(笑)
参考ページ↓
C言語による乱数生成


このページにはレイリー分布については書いてませんので注意してください。レイリー分布に関しては先程紹介した本に記載されていますので、そちらを確認していただければと思います。しかし、レイリー分布に関しては何故この式でいいのだろう?と思ったのでその事に関してだけ。。。
この疑問については…よくよく考えてみると振幅値、つまり、 { \displaystyle r }の値なので単純に { \displaystyle r }に関する式から考えて、上記のプログラムのようになったと理解できました。冷静に考える重要さが身に染みましたね(笑)


と、まぁこんな感じで少しずつですが勉強していってます。
かなり長々と書いたつもりですが、僕が不慣れすぎて雑になってしまいました(⌒-⌒; )
今回は大目に見てもらえると今後も続けられると思います(笑)


それでは、キリが悪いのですがこの辺で!