ディジタル通信システムを設計するとき、最も基本的で重要な問いの1つは「どれくらいの確率でビットが誤って受信されるか」です。たとえば、Wi-Fiで動画を視聴しているとき、一定割合以上のビットが化ければ映像が乱れます。衛星から地上に送られる観測データでは、1ビットの誤りが科学的な結論を左右することもあります。この「ビット誤りの起きやすさ」を定量化する指標が BER(Bit Error Rate:ビット誤り率) です。
BER を理論的に求められると、次のような設計判断が可能になります。
- 通信システムの変調方式選定: 同じ帯域幅・電力の条件下でBPSK、QPSK、16-QAMなどのどれが最適かを比較できる
- リンクバジェット設計: 衛星通信や移動体通信で必要な送信電力やアンテナ利得を逆算できる
- 誤り訂正符号の性能評価: 符号化前後のBERの改善量(コーディングゲイン)を定量的に評価できる
本記事の内容
- BERの定義と通信品質指標としての位置づけ
- AWGNチャネルモデル — ディジタル通信の基本舞台
- Q関数と相補誤差関数(erfc)の定義と関係
- BPSK/QPSKのBER導出(マッチドフィルタ → 判定 → 誤り確率)
- M-QAMのBER近似式
- ASK/FSKのBER(直交検波 vs. 非直交検波)
- ウォーターフォールカーブの物理的意味
- Pythonによる各変調方式のBERシミュレーション vs 理論曲線の比較
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
BERとは — ビット誤り率の定義と意味
直感的な理解
電話で友人と会話しているとき、騒がしい環境では相手の言葉を聞き間違えることがあります。「右(みぎ)」を「左(ひだり)」と聞き違えるようなものです。ディジタル通信でも、送った「0」が「1」として受信されたり、その逆が起きたりします。BER は、この「聞き間違い」が全体のどれくらいの割合で発生するかを表す数値です。
数学的定義
BER は、送信されたビット数に対する誤ったビット数の比率として定義されます。
$$ \text{BER} = \frac{\text{誤りビット数}}{\text{総送信ビット数}} = \frac{N_{\text{error}}}{N_{\text{total}}} $$
たとえば100万ビットを送信して10ビットが誤った場合、$\text{BER} = 10 / 10^6 = 10^{-5}$ です。
通信品質の目安
BER の値は用途によって要求水準が大きく異なります。
| 用途 | 要求BER | 備考 |
|---|---|---|
| 音声通話 | $10^{-3}$ | 多少の誤りは音質劣化として許容 |
| データ通信 | $10^{-6}$ | 再送制御(ARQ)併用が一般的 |
| 光ファイバー通信 | $10^{-9}$ | FEC(前方誤り訂正)適用後の要求 |
| 宇宙探査データ | $10^{-5}$ | 強力な誤り訂正符号を適用 |
BER は通信システムの「成績表」のようなもので、変調方式、符号化方式、チャネル条件のすべてが最終的にこの1つの数値に集約されます。
ここまでで BER という指標の意味がわかりました。BER を理論的に計算するには、まず通信路で何が起きているかを数学的にモデル化する必要があります。次に、最も基本的な通信路モデルである AWGN チャネルを定式化しましょう。
AWGNチャネルモデル — ディジタル通信の基本舞台
なぜAWGNチャネルか
実際の通信路では、フェージング、マルチパス、干渉など多くの劣化要因がありますが、全ての通信路解析の出発点となるのが AWGN(Additive White Gaussian Noise:加法性白色ガウス雑音)チャネル です。このモデルは「雑音だけが信号を劣化させる」という最もシンプルな状況を表します。現実のチャネルがどれほど複雑でも、最終的には「等価的にどのくらいの AWGN に相当するか」という視点で性能を評価することが多いため、AWGN チャネルの解析は全ての基盤となります。
数学的モデル
送信信号 $s(t)$ が AWGN チャネルを通過すると、受信信号は
$$ r(t) = s(t) + n(t) $$
となります。ここで $n(t)$ は以下の性質を持つ雑音過程です。
加法性(Additive): 雑音が信号に「足される」形で混入します。乗算的な劣化(フェージングなど)はこのモデルには含まれません。
白色(White): 電力スペクトル密度が全周波数で一定です。
$$ S_n(f) = \frac{N_0}{2} \quad [\text{W/Hz}] $$
ここで $N_0$ は片側雑音電力スペクトル密度です。「白色」の名前は、すべての周波数成分を均等に含む白色光のアナロジーに由来します。
ガウス(Gaussian): 任意の時刻で $n(t)$ の振幅が平均ゼロ、分散 $\sigma^2$ の正規分布に従います。
$$ n(t) \sim \mathcal{N}(0, \sigma^2) $$
$E_b/N_0$ — ディジタル通信の正規化SNR
アナログ通信では SNR(信号対雑音比)を使いますが、ディジタル通信では 1ビットあたりのエネルギー $E_b$ と 雑音電力スペクトル密度 $N_0$ の比を使うのが標準的です。
$$ \frac{E_b}{N_0} = \frac{S \cdot T_b}{N_0} = \frac{S}{N_0 R_b} $$
ここで $S$ は受信信号電力、$T_b$ はビット周期、$R_b = 1/T_b$ はビットレートです。$E_b/N_0$ は変調方式やビットレートに依存しない正規化された SNR であり、異なる変調方式を公平に比較するための共通の物差しとなります。
$E_b/N_0$ とシンボルあたりのエネルギー $E_s$ の関係も重要です。1シンボルが $\log_2 M$ ビットを運ぶ $M$ 値変調では
$$ E_s = E_b \cdot \log_2 M $$
が成り立ちます。たとえば QPSK($M = 4$)では $E_s = 2 E_b$、16-QAM($M = 16$)では $E_s = 4 E_b$ です。
AWGN チャネルモデルと $E_b/N_0$ の定義が揃いました。BER を計算するためにもう1つ必要な数学的道具があります。それが誤り確率を表現する Q 関数です。
Q関数と相補誤差関数 — 誤り確率の数学的道具
Q関数の直感的な意味
ガウス分布に従う雑音が、ある閾値を超える確率を求めたい — これが BER 計算の本質です。Q 関数はまさにこの「正規分布の裾の面積」を返す関数です。
日常的なアナロジーで言えば、Q 関数は「テストの得点が平均から何標準偏差以上離れている人の割合」に相当します。平均から 1 標準偏差以上高い得点の人は約 15.9%、2 標準偏差以上は約 2.3%、3 標準偏差以上は約 0.13% です。通信における BER 計算も、雑音が信号間距離の半分を超えて判定境界を越える確率を求めているのです。
Q関数の定義
Q 関数は標準正規分布(平均0、分散1)の上側累積分布関数として定義されます。
$$ Q(x) = \frac{1}{\sqrt{2\pi}} \int_x^{\infty} \exp\left(-\frac{t^2}{2}\right) dt $$
$Q(x)$ は「標準正規確率変数が $x$ 以上の値を取る確率」です。$x$ が大きくなるほど $Q(x)$ は急速にゼロに近づきます。
いくつかの代表的な値を確認しておきましょう。
| $x$ | $Q(x)$ |
|---|---|
| 0 | 0.5 |
| 1 | 0.1587 |
| 2 | 0.02275 |
| 3 | $1.350 \times 10^{-3}$ |
| 4 | $3.167 \times 10^{-5}$ |
| 5 | $2.867 \times 10^{-7}$ |
$x$ が 1 増えるごとに $Q(x)$ はおよそ1桁以上小さくなります。この急激な減衰が、ディジタル通信で SNR をわずかに改善するだけで BER が劇的に下がる理由です。
相補誤差関数との関係
Pythonの scipy.special.erfc で簡単に計算できる相補誤差関数 $\text{erfc}(x)$ は、Q 関数と次の関係にあります。
$$ Q(x) = \frac{1}{2} \text{erfc}\left(\frac{x}{\sqrt{2}}\right) $$
逆に書くと
$$ \text{erfc}(x) = 2Q(\sqrt{2} \, x) $$
です。$\text{erfc}(x)$ の定義は
$$ \text{erfc}(x) = \frac{2}{\sqrt{\pi}} \int_x^{\infty} \exp(-t^2) \, dt $$
であり、積分の中の指数関数の形が $Q$ 関数とわずかに異なります($-t^2$ vs. $-t^2/2$)。この違いは変数変換 $t \to t/\sqrt{2}$ で吸収されます。
具体的に確認してみましょう。$Q$ 関数の定義で $u = t/\sqrt{2}$ と置換すると、$dt = \sqrt{2} \, du$ であり、$t = x$ のとき $u = x/\sqrt{2}$ なので
$$ Q(x) = \frac{1}{\sqrt{2\pi}} \int_{x/\sqrt{2}}^{\infty} e^{-u^2} \sqrt{2} \, du = \frac{1}{\sqrt{\pi}} \int_{x/\sqrt{2}}^{\infty} e^{-u^2} \, du = \frac{1}{2} \text{erfc}\left(\frac{x}{\sqrt{2}}\right) $$
が得られます。
BER計算での使い方
BER を計算するとき、典型的には次のような式が現れます。
$$ \text{BER} = Q\left(\sqrt{2 \frac{E_b}{N_0}}\right) = \frac{1}{2} \text{erfc}\left(\sqrt{\frac{E_b}{N_0}}\right) $$
この式の物理的意味は、「ガウス雑音が信号間距離の半分を超えて判定境界の反対側に達する確率」です。$E_b/N_0$ が大きいほど(信号が雑音に対して強いほど)、この確率は指数関数的に小さくなります。
Q 関数という数学的道具が揃ったところで、いよいよ具体的な変調方式の BER を導出していきます。最も基本的な BPSK から始めましょう。
BPSKのBER導出
BPSK復調のモデル
BPSK(Binary Phase Shift Keying)は、0 と 1 のビットをそれぞれ位相 0 と位相 $\pi$ の搬送波に対応させる、最もシンプルな変調方式です。まず、なぜ BPSK が BER 解析の出発点として理想的なのかを考えましょう。BPSK は信号空間(constellation)上で2つの信号点が原点を挟んで対称に配置される1次元の変調であり、BER 計算が1次元の確率問題に帰着するからです。
信号空間上で、ビット「1」の送信信号点は $+\sqrt{E_b}$、ビット「0」の送信信号点は $-\sqrt{E_b}$ に配置されます。2つの信号点間のユークリッド距離は $2\sqrt{E_b}$ です。
AWGN チャネルを通過後、マッチドフィルタ(整合フィルタ)の出力は
$$ r = s + n $$
で与えられます。ここで $s = \pm\sqrt{E_b}$(送信信号に対応)、$n$ はマッチドフィルタ出力での雑音で $n \sim \mathcal{N}(0, N_0/2)$ です。
マッチドフィルタ出力で雑音の分散が $N_0/2$ になる理由を確認しておきましょう。マッチドフィルタは送信パルスの時間反転複素共役を受信信号に畳み込む操作です。フィルタ出力の雑音分散は
$$ \sigma_n^2 = \frac{N_0}{2} \int_{-\infty}^{\infty} |h(t)|^2 \, dt = \frac{N_0}{2} \cdot 1 = \frac{N_0}{2} $$
となります。ここでフィルタのエネルギーを1に正規化しています(信号エネルギー $E_b$ はフィルタ出力の信号成分に反映されます)。
判定規則と誤り確率の導出
受信側では、マッチドフィルタ出力 $r$ の符号で判定します。$r > 0$ ならビット「1」、$r < 0$ ならビット「0」と判定します。判定境界は $r = 0$ です。
ビット誤りが起きるのは、送信が $+\sqrt{E_b}$ なのに $r < 0$ となる場合、もしくは送信が $-\sqrt{E_b}$ なのに $r > 0$ となる場合です。対称性から、どちらの場合も誤り確率は同じです。
$s = +\sqrt{E_b}$ を送信した場合を考えます。誤りは $r = \sqrt{E_b} + n < 0$、すなわち $n < -\sqrt{E_b}$ のときに発生します。
$$ P_e = P(n < -\sqrt{E_b}) $$
$n \sim \mathcal{N}(0, N_0/2)$ なので、標準正規分布に変換します。$z = n / \sqrt{N_0/2}$ とおくと $z \sim \mathcal{N}(0, 1)$ であり、条件 $n < -\sqrt{E_b}$ は $z < -\sqrt{E_b} / \sqrt{N_0/2} = -\sqrt{2E_b/N_0}$ と等価です。
$$ P_e = P\left(z < -\sqrt{\frac{2E_b}{N_0}}\right) $$
標準正規分布の対称性($P(z < -x) = P(z > x) = Q(x)$)を使うと
$$ P_e = Q\left(\sqrt{\frac{2E_b}{N_0}}\right) $$
が得られます。Q 関数と erfc の関係式を適用すると
$$ \boxed{P_{e,\text{BPSK}} = Q\left(\sqrt{\frac{2E_b}{N_0}}\right) = \frac{1}{2} \text{erfc}\left(\sqrt{\frac{E_b}{N_0}}\right)} $$
これが BPSK の BER の理論式です。この式は AWGN チャネルにおける BPSK の最適受信(マッチドフィルタ受信)の性能を表す、ディジタル通信の最も基本的な結果の1つです。
結果の物理的解釈
導出された式からいくつかの重要な洞察が得られます。
$E_b/N_0$ が 1(0 dB)のとき、$P_e = Q(\sqrt{2}) \approx 0.0786$、すなわち約 7.9% のビットが誤ります。$E_b/N_0$ が 10(10 dB)のとき、$P_e = Q(\sqrt{20}) \approx 3.9 \times 10^{-6}$ まで下がります。$E_b/N_0$ を 0 dB から 10 dB に上げるだけで、BER は 4 桁以上改善されます。この急激な改善は Q 関数の指数関数的な減衰によるもので、「あと少し SNR を上げれば劇的に性能が良くなる」というディジタル通信特有の閾値効果を生み出しています。
BPSK は1シンボルに1ビットしか運べないため、帯域効率は 1 bit/s/Hz です。帯域効率を2倍にしつつ同じ BER 性能を維持できる方式はないでしょうか? 実は QPSK がまさにその答えです。
QPSKのBER導出
QPSKの信号空間
QPSK(Quadrature Phase Shift Keying)は、搬送波の位相を4つの値 $\{0, \pi/2, \pi, 3\pi/2\}$(もしくは $\{\pi/4, 3\pi/4, 5\pi/4, 7\pi/4\}$)に切り替える変調方式です。1シンボルで2ビットを運ぶため、帯域効率は 2 bit/s/Hz と BPSK の2倍です。
ここで重要な洞察があります。QPSK は、I チャネル(同相成分)と Q チャネル(直交成分)にそれぞれ独立な BPSK 信号を載せた方式と見なせます。信号空間上で見ると、QPSK の4つの信号点は
$$ s_m = \left(\pm\sqrt{\frac{E_s}{2}}, \, \pm\sqrt{\frac{E_s}{2}}\right), \quad m = 0, 1, 2, 3 $$
のように配置されます。ここで $E_s$ はシンボルエネルギーです。
BER の導出
QPSK のシンボルエネルギーとビットエネルギーの関係は $E_s = 2E_b$ です。I 軸方向の信号点間距離は $2\sqrt{E_s/2} = 2\sqrt{E_b}$ であり、これは BPSK の信号点間距離 $2\sqrt{E_b}$ と同じです。
グレイ符号化(隣接信号点が1ビットだけ異なるようにビットを割り当てる方法)を用いた QPSK では、I チャネルの判定は第1ビット、Q チャネルの判定は第2ビットにそれぞれ対応します。I チャネルと Q チャネルは直交しているため、雑音も独立であり、各チャネルの誤り確率は独立に計算できます。
I チャネルについて、信号成分は $\pm\sqrt{E_b}$、雑音は $n_I \sim \mathcal{N}(0, N_0/2)$ です。これは BPSK とまったく同じ状況なので
$$ P_{e,I} = Q\left(\sqrt{\frac{2E_b}{N_0}}\right) $$
Q チャネルも対称性から同じ式になります。ビットの誤りは I チャネルまたは Q チャネルの独立な判定で生じるため、全体のビット誤り率は
$$ \boxed{P_{e,\text{QPSK}} = Q\left(\sqrt{\frac{2E_b}{N_0}}\right) = \frac{1}{2} \text{erfc}\left(\sqrt{\frac{E_b}{N_0}}\right)} $$
となります。驚くべきことに、QPSK の BER は BPSK と 完全に同一 です。帯域効率が2倍に向上しているにもかかわらず、ビットあたりの誤り率は変わりません。これは、シンボルエネルギー $E_s = 2E_b$ を I/Q の2チャネルに均等に分配するため、各チャネルが BPSK と等価になるという構造から来ています。
ただし、$E_s/N_0$ で比較すると話は異なります。同じ $E_s/N_0$ では QPSK のほうが BPSK より 3 dB 不利です($E_b = E_s/2$ なので $E_b/N_0$ が 3 dB 小さくなるため)。つまり QPSK は「帯域効率と電力効率のトレードオフ」においてBPSKと等価な位置にある方式です。
BPSK と QPSK では、信号点の数が限られているため BER を厳密に導出できました。しかし、さらに高い帯域効率が必要な場面では、より多くの信号点を持つ QAM が使われます。次に、M-QAM の BER を求めてみましょう。
M-QAMのBER近似式
M-QAMの信号配置
M-QAM(M-ary Quadrature Amplitude Modulation)は、I-Q 平面上に $M$ 個の信号点を格子状に配置する方式です。$M = 4$ が QPSK に相当し、$M = 16, 64, 256, \dots$ と信号点を増やすことで、1シンボルあたり $\log_2 M$ ビットを運べます。
矩形 QAM($M = L^2$, $L = \sqrt{M}$)を考えます。各信号点は
$$ s_{ij} = \left((2i – 1 – L)d, \, (2j – 1 – L)d\right), \quad i, j = 1, 2, \dots, L $$
のように配置されます。ここで $2d$ は隣接信号点間の距離であり、$d$ は以下の平均シンボルエネルギーの条件から決まります。
平均シンボルエネルギーを $E_s$ と表すと、
$$ E_s = \frac{2(M-1)}{3} d^2 $$
が成り立ちます。この式を $d$ について解くと
$$ d = \sqrt{\frac{3E_s}{2(M-1)}} $$
を得ます。$E_s = E_b \log_2 M$ の関係を使うと
$$ d = \sqrt{\frac{3 E_b \log_2 M}{2(M-1)}} $$
です。
シンボル誤り率の導出
$L \times L$ の格子において、信号点の位置によって隣接する信号点の数が異なります。角の信号点は2つ、辺上の信号点は3つ、内部の信号点は4つの隣接点を持ちます。
各方向(I 軸または Q 軸)について、1次元の誤り確率は
$$ P_{\sqrt{M}} = 2\left(1 – \frac{1}{\sqrt{M}}\right) Q\left(\frac{2d}{\sqrt{N_0}}\right) $$
で与えられます。この式の由来は次の通りです。$\sqrt{M}$ 値 PAM の最外側の点は片側にしか誤る方向がないため、係数 $(1 – 1/\sqrt{M})$ は「両側に誤り得る点の割合」を反映しています。$2d$ は隣接信号点間距離、$\sqrt{N_0}$ は $\sqrt{N_0/2 \cdot 2} = \sqrt{N_0}$ から来ます(各次元の雑音分散 $N_0/2$ と判定閾値の関係)。
I 軸と Q 軸の判定は独立なので、シンボル誤り率は
$$ P_{s,M\text{-QAM}} = 1 – (1 – P_{\sqrt{M}})^2 $$
これを展開すると
$$ P_{s,M\text{-QAM}} = 2P_{\sqrt{M}} – P_{\sqrt{M}}^2 \approx 2P_{\sqrt{M}} \quad (\text{高SNRでは } P_{\sqrt{M}} \ll 1) $$
と近似できます。
BERへの変換
グレイ符号化を用いた場合、シンボル誤りの大部分は隣接信号点への誤りであり、1シンボル誤りあたり1ビットだけが誤ります。したがって、BER とシンボル誤り率の近似的な関係は
$$ \text{BER} \approx \frac{P_s}{\log_2 M} $$
となります。具体的に $d$ の式を代入して整理すると
$$ \boxed{P_{e, M\text{-QAM}} \approx \frac{4}{\log_2 M}\left(1 – \frac{1}{\sqrt{M}}\right) Q\left(\sqrt{\frac{3 \log_2 M}{M-1} \cdot \frac{2E_b}{N_0}}\right)} $$
が得られます。この近似式はグレイ符号化と高 SNR の仮定のもとで精度良く成り立ちます。
具体的なBER式
主要な QAM のBER式を整理しておきます。
16-QAM ($M = 16$, $\log_2 M = 4$):
$$ P_{e, 16\text{-QAM}} \approx \frac{3}{4} Q\left(\sqrt{\frac{4}{5} \cdot \frac{2E_b}{N_0}}\right) $$
64-QAM ($M = 64$, $\log_2 M = 6$):
$$ P_{e, 64\text{-QAM}} \approx \frac{7}{12} Q\left(\sqrt{\frac{2}{7} \cdot \frac{2E_b}{N_0}}\right) $$
256-QAM ($M = 256$, $\log_2 M = 8$):
$$ P_{e, 256\text{-QAM}} \approx \frac{15}{32} Q\left(\sqrt{\frac{8}{85} \cdot \frac{2E_b}{N_0}}\right) $$
$M$ が増えるほど、Q 関数の引数が小さくなる(信号点間距離が相対的に縮む)ため、同じ BER を達成するために必要な $E_b/N_0$ が増加します。これが「帯域効率と電力効率のトレードオフ」の定量的な表現です。16-QAM は QPSK に比べて帯域効率が2倍ですが、同じ BER を達成するために約 4 dB 多くの $E_b/N_0$ が必要になります。
QAM と並んで基本的な変調方式である ASK と FSK のBERも重要です。次にこれらの方式の BER を導出しましょう。
ASK/FSKのBER導出
BASK(OOK)のBER
BASK(Binary Amplitude Shift Keying)、特にOOK(On-Off Keying)は最もシンプルな振幅変調で、ビット「1」のときに搬送波を送信し、ビット「0」のときは何も送信しません。信号空間上では、2つの信号点は $0$ と $\sqrt{2E_b}$(平均エネルギーが $E_b$ になるように正規化)に配置されます。
信号点間距離は $\sqrt{2E_b}$ であり、BPSK の $2\sqrt{E_b}$ と比較すると $\sqrt{2}$ 倍だけ短くなっています。判定境界は信号点の中点 $\sqrt{E_b/2}$ に置きます。
マッチドフィルタ出力の分布は、ビット「1」のとき $r \sim \mathcal{N}(\sqrt{2E_b}, N_0/2)$、ビット「0」のとき $r \sim \mathcal{N}(0, N_0/2)$ です。ビット「0」を送信した場合の誤り確率を計算します。$r > \sqrt{E_b/2}$ となるとき誤りが発生します。
$$ P(r > \sqrt{E_b/2} \mid s = 0) = Q\left(\frac{\sqrt{E_b/2}}{\sqrt{N_0/2}}\right) = Q\left(\sqrt{\frac{E_b}{N_0}}\right) $$
対称性から、ビット「1」の場合も同じ誤り確率なので
$$ \boxed{P_{e, \text{BASK}} = Q\left(\sqrt{\frac{E_b}{N_0}}\right) = \frac{1}{2}\text{erfc}\left(\sqrt{\frac{E_b}{2N_0}}\right)} $$
BPSK の BER $Q(\sqrt{2E_b/N_0})$ と比較すると、Q 関数の引数が $\sqrt{2}$ 倍小さいため、同じ $E_b/N_0$ で BASK は BPSK より 3 dB 劣ります。これは信号点間距離が BPSK より短いことの直接的な帰結です。
同期検波FSKのBER
BFSK(Binary Frequency Shift Keying)では、ビット「1」と「0」をそれぞれ異なる周波数 $f_1$, $f_0$ の搬送波に対応させます。BER は2つの搬送波の直交性によって異なります。
直交FSK($|f_1 – f_0| = 1/(2T_b)$ 以上)の同期検波:
2つの周波数が直交している場合、受信機は2つのマッチドフィルタの出力 $r_1$, $r_0$ を比較し、大きいほうの周波数を選択します。
ビット「1」(周波数 $f_1$)を送信した場合を考えます。
$$ r_1 = \sqrt{E_b} + n_1, \quad r_0 = n_0 $$
ここで $n_1, n_0 \sim \mathcal{N}(0, N_0/2)$ は独立です。誤り確率は $r_0 > r_1$、すなわち $n_0 – n_1 > \sqrt{E_b}$ の確率です。
$n_0 – n_1$ は平均ゼロ、分散 $N_0$ のガウス確率変数なので
$$ P_e = Q\left(\frac{\sqrt{E_b}}{\sqrt{N_0}}\right) = Q\left(\sqrt{\frac{E_b}{N_0}}\right) $$
つまり、同期検波の直交 BFSK は BASK(OOK)と同じ BER を持ちます。
$$ \boxed{P_{e, \text{BFSK(coherent)}} = Q\left(\sqrt{\frac{E_b}{N_0}}\right) = \frac{1}{2}\text{erfc}\left(\sqrt{\frac{E_b}{2N_0}}\right)} $$
非同期検波FSKのBER
実際の通信システムでは、受信機が搬送波の正確な位相を追跡できない場合があります。このとき包絡線検波(非同期検波) が用いられます。
非同期検波では、2つの周波数それぞれの包絡線(振幅)を比較して判定します。包絡線は雑音を含むため、ライス分布(信号あり)とレイリー分布(信号なし)に従います。
詳細な導出を省略して結果を示すと、非同期検波の直交 BFSK のBERは
$$ \boxed{P_{e, \text{BFSK(noncoherent)}} = \frac{1}{2} \exp\left(-\frac{E_b}{2N_0}\right)} $$
となります。この式は Q 関数ではなく指数関数で表されている点が特徴的です。高 SNR 領域では同期検波よりも 1 dB 弱劣りますが、位相追跡が不要であるという実装上の大きなメリットがあります。
非直交FSKのBER
2つの周波数が直交していない場合($|f_1 – f_0| < 1/(2T_b)$)、2つの信号間の相関 $\rho$($0 < \rho < 1$)が残ります。同期検波の BER は
$$ P_{e, \text{FSK(non-orth)}} = Q\left(\sqrt{\frac{(1-\rho)E_b}{N_0}}\right) $$
となります。$\rho = 0$(直交)のとき先ほどの結果に一致し、$\rho \to 1$(ほぼ同じ周波数)のとき BER は 0.5 に近づく(判別不能)ことが確認できます。
各変調方式の BER が出揃いました。これらの結果を横断的に比較すると、非常に重要なパターンが見えてきます。次に、すべての変調方式を1つのグラフ上で比較するウォーターフォールカーブを見ていきましょう。
ウォーターフォールカーブの物理的意味
ウォーターフォールカーブとは
BER を $E_b/N_0$(dBスケール)に対して対数軸でプロットすると、特徴的な右下がりの曲線が現れます。この曲線は、まるで滝が流れ落ちるように急激に BER が低下することから ウォーターフォールカーブ(waterfall curve) と呼ばれます。
この急峻な傾斜は、Q 関数(またはerfc)の引数が $\sqrt{E_b/N_0}$ に比例しているためです。dB スケールで $E_b/N_0$ が線形に増加すると、Q 関数の値は指数関数的に(より正確にはガウス関数的に)減少します。これは対数スケールの BER 軸上では、ほぼ直線的な降下として現れます。
BER曲線から読み取れる情報
BER 曲線の比較から、変調方式の性能を多面的に評価できます。
水平方向のずれ($E_b/N_0$ の差): 同じ BER を達成するために必要な $E_b/N_0$ の差をデシベルで読み取ります。たとえば BPSK が BER $= 10^{-5}$ を達成するのに 9.6 dB 必要で、BASK が 12.6 dB 必要なら、BASK は BPSK より 3 dB 劣る、と表現します。
曲線の傾き: 傾きが急なほど、$E_b/N_0$ の変化に対して BER が敏感です。AWGN チャネルでは各方式のウォーターフォール曲線の傾きはほぼ同じです(いずれも Q 関数の減衰特性に支配されるため)。しかし、フェージングチャネルでは傾きが緩やかになり、ダイバーシティを適用すると再び急峻になります。
「膝」の位置: BER がほぼ 0.5(ランダム推測)から急降下し始める $E_b/N_0$ の値です。この点が実効的な「通信が成立し始める閾値」に対応します。
各変調方式の比較まとめ
ここまで導出した各方式のBER式を整理します。
| 変調方式 | BER式 | BER $= 10^{-5}$ に必要な $E_b/N_0$ |
|---|---|---|
| BPSK | $Q(\sqrt{2E_b/N_0})$ | 9.6 dB |
| QPSK | $Q(\sqrt{2E_b/N_0})$ | 9.6 dB |
| BASK(OOK) | $Q(\sqrt{E_b/N_0})$ | 12.6 dB |
| BFSK(同期) | $Q(\sqrt{E_b/N_0})$ | 12.6 dB |
| BFSK(非同期) | $\frac{1}{2}e^{-E_b/(2N_0)}$ | 13.4 dB |
| 16-QAM | $\frac{3}{4}Q(\sqrt{\frac{4}{5} \cdot \frac{2E_b}{N_0}})$ | 13.5 dB |
| 64-QAM | $\frac{7}{12}Q(\sqrt{\frac{2}{7} \cdot \frac{2E_b}{N_0}})$ | 17.8 dB |
BPSK/QPSK は最も電力効率の良い方式であり、M-QAM は帯域効率を高める代わりに電力効率を犠牲にしています。BASK/BFSK は実装がシンプルですが、BPSK/QPSK より 3 dB 劣ります。
理論式の導出が一通り完了しました。ここからは Python を使って、理論曲線とモンテカルロシミュレーション結果を重ね合わせ、導出した式が正しいことを確認していきましょう。
Pythonでの実装 — BERシミュレーション vs 理論曲線
全方式の理論曲線をプロット
まず、導出した理論式を使って各変調方式のBER曲線を描画します。
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import erfc
# Eb/N0の範囲 (dB)
eb_n0_db = np.linspace(0, 20, 500)
eb_n0_lin = 10 ** (eb_n0_db / 10)
# Q関数の定義
def Q(x):
return 0.5 * erfc(x / np.sqrt(2))
# 各変調方式のBER理論値
ber_bpsk = Q(np.sqrt(2 * eb_n0_lin))
ber_bask = Q(np.sqrt(eb_n0_lin))
ber_bfsk_coh = Q(np.sqrt(eb_n0_lin))
ber_bfsk_noncoh = 0.5 * np.exp(-eb_n0_lin / 2)
ber_16qam = (3/4) * Q(np.sqrt((4/5) * 2 * eb_n0_lin))
ber_64qam = (7/12) * Q(np.sqrt((2/7) * 2 * eb_n0_lin))
ber_256qam = (15/32) * Q(np.sqrt((8/85) * 2 * eb_n0_lin))
# プロット
plt.figure(figsize=(10, 7))
plt.semilogy(eb_n0_db, ber_bpsk, 'b-', linewidth=2, label='BPSK / QPSK')
plt.semilogy(eb_n0_db, ber_bask, 'r-', linewidth=2, label='BASK (OOK)')
plt.semilogy(eb_n0_db, ber_bfsk_coh, 'r--', linewidth=2, label='BFSK (coherent)')
plt.semilogy(eb_n0_db, ber_bfsk_noncoh, 'm-', linewidth=2, label='BFSK (noncoherent)')
plt.semilogy(eb_n0_db, ber_16qam, 'g-', linewidth=2, label='16-QAM')
plt.semilogy(eb_n0_db, ber_64qam, 'c-', linewidth=2, label='64-QAM')
plt.semilogy(eb_n0_db, ber_256qam, 'k-', linewidth=2, label='256-QAM')
plt.xlabel('$E_b/N_0$ [dB]', fontsize=12)
plt.ylabel('BER', fontsize=12)
plt.title('BER vs $E_b/N_0$ - Theoretical Curves for Various Modulations', fontsize=13)
plt.legend(fontsize=10, loc='lower left')
plt.grid(True, which='both', alpha=0.3)
plt.xlim(0, 20)
plt.ylim(1e-7, 1)
plt.tight_layout()
plt.savefig('ber_theoretical_curves.png', dpi=150, bbox_inches='tight')
plt.show()
このグラフから、各変調方式の性能差が視覚的に明確になります。BPSK/QPSK(青線)が最も左側に位置し、最小の $E_b/N_0$ で低い BER を達成できることがわかります。BASK と同期 BFSK(赤線)は 3 dB 右にシフトし、非同期 BFSK(紫線)はさらにわずかに右側です。QAM は $M$ が増えるにつれて右にシフトし、256-QAM は BPSK/QPSK に比べて約 9 dB 余計に $E_b/N_0$ が必要です。しかし 256-QAM は1シンボルに8ビットを載せる高い帯域効率を持っており、帯域幅が限られた環境では不可欠な方式です。
BPSKのモンテカルロシミュレーション
理論曲線が本当に正しいか、モンテカルロシミュレーションで検証しましょう。まず BPSK から始めます。
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import erfc
def Q(x):
return 0.5 * erfc(x / np.sqrt(2))
def simulate_bpsk_ber(eb_n0_db_range, n_bits=500000):
"""BPSKのBERをモンテカルロシミュレーションで計算"""
ber_sim = []
for eb_n0_db in eb_n0_db_range:
eb_n0 = 10 ** (eb_n0_db / 10)
# 送信ビット: {0, 1} -> BPSK信号: {-1, +1}
bits = np.random.randint(0, 2, n_bits)
symbols = 2 * bits - 1 # 0 -> -1, 1 -> +1
# AWGN: 分散 = N0/2 = 1/(2*Eb/N0) (Eb=1に正規化)
noise_std = 1.0 / np.sqrt(2 * eb_n0)
noise = noise_std * np.random.randn(n_bits)
# 受信信号
received = symbols + noise
# 判定: r > 0 -> 1, r <= 0 -> 0
detected = (received > 0).astype(int)
# BER計算
errors = np.sum(bits != detected)
ber_sim.append(errors / n_bits)
return np.array(ber_sim)
# シミュレーション実行
eb_n0_db_sim = np.arange(0, 13, 1)
ber_bpsk_sim = simulate_bpsk_ber(eb_n0_db_sim, n_bits=1000000)
# 理論曲線
eb_n0_db_theory = np.linspace(0, 12, 200)
eb_n0_lin_theory = 10 ** (eb_n0_db_theory / 10)
ber_bpsk_theory = Q(np.sqrt(2 * eb_n0_lin_theory))
# プロット
plt.figure(figsize=(9, 6))
plt.semilogy(eb_n0_db_theory, ber_bpsk_theory, 'b-', linewidth=2, label='BPSK theory')
plt.semilogy(eb_n0_db_sim, np.maximum(ber_bpsk_sim, 1e-7), 'ro', markersize=8,
label='BPSK simulation')
plt.xlabel('$E_b/N_0$ [dB]', fontsize=12)
plt.ylabel('BER', fontsize=12)
plt.title('BPSK: Theory vs Monte Carlo Simulation', fontsize=13)
plt.legend(fontsize=11)
plt.grid(True, which='both', alpha=0.3)
plt.xlim(0, 12)
plt.ylim(1e-7, 1)
plt.tight_layout()
plt.savefig('ber_bpsk_verification.png', dpi=150, bbox_inches='tight')
plt.show()
シミュレーション結果(赤丸)が理論曲線(青線)と高精度に一致していることが確認できます。$E_b/N_0 = 0$ dB 付近では BER が約 0.08、$E_b/N_0 = 10$ dB 付近では BER が $10^{-5}$ 台まで下がっており、Q 関数の急激な減衰特性が実際のシミュレーションでも再現されています。低 BER 領域($10^{-6}$ 以下)では、シミュレーションのビット数が有限であるため統計的な揺らぎが大きくなりますが、十分なビット数を使えば理論値に収束することが確認できます。
M-QAMのモンテカルロシミュレーション
次に、16-QAM と 64-QAM のシミュレーションを行い、近似式の精度を検証します。
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import erfc
def Q(x):
return 0.5 * erfc(x / np.sqrt(2))
def simulate_mqam_ber(M, eb_n0_db_range, n_symbols=500000):
"""M-QAMのBERをモンテカルロシミュレーションで計算(グレイ符号化)"""
L = int(np.sqrt(M))
k = int(np.log2(M)) # ビット数/シンボル
ber_sim = []
for eb_n0_db in eb_n0_db_range:
eb_n0 = 10 ** (eb_n0_db / 10)
es_n0 = eb_n0 * k # シンボルエネルギー/雑音
# コンスタレーション点の生成 (PAMレベル: -(L-1), -(L-3), ..., (L-3), (L-1))
levels = np.arange(-(L-1), L, 2)
# 平均電力の正規化
avg_power = np.mean(levels**2) # 各次元の平均パワー
# 全体の平均シンボルエネルギー = 2 * avg_power * scale^2 = 1 にする
scale = np.sqrt(es_n0 / (2 * avg_power))
# 送信シンボル生成
bits_i = np.random.randint(0, L, n_symbols)
bits_q = np.random.randint(0, L, n_symbols)
tx_i = levels[bits_i] * scale
tx_q = levels[bits_q] * scale
# AWGN
noise_std = 1.0 / np.sqrt(2)
noise_i = noise_std * np.random.randn(n_symbols)
noise_q = noise_std * np.random.randn(n_symbols)
rx_i = tx_i + noise_i
rx_q = tx_q + noise_q
# 判定: 最近傍点を選択
det_i = np.clip(np.round((rx_i / scale + (L-1)) / 2), 0, L-1).astype(int)
det_q = np.clip(np.round((rx_q / scale + (L-1)) / 2), 0, L-1).astype(int)
# グレイ符号化のビットマッピング
def gray_code(n):
return n ^ (n >> 1)
gray_table = np.array([gray_code(i) for i in range(L)])
# ビット誤り数の計算
errors = 0
for s in range(n_symbols):
tx_gray_i = gray_table[bits_i[s]]
rx_gray_i = gray_table[det_i[s]]
tx_gray_q = gray_table[bits_q[s]]
rx_gray_q = gray_table[det_q[s]]
errors += bin(tx_gray_i ^ rx_gray_i).count('1')
errors += bin(tx_gray_q ^ rx_gray_q).count('1')
total_bits = n_symbols * k
ber_sim.append(errors / total_bits)
return np.array(ber_sim)
# シミュレーション
eb_n0_db_sim = np.arange(0, 22, 1)
ber_16qam_sim = simulate_mqam_ber(16, eb_n0_db_sim, n_symbols=300000)
ber_64qam_sim = simulate_mqam_ber(64, eb_n0_db_sim, n_symbols=300000)
# 理論曲線
eb_n0_db_th = np.linspace(0, 22, 300)
eb_n0_lin_th = 10 ** (eb_n0_db_th / 10)
ber_bpsk_th = Q(np.sqrt(2 * eb_n0_lin_th))
ber_16qam_th = (3/4) * Q(np.sqrt((4/5) * 2 * eb_n0_lin_th))
ber_64qam_th = (7/12) * Q(np.sqrt((2/7) * 2 * eb_n0_lin_th))
plt.figure(figsize=(10, 7))
plt.semilogy(eb_n0_db_th, ber_bpsk_th, 'b-', linewidth=2, label='BPSK/QPSK (theory)')
plt.semilogy(eb_n0_db_th, ber_16qam_th, 'g-', linewidth=2, label='16-QAM (theory)')
plt.semilogy(eb_n0_db_th, ber_64qam_th, 'r-', linewidth=2, label='64-QAM (theory)')
plt.semilogy(eb_n0_db_sim, np.maximum(ber_16qam_sim, 1e-7), 'g^', markersize=7,
label='16-QAM (sim)')
plt.semilogy(eb_n0_db_sim, np.maximum(ber_64qam_sim, 1e-7), 'rs', markersize=6,
label='64-QAM (sim)')
plt.xlabel('$E_b/N_0$ [dB]', fontsize=12)
plt.ylabel('BER', fontsize=12)
plt.title('M-QAM: Theory vs Monte Carlo Simulation', fontsize=13)
plt.legend(fontsize=10)
plt.grid(True, which='both', alpha=0.3)
plt.xlim(0, 22)
plt.ylim(1e-7, 1)
plt.tight_layout()
plt.savefig('ber_mqam_verification.png', dpi=150, bbox_inches='tight')
plt.show()
16-QAM と 64-QAM の両方について、シミュレーション結果(マーカー)が理論近似曲線(実線)と非常に良く一致しています。特に BER $> 10^{-5}$ の範囲では、グレイ符号化を用いた近似式の精度が高いことがわかります。16-QAM は BPSK/QPSK に比べて約 4 dB 右にシフトし、64-QAM はさらに約 4 dB 右にあります。つまり $M$ を16倍(4乗)にするごとに、約 4 dB の追加電力が必要になるという傾向が確認できます。
全変調方式の比較シミュレーション
最後に、ASK と FSK も含めた包括的な比較シミュレーションを行います。
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import erfc
def Q(x):
return 0.5 * erfc(x / np.sqrt(2))
def simulate_bfsk_coherent(eb_n0_db_range, n_bits=500000):
"""同期検波直交BFSKのBERシミュレーション"""
ber_sim = []
for eb_n0_db in eb_n0_db_range:
eb_n0 = 10 ** (eb_n0_db / 10)
bits = np.random.randint(0, 2, n_bits)
# 2つの直交チャネルの出力
r1 = np.zeros(n_bits)
r0 = np.zeros(n_bits)
noise_std = 1.0 / np.sqrt(2 * eb_n0)
# ビット=1の場合: r1にsqrt(Eb)、r0にゼロ
r1[bits == 1] = 1.0 # sqrt(Eb)=1に正規化
r0[bits == 0] = 1.0
r1 += noise_std * np.random.randn(n_bits)
r0 += noise_std * np.random.randn(n_bits)
# 判定: r1 > r0 -> 1, otherwise -> 0
detected = (r1 > r0).astype(int)
errors = np.sum(bits != detected)
ber_sim.append(errors / n_bits)
return np.array(ber_sim)
def simulate_bfsk_noncoherent(eb_n0_db_range, n_bits=500000):
"""非同期検波直交BFSKのBERシミュレーション"""
ber_sim = []
for eb_n0_db in eb_n0_db_range:
eb_n0 = 10 ** (eb_n0_db / 10)
bits = np.random.randint(0, 2, n_bits)
noise_std = 1.0 / np.sqrt(2 * eb_n0)
# 各チャネルのI/Q成分
r1_i = np.zeros(n_bits)
r1_q = np.zeros(n_bits)
r0_i = np.zeros(n_bits)
r0_q = np.zeros(n_bits)
r1_i[bits == 1] = 1.0
r0_i[bits == 0] = 1.0
r1_i += noise_std * np.random.randn(n_bits)
r1_q += noise_std * np.random.randn(n_bits)
r0_i += noise_std * np.random.randn(n_bits)
r0_q += noise_std * np.random.randn(n_bits)
# 包絡線の比較
env1 = np.sqrt(r1_i**2 + r1_q**2)
env0 = np.sqrt(r0_i**2 + r0_q**2)
detected = (env1 > env0).astype(int)
errors = np.sum(bits != detected)
ber_sim.append(errors / n_bits)
return np.array(ber_sim)
def simulate_bask(eb_n0_db_range, n_bits=500000):
"""BASK (OOK)のBERシミュレーション"""
ber_sim = []
for eb_n0_db in eb_n0_db_range:
eb_n0 = 10 ** (eb_n0_db / 10)
bits = np.random.randint(0, 2, n_bits)
# OOK: bit=1 -> sqrt(2*Eb), bit=0 -> 0 (平均Eb)
symbols = bits * np.sqrt(2.0) # Eb=1正規化でsqrt(2Eb)=sqrt(2)
noise_std = 1.0 / np.sqrt(2 * eb_n0)
noise = noise_std * np.random.randn(n_bits)
received = symbols + noise
threshold = np.sqrt(2.0) / 2 # 中点
detected = (received > threshold).astype(int)
errors = np.sum(bits != detected)
ber_sim.append(errors / n_bits)
return np.array(ber_sim)
# シミュレーション実行
eb_n0_db_sim = np.arange(0, 16, 1)
ber_bask_sim = simulate_bask(eb_n0_db_sim, n_bits=800000)
ber_bfsk_coh_sim = simulate_bfsk_coherent(eb_n0_db_sim, n_bits=800000)
ber_bfsk_noncoh_sim = simulate_bfsk_noncoherent(eb_n0_db_sim, n_bits=800000)
# 理論曲線
eb_n0_db_th = np.linspace(0, 16, 300)
eb_n0_lin_th = 10 ** (eb_n0_db_th / 10)
ber_bpsk_th = Q(np.sqrt(2 * eb_n0_lin_th))
ber_bask_th = Q(np.sqrt(eb_n0_lin_th))
ber_bfsk_coh_th = Q(np.sqrt(eb_n0_lin_th))
ber_bfsk_noncoh_th = 0.5 * np.exp(-eb_n0_lin_th / 2)
plt.figure(figsize=(10, 7))
# 理論曲線
plt.semilogy(eb_n0_db_th, ber_bpsk_th, 'b-', linewidth=2, label='BPSK/QPSK (theory)')
plt.semilogy(eb_n0_db_th, ber_bask_th, 'r-', linewidth=2, label='BASK/OOK (theory)')
plt.semilogy(eb_n0_db_th, ber_bfsk_coh_th, 'g-', linewidth=2, label='BFSK coherent (theory)')
plt.semilogy(eb_n0_db_th, ber_bfsk_noncoh_th, 'm-', linewidth=2, label='BFSK noncoherent (theory)')
# シミュレーション
plt.semilogy(eb_n0_db_sim, np.maximum(ber_bask_sim, 1e-7), 'r^', markersize=7,
label='BASK (sim)')
plt.semilogy(eb_n0_db_sim, np.maximum(ber_bfsk_coh_sim, 1e-7), 'gs', markersize=6,
label='BFSK coh. (sim)')
plt.semilogy(eb_n0_db_sim, np.maximum(ber_bfsk_noncoh_sim, 1e-7), 'mD', markersize=5,
label='BFSK noncoh. (sim)')
plt.xlabel('$E_b/N_0$ [dB]', fontsize=12)
plt.ylabel('BER', fontsize=12)
plt.title('BER Comparison: ASK/FSK - Theory vs Simulation', fontsize=13)
plt.legend(fontsize=9, loc='lower left')
plt.grid(True, which='both', alpha=0.3)
plt.xlim(0, 16)
plt.ylim(1e-7, 1)
plt.tight_layout()
plt.savefig('ber_ask_fsk_comparison.png', dpi=150, bbox_inches='tight')
plt.show()
全ての変調方式について、シミュレーション結果が理論曲線と正確に一致しています。特に注目すべき点をまとめます。BASK(赤三角)と同期検波 BFSK(緑四角)は、いずれも $Q(\sqrt{E_b/N_0})$ という同じ理論式に従い、シミュレーション上でもほぼ重なっています。非同期検波 BFSK(紫ダイヤ)は同期検波より約 1 dB 劣る位置にあり、$\frac{1}{2}\exp(-E_b/(2N_0))$ の理論式と一致しています。BPSK/QPSK の理論線(青)はこれらすべてより3 dB 左に位置し、最良の電力効率を示しています。
帯域効率 vs 電力効率のトレードオフ可視化
実用的な観点から、帯域効率と電力効率のトレードオフを1枚のグラフにまとめます。
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import erfc
def Q(x):
return 0.5 * erfc(x / np.sqrt(2))
# 各方式のBER = 10^{-5}を達成する Eb/N0 を数値的に求める
target_ber = 1e-5
def find_required_ebn0(ber_func, target, search_range=(0, 30)):
"""BER関数を指定し、目標BERを達成するEb/N0 [dB]を二分探索で求める"""
lo, hi = search_range
for _ in range(100):
mid = (lo + hi) / 2
ebn0_lin = 10 ** (mid / 10)
if ber_func(ebn0_lin) > target:
lo = mid
else:
hi = mid
return (lo + hi) / 2
# BER関数の定義
ber_funcs = {
'BPSK': lambda x: Q(np.sqrt(2*x)),
'QPSK': lambda x: Q(np.sqrt(2*x)),
'BASK': lambda x: Q(np.sqrt(x)),
'BFSK\n(coherent)': lambda x: Q(np.sqrt(x)),
'BFSK\n(noncoh.)': lambda x: 0.5*np.exp(-x/2),
'16-QAM': lambda x: (3/4)*Q(np.sqrt((4/5)*2*x)),
'64-QAM': lambda x: (7/12)*Q(np.sqrt((2/7)*2*x)),
'256-QAM': lambda x: (15/32)*Q(np.sqrt((8/85)*2*x)),
}
# 帯域効率 (bit/s/Hz)
bandwidth_eff = {
'BPSK': 1.0,
'QPSK': 2.0,
'BASK': 1.0,
'BFSK\n(coherent)': 1.0,
'BFSK\n(noncoh.)': 1.0,
'16-QAM': 4.0,
'64-QAM': 6.0,
'256-QAM': 8.0,
}
# 計算
names = list(ber_funcs.keys())
ebn0_required = [find_required_ebn0(ber_funcs[n], target_ber) for n in names]
bw_effs = [bandwidth_eff[n] for n in names]
plt.figure(figsize=(10, 7))
colors = ['blue', 'blue', 'red', 'green', 'magenta', 'orange', 'cyan', 'black']
markers = ['o', 's', '^', 'D', 'v', 'p', 'h', '*']
for i, name in enumerate(names):
plt.plot(ebn0_required[i], bw_effs[i], markers[i], color=colors[i],
markersize=12, label=name, markeredgecolor='black', markeredgewidth=0.5)
# シャノン限界
ebn0_shannon = np.linspace(-1.6, 25, 200)
ebn0_lin_sh = 10 ** (ebn0_shannon / 10)
capacity = np.log2(1 + ebn0_lin_sh) # AWGN容量
plt.plot(ebn0_shannon, capacity, 'k--', linewidth=2, label='Shannon limit')
plt.xlabel('Required $E_b/N_0$ for BER = $10^{-5}$ [dB]', fontsize=12)
plt.ylabel('Bandwidth Efficiency [bit/s/Hz]', fontsize=12)
plt.title('Bandwidth Efficiency vs Power Efficiency Trade-off', fontsize=13)
plt.legend(fontsize=9, loc='upper left')
plt.grid(True, alpha=0.3)
plt.xlim(-2, 22)
plt.ylim(0, 10)
plt.tight_layout()
plt.savefig('ber_bandwidth_power_tradeoff.png', dpi=150, bbox_inches='tight')
plt.show()
このプロットは、各変調方式の「帯域効率 vs 電力効率」のトレードオフを一覧で示しています。横軸が大きいほど電力効率が悪く(多くの送信電力が必要)、縦軸が大きいほど帯域効率が良い(少ない帯域幅で多くのビットを送れる)ことを表します。黒破線のシャノン限界は、理論的にこれ以上左側には到達できない究極の境界です。全ての変調方式はシャノン限界の右側に位置しています。QPSK は帯域効率 2 bit/s/Hz を $E_b/N_0 \approx 9.6$ dB で達成し、シャノン限界からの距離が比較的小さい効率の良い方式です。一方、256-QAM は帯域効率 8 bit/s/Hz という高い値を実現しますが、$E_b/N_0 \approx 19$ dB が必要であり、電力効率の犠牲が大きいことがわかります。実際のシステム設計では、利用可能な帯域幅と送信電力の制約を考慮して、この図上の最適な動作点を選択します。
まとめ
本記事では、BER(ビット誤り率)の理論を体系的に解説しました。
- BER の定義: 送信ビット数に対する誤りビット数の比率。ディジタル通信の品質を1つの数値で表す最も基本的な指標
- AWGN チャネルと $E_b/N_0$: 全ての BER 解析の出発点。$E_b/N_0$ は変調方式に依存しない正規化された SNR として、公平な比較を可能にする
- Q 関数と erfc: $Q(x) = \frac{1}{2}\text{erfc}(x/\sqrt{2})$ の関係でつながる。ガウス雑音が判定境界を越える確率を計算する数学的道具
- BPSK/QPSK のBER: $Q(\sqrt{2E_b/N_0})$ — 最も電力効率の良い方式。QPSK は BPSK と同じ BER で帯域効率が2倍
- M-QAM のBER: $M$ が増えるほど帯域効率は向上するが、同じ BER を達成するための $E_b/N_0$ が増加する。帯域効率と電力効率のトレードオフの定量的表現
- ASK/FSK のBER: BPSK より 3 dB 劣るが実装がシンプル。非同期 FSK はさらに約 1 dB 劣るが位相追跡が不要
- ウォーターフォールカーブ: Q 関数の急激な減衰が「少しの SNR 改善で BER が劇的に下がる」閾値効果を生む
BER 解析は通信システム設計の基礎です。ここで学んだ理論曲線を基準として、誤り訂正符号(畳み込み符号、ターボ符号、LDPC符号など)の「コーディングゲイン」を評価したり、フェージングチャネルでの性能劣化を定量化したりすることができます。
次のステップとして、以下の記事も参考にしてください。