符号化利得とシャノン限界 — 誤り訂正はどこまで得をするか

土星探査機カッシーニがタイタンの画像を地球に送るとき、送信機のRF出力はわずか20 W程度しかありません。片道14億km、X帯(8.4 GHz)での自由空間損失は $20\log_{10}(4\pi d/\lambda) \approx 294$ dBにも達し、地上の巨大アンテナに届く電力はピコワットどころかその1兆分の1というオーダーになります。それでも画像は届きます。なぜでしょうか。答えの大きな一角を占めるのが誤り訂正符号です。符号を入れると、同じ画質(同じビット誤り率)を、より小さい受信電力で達成できます。この「浮いた電力」をdBで測った量が符号化利得(coding gain)です。

ここで自然な疑問が生まれます。誤り訂正はどこまで得をさせてくれるのでしょうか。パリティを増やせば増やすほど得をするなら、無限に得ができてしまいます。しかしそんなうまい話はありません。シャノンの通信路容量の式は、「どんな符号を使っても、これ以上は絶対に下げられない」という電力の絶対的な下限を与えます。二元入力の制約すら外した究極の下限が、有名な $E_b/N_0 = -1.59\ \mathrm{dB}$、いわゆるシャノン限界です。

この2つ — 「実際に得た利得」と「理論上得られる最大の利得」 — を並べて眺めると、符号化技術の歴史が一望できます。ハミング符号は約2 dB、ビタビ復号の畳み込み符号は約5 dB、ターボ符号やLDPC符号は約9 dB。そして未符号化からシャノン限界までの全予算は約11 dBです。「あと何dB残っているか」という視点は、次のような場面で直接効いてきます。

  • 衛星・深宇宙通信のリンクバジェット設計: 符号化利得を1 dB稼げれば、送信電力を約21%減らせるか、開口面積が利得に比例することからアンテナ直径を約11%小さくできます。探査機の質量予算に直結する数字です
  • 移動体通信の規格選定: 5G NRがLDPC符号とポーラー符号を、4G LTEがターボ符号を採用した背景には、「限界までの残り距離」と「復号器のスループット」のトレードオフがあります
  • ストレージ・光通信: NANDフラッシュのLDPC、400G光トランシーバの軟判定FECも、すべて「符号化利得を何dB稼げるか」で設計が評価されます

本記事の内容

  • 符号化利得の厳密な定義 — なぜ $E_s/N_0$ ではなく $E_b/N_0$ で測るのか
  • 軟判定AWGNにおける漸近符号化利得 $G_a = 10\log_{10}(r\, d_{\min})$ の、ユークリッド距離からの導出
  • 硬判定にすると $d_{\min}$ が実質 $\lfloor (d_{\min}-1)/2 \rfloor + 1$ に落ちる理由と、「2 dBの損失」の正体
  • 容量式 $C = B\log_2(1+\mathrm{SNR})$ から $E_b/N_0 \to \ln 2 = -1.59\ \mathrm{dB}$ を導く過程(1行ずつ)
  • 帯域制限つきシャノン限界と、BPSK入力に制約したときのより厳しい限界
  • Pythonでハミング符号・畳み込み符号・ターボ符号相当の性能曲線を描き、BER $=10^{-5}$ における符号化利得を数値で読み取る

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

符号化利得とは — 「同じ品質をより少ない電力で」

未符号化BPSKと畳み込み符号のBER曲線を並べ、目標BER=10^-5における横方向の距離が符号化利得であることを示した概念図

まずこの1枚で全体像をつかんでください。黒が誤り訂正なし、青が誤り訂正ありのBER曲線で、目標品質(BER $=10^{-5}$)の水平線を引いたときの横方向の距離が符号化利得です。この例では未符号化が9.59 dBを要求するのに対し符号化系は4.17 dBで済み、差の5.42 dBがまるごと送信電力の節約になります。縦方向(同じ $E_b/N_0$ でBERがどれだけ下がるか)ではなく横方向で測る、という点が符号化利得の定義の要です。

ノートPCで映画を観るとき、画質を落とさずにバッテリー消費を減らせたら嬉しいはずです。通信でも同じ発想があります。目標の通信品質(たとえばビット誤り率 BER $=10^{-5}$)を固定したまま、必要な受信電力をどれだけ下げられるか。この「下げられた分」が符号化利得です。

もう少し正確に言い直します。横軸に $E_b/N_0$(1情報ビットあたりのエネルギーと雑音電力密度の比)、縦軸にBERを対数でとった曲線を2本描きます。1本は誤り訂正を使わない未符号化(uncoded)BPSK、もう1本は符号化した系です。目標BERの水平線を引き、2本の曲線との交点の横軸の差を読むと、それが符号化利得です。

$$ \begin{equation} G(\mathrm{BER}_{\mathrm{target}}) = \left[\frac{E_b}{N_0}\right]_{\mathrm{uncoded}}^{\mathrm{dB}} – \left[\frac{E_b}{N_0}\right]_{\mathrm{coded}}^{\mathrm{dB}} \end{equation} $$

定義そのものはこれだけです。しかし、この定義には注意すべき点が3つ潜んでいます。

第一に、符号化利得は「目標BERに依存する量」です。 単一の数字ではありません。同じ符号でも、BER $=10^{-3}$ で測るか $10^{-6}$ で測るかで値が変わります。一般に、目標BERを厳しくするほど符号化利得は大きくなります。後で数値を見ますが、拘束長 $K=7$ の畳み込み符号(軟判定)の利得は BER $=10^{-2}$ で約2.3 dB、$10^{-5}$ で約5.4 dB、$10^{-7}$ で約6.0 dBと、じわじわ増えていきます。これは符号化後のBER曲線のほうが未符号化より傾きが急だからです。傾きが急な曲線と緩い曲線を比べれば、下に行くほど水平方向の差が開くのは当然です。

第二に、符号化利得は負にもなり得ます。 雑音が非常に強い領域では、符号化したほうがBERが悪化します。理由は次節で詳しく見ますが、直感的には「訂正できる誤りの数を超えて誤りが入ると、復号器はむしろ誤りを増やしてしまう」からです。この現象をしきい値効果(threshold effect)と呼びます。符号化利得が正に転じる境目のことを、符号化のクロスオーバー点と言います。

第三に、$E_b/N_0$ で測ることが本質的です。 ここが初学者のつまずきどころです。もし1シンボル(チャネルビット)あたりのエネルギー比 $E_s/N_0$ で比べてしまうと、符号化の「コスト」がまったく勘定に入りません。符号化は冗長ビットを足す作業ですから、同じ情報を送るのに必要なチャネルビット数が $1/r$ 倍に増えます($r$ は符号化率)。ビットレートを保つには、シンボル速度を上げるか、1シンボルあたりのエネルギーを削るしかありません。$E_b/N_0$ で測ると、この「冗長ビットのために薄まったエネルギー」が自動的に不利として計上されます。フェアな比較のために、符号化利得は必ず $E_b/N_0$ 基準で語ります。

では、その「薄まり方」を式で確かめておきましょう。

$E_b/N_0$ と符号化率 — 符号化がまず背負う借金

左:符号化すると同じEbを2シンボルで山分けするためEs=rEbに薄まる模式図。右:符号化率rに対する借金10log10(1/r)の曲線と各符号の位置

左の図が「借金」の正体です。1情報ビットに割り当てられる総エネルギー $E_b$ は変わらないまま、それを2つのチャネルビットで山分けするので、1シンボルあたりは半分になります。右の図はこれをdBで表したもので、$r=1/2$ なら3.01 dB、ハミング(7,4)の $r=4/7$ でも2.43 dBのマイナスからスタートすることがわかります。符号化利得が正になるには、訂正能力でこの高さを埋めた上でさらに上回る必要があります。

符号化率 $r = k/n$ の符号を考えます。$k$ 個の情報ビットを $n$ 個のチャネルビットに写します。送信機が使える平均電力 $P$ と情報ビットレート $R_b$ が決まっているとき、情報ビットあたりのエネルギーは

$$ E_b = \frac{P}{R_b} $$

です。一方、チャネルビットレートは $R_c = R_b / r$ に増えるので、チャネルビット(=BPSKの1シンボル)あたりのエネルギーは

$$ \begin{equation} E_s = \frac{P}{R_c} = \frac{P\, r}{R_b} = r\, E_b \end{equation} $$

となります。$r < 1$ ですから $E_s < E_b$、つまり符号化した瞬間に、1シンボルあたりのエネルギーは必ず減ります。$r = 1/2$ なら半分、dBで言えば $-3.01$ dBです。

この状態でBPSKを送ると、変調器・復調器の目に映る「生の」ビット誤り率(=復号する前のチャネル誤り率)は

$$ \begin{equation} p = Q\!\left(\sqrt{\frac{2E_s}{N_0}}\right) = Q\!\left(\sqrt{2r\,\frac{E_b}{N_0}}\right) \end{equation} $$

です。ここで $Q(x) = \frac{1}{\sqrt{2\pi}}\int_x^\infty e^{-u^2/2}\,du$ はガウス裾関数です。未符号化のBERが $Q(\sqrt{2E_b/N_0})$ であることと比べると、引数の中身が $r$ 倍だけ小さくなっています。

つまり誤り訂正符号は、レースのスタート地点で $10\log_{10}(1/r)$ dBの借金を背負ってから走り出すわけです。$r=1/2$ なら3 dBの借金です。符号化利得が正になるには、訂正能力によってこの借金を返した上で、さらに黒字を出さなければなりません。実際、後で数値を見ると、ハミング(7,4)符号を硬判定で使った場合、$E_b/N_0$ が約5.9 dBを超えるまでは借金を返しきれず、未符号化より悪いBERになります。

この「借金と返済」の綱引きを定量化するのが、次に導く漸近符号化利得です。

軟判定における漸近符号化利得 $G_a = 10\log_{10}(r\,d_{\min})$ の導出

ハミング距離をユークリッド距離に翻訳する

符号理論では符号語間の隔たりをハミング距離(異なるビット位置の個数)で測ります。一方、AWGN通信路で誤り確率を決めるのは信号点間のユークリッド距離です。軟判定符号化利得の導出は、要するにこの2つの距離を翻訳する作業です。

BPSK変調では、符号語のビット $c_i \in \{0,1\}$ を信号点 $x_i = (1-2c_i)\sqrt{E_s}$、つまり $\pm\sqrt{E_s}$ に写します。2つの符号語 $\bm{c}$ と $\bm{c}’$ が $d$ 個の位置で異なるとしましょう。対応する信号点ベクトル $\bm{x}, \bm{x}’$ の間の二乗ユークリッド距離を計算します。一致している位置では差がゼロ、異なる位置では $+\sqrt{E_s}$ と $-\sqrt{E_s}$ の差なので $2\sqrt{E_s}$ です。したがって

$$ \begin{equation} d_E^2(\bm{x}, \bm{x}’) = \sum_{i=1}^{n} (x_i – x_i’)^2 = d \cdot \left(2\sqrt{E_s}\right)^2 = 4\, d\, E_s \end{equation} $$

を得ます。ハミング距離 $d$ が二乗ユークリッド距離に線形に効いてくる、これが決定的な事実です。

7ビットの2つの符号語のBPSK信号点を並べ、異なる3箇所だけが2√Es離れて4Esずつ寄与し、合計12Esになる様子を示した図

この図は式(4)の中身をビット位置ごとに分解したものです。ビットが一致している位置(グレー)は二乗距離に何も寄与せず、異なる位置(赤帯)だけが $ (2\sqrt{E_s})^2 = 4E_s$ ずつ加算されます。したがって寄与する位置の個数、すなわちハミング距離 $d$ がそのまま二乗ユークリッド距離の倍率になり、ここでは $d=3$ なので $d_E^2 = 12E_s$ です。

ペアワイズ誤り確率

2つの信号点の中点に判定境界を引き、送信点まわりのガウス雑音分布のうち境界を越えた裾の面積がペアワイズ誤り確率になることを示した図

2つの信号点を結ぶ直線上に射影して考えると、話は1次元のガウス分布の裾の問題に帰着します。判定境界は2点のちょうど中点にあるので、境界までの距離は $d_E/2$、雑音の標準偏差は $\sigma$ で、赤い裾の面積が $Q(d_E/2\sigma)$ です。距離 $d_E$ が伸びれば境界が遠ざかり、$Q$ 関数の裾はガウス的に急減する — これが「距離が大きい符号ほど強い」ことの正体です。

軟判定の最尤復号器は、受信ベクトル $\bm{y}$ に最も近い信号点ベクトルを選びます。送信されたのが $\bm{x}$ なのに、復号器が $\bm{x}’$ のほうを選んでしまう確率をペアワイズ誤り確率(PEP)と呼びます。AWGNの各成分の分散を $\sigma^2 = N_0/2$ とすると、2点間の垂直二等分面を越える確率として

$$ P_2(d) = Q\!\left(\frac{d_E(\bm{x},\bm{x}’)}{2\sigma}\right) $$

が得られます。ここに式(4)と $\sigma = \sqrt{N_0/2}$ を代入していきます。まず $d_E = \sqrt{4dE_s} = 2\sqrt{dE_s}$ なので、分子分母を整理すると

$$ P_2(d) = Q\!\left(\frac{2\sqrt{d E_s}}{2\sqrt{N_0/2}}\right) = Q\!\left(\sqrt{\frac{d E_s}{N_0/2}}\right) = Q\!\left(\sqrt{\frac{2 d E_s}{N_0}}\right) $$

となります。最後に式(2)の $E_s = r E_b$ を代入すると、符号化利得の議論の中心となる式が現れます。

$$ \begin{equation} P_2(d) = Q\!\left(\sqrt{2\, r\, d\, \frac{E_b}{N_0}}\right) \end{equation} $$

未符号化と引数を比べる

未符号化BPSKのBERは $P_b^{\mathrm{unc}} = Q(\sqrt{2 E_b/N_0})$ です。式(5)と見比べると、$Q$ の引数の二乗(=実効的なSNR)が

$$ \underbrace{2\,r\,d\,\frac{E_b}{N_0}}_{\text{符号化}} \quad \text{vs.} \quad \underbrace{2\,\frac{E_b}{N_0}}_{\text{未符号化}} $$

と比較されます。比を取ると、ちょうど $r\,d$ 倍です。$Q$ 関数は単調減少なので、「引数の中身が $r d$ 倍になった」ことは「同じ誤り確率を $1/(rd)$ 倍の $E_b/N_0$ で達成できる」ことを意味します。高SNR極限では、符号語対の中で最も間違えやすいのは距離が最小の対、すなわち $d = d_{\min}$(畳み込み符号なら $d = d_{\mathrm{free}}$)の対です。したがって

$$ \begin{equation} G_a = 10\log_{10}\left(r\, d_{\min}\right) \quad [\mathrm{dB}] \end{equation} $$

漸近符号化利得(asymptotic coding gain)です。導出を振り返ると、$r$ が「冗長ビットのせいでエネルギーが薄まる借金」、$d_{\min}$ が「符号語同士が離れていることによる返済」を表しており、その積が正味の利得になっている、という構造がはっきり見えます。

具体的な数値を入れてみましょう。ハミング(7,4)符号は $r = 4/7$、$d_{\min} = 3$ なので

$$ G_a = 10\log_{10}\!\left(\frac{4}{7}\times 3\right) = 10\log_{10}(1.714) = 2.34\ \mathrm{dB} $$

です。拘束長 $K=7$、$r=1/2$ の畳み込み符号(生成多項式 133/171 octal)は $d_{\mathrm{free}} = 10$ なので

$$ G_a = 10\log_{10}\!\left(\frac{1}{2}\times 10\right) = 10\log_{10}(5) = 6.99\ \mathrm{dB} $$

となります。ゴレイ(23,12)符号なら $10\log_{10}(12/23 \times 7) = 5.63$ dBです。

符号化率rと最小距離dminの平面上に漸近符号化利得10log10(r・dmin)を等高線で描き、ハミング・ゴレイ・畳み込み符号の位置を示した図

漸近符号化利得は $r$ と $d_{\min}$ の積だけで決まるので、この平面上では等高線が双曲線になります。右上(高レート・大距離)ほど濃い緑で利得が大きく、左下は赤で利得がマイナス、つまり符号化するほど損をする領域です。太い破線 $r\,d_{\min}=1$ がその境界で、ハミング(7,4)の硬判定(実効距離2)が0.58 dBとぎりぎり境界のすぐ上にいることが一目でわかります。

軟判定と硬判定で同じ符号の点が縦に離れているのも重要な情報です。畳み込み $K=7$ は軟判定なら $d=10$ で6.99 dBの高さにいますが、硬判定では実効距離が5に落ちて3.98 dBまで下がります。符号そのものは同じでも、復調器から復号器へ渡す情報の量だけで平面上の位置が大きく動くのです。

漸近利得は「到達できない上限」である

ここで釘を刺しておきます。式(6)はあくまで $E_b/N_0 \to \infty$ の極限値であり、実際の有限SNRでの利得はこれより小さくなります。理由は多重度(multiplicity)です。最小距離の符号語対は1組ではなく複数あり、それらすべてがエラーに寄与します。ユニオンバウンドで書くと

$$ \begin{equation} P_b \le \sum_{d \ge d_{\min}} \frac{W_d}{k}\, Q\!\left(\sqrt{2\,r\,d\,\frac{E_b}{N_0}}\right) \end{equation} $$

ハミング(7,4)軟判定のユニオンバウンドをd=3,4,7の各項に分解し、合計曲線が多重度1の理想曲線より0.49 dB右にずれることを示した図

この図は式(7)の右辺を項ごとにばらしたものです。赤い点線が「最小距離の符号語対が1組だけ」という理想(漸近利得2.34 dBに対応)で、黒の実線が多重度を含めた実際のユニオンバウンドです。BER $=10^{-5}$ の水平線上で両者は0.49 dBずれており、これがそのまま「漸近利得に届かない分」になります。$d=3$ の項が支配的ですが、$d=4$ の項も高SNRまで無視できない大きさで残っている点にも注目してください。

ここで $W_d$ は重み $d$ の符号語に対応する情報ビット重みの総和です。ハミング(7,4)を実際に全16符号語について数え上げると、$A_3 = 7,\ A_4 = 7,\ A_7 = 1$(重み分布)で、情報ビット重みの総和は $W_3 = 12,\ W_4 = 16,\ W_7 = 4$ になります。$k=4$ で割ると、式(7)の先頭項の係数は $12/4 = 3$ です。この「3倍」がBER曲線を上にシフトさせ、実効的な利得を削ります。実際にBER $=10^{-5}$ で測ると、ハミング(7,4)軟判定の利得は約1.85 dBで、漸近値2.34 dBに約0.5 dB届きません。

畳み込み符号ではもっと顕著です。133/171符号の重み分布は $B_{10}=36,\ B_{12}=211,\ B_{14}=1404,\ B_{16}=11633,\ B_{18}=77433$ と急激に増えるため、BER $=10^{-5}$ での実効利得は約5.4 dBにとどまり、漸近値6.99 dBから1.6 dBも目減りします。「$d_{\mathrm{free}}$ を大きくすれば無条件に強くなる」わけではなく、重み分布全体の形が効くのです。

ここまでは軟判定、つまり復調器が受信信号の実数値をそのまま復号器に渡す場合の話でした。では、復調器が先に「0か1か」を決めてしまう硬判定では何が起きるのでしょうか。

硬判定での劣化 — なぜ $d_{\min}$ が $\lfloor (d_{\min}-1)/2 \rfloor + 1$ に化けるのか

硬判定は情報を捨てている

左:軟判定は受信実数値の確信度を保つ様子。右:硬判定はしきい値で0/1に潰し、+0.05も+2.70も同じ「0」になる様子

左は復調器出力の確率密度で、受信値が0付近なら判定は五分五分、大きく離れていればほぼ確実、という「確信度」が実数値として残っています。右はそれを1ビットに潰した後で、$+0.05$ も $+2.70$ もどちらも同じ「0」になり、区別がつきません。復号器はこの潰れた情報だけでハミング距離を計算するので、性能が落ちるのは避けられません。

軟判定では、受信値が $+0.05$ なのか $+2.7$ なのかを復号器が知っています。前者は「かろうじて0っぽいが自信なし」、後者は「ほぼ確実に0」です。硬判定は、この確信度をゼロビットに切り捨てて「どちらも0」と伝えます。捨てた情報の分だけ性能が落ちるのは当然ですが、問題はそれが何dBに相当するかです。

硬判定にすると、AWGN通信路は反転確率 $p = Q(\sqrt{2r E_b/N_0})$ の二元対称通信路(BSC)に化けます。復号器はハミング距離だけを頼りに復号します。最小距離 $d_{\min}$ の符号は $t = \lfloor (d_{\min}-1)/2 \rfloor$ 個までの誤りを確実に訂正できます。逆に言えば、$t+1$ 個の誤りが入ると(限界距離復号では)誤った符号語に落ちる可能性が出ます。

指数の比較で利得を読む

高SNR領域の振る舞いを掴むために、$Q$ 関数の指数的な上界

$$ Q(x) \le \frac{1}{2}e^{-x^2/2} $$

を使います。$x = \sqrt{2 r \gamma_b}$($\gamma_b \equiv E_b/N_0$)を代入すると、生のビット誤り率は

$$ p \le \frac{1}{2}e^{-r \gamma_b} $$

と評価できます。指数の肩に $-r\gamma_b$ が乗っている点を覚えておいてください。

さて、距離 $d$ 離れた誤った符号語に落ちるには、その $d$ 個の相異位置のうち少なくとも $t+1$ 個が反転する必要があります。二項分布で書くと

$$ P_2^{\mathrm{hard}}(d) = \sum_{e = t+1}^{d} \binom{d}{e} p^e (1-p)^{d-e} $$

です。$p \ll 1$ のとき、この和は先頭項が支配します。つまり

$$ P_2^{\mathrm{hard}}(d) \approx \binom{d}{t+1} p^{t+1} $$

です。ここに上の $p$ の評価を代入すると、$p^{t+1}$ の部分から $e^{-(t+1) r \gamma_b}$ が出てきます。整理すると

$$ \begin{equation} P_2^{\mathrm{hard}}(d) \lesssim \binom{d}{t+1} 2^{-(t+1)} \exp\!\left[-(t+1)\, r\, \gamma_b\right] \end{equation} $$

一方、軟判定の式(5)を同じ指数上界で評価すると

$$ \begin{equation} P_2^{\mathrm{soft}}(d) \le \frac{1}{2}\exp\!\left[- d\, r\, \gamma_b\right] \end{equation} $$

です。式(8)と式(9)の指数の肩を見比べてください。軟判定は $d\, r\, \gamma_b$、硬判定は $(t+1)\, r\, \gamma_b$。つまり硬判定では、符号の距離 $d$ が実質的に $t+1 = \lfloor (d-1)/2 \rfloor + 1$ に置き換わっているわけです。したがって硬判定の漸近符号化利得は

$$ \begin{equation} G_a^{\mathrm{hard}} = 10\log_{10}\!\left[r\left(\left\lfloor \frac{d_{\min}-1}{2}\right\rfloor + 1\right)\right] \end{equation} $$

となります。奇数の $d$ に対しては $t+1 = (d+1)/2$ ですから、軟判定との比は $(d+1)/(2d)$ で、$d$ が大きいときは $1/2$、すなわち 3 dBの損失に漸近します。

左:最小距離dに対する軟判定の実効距離dと硬判定の実効距離⌊(d-1)/2⌋+1の比較。右:その比をdBにした硬判定損失と、実測差2.35dB・1.44dBの比較

左の図で、青(軟判定)は $d$ そのままの直線ですが、赤(硬判定)は階段状に半分の高さまで落ちます。ハミング(7,4)の $d=3$ は実効2に、畳み込み $K=7$ の $d=10$ は実効5に化けるという、式(10)の内容がそのまま見えています。右の図はその比をdBに直したもので、$d$ が偶数のときは $t+1 = d/2$ がちょうど半分になるので上限の3.01 dBに一致し、奇数のときは $t+1=(d+1)/2$ が半分よりわずかに大きいので損失が少し軽くなる、というジグザグを描きます。ジグザグの谷(奇数側)も $d$ が大きくなるにつれて 1.76 → 2.22 → 2.44 → …と持ち上がり、全体として3.01 dBの上限に収束していきます。

同時に右の図には、BER $=10^{-5}$ で実測した硬判定と軟判定の差(畳み込みで2.35 dB、ハミングで1.44 dB)も横線で入れてあります。どちらも漸近的な3 dBよりかなり低い位置にあり、「教科書の約2 dB」は漸近値ではなく実用域の値だということが読み取れます。

「2 dBの損失」という経験則との関係

教科書には「硬判定は軟判定より約2 dB損」と書かれていることが多く、上で導いた3 dBと食い違って見えます。どちらも正しく、見ている領域が違います。

式(8)の導出では $Q(x) \le \frac12 e^{-x^2/2}$ という緩い上界を使いました。この不等式は $x$ が大きいほど緩くなるため、硬判定側の評価が実際より悲観的になります。実用的なBER($10^{-5}$ 程度)では、まだ完全な漸近領域に入っていないので、損失は3 dBまで開ききりません。後で実際に計算しますが、$K=7$ 畳み込み符号でBER $=10^{-5}$ を目標にすると、軟判定は4.17 dB、硬判定は6.52 dBを要求し、差は2.35 dBです。ハミング(7,4)では差は1.44 dBでした。つまり「実用域で約2 dB、漸近的には約3 dB」と理解しておけば矛盾しません。

ちなみに、この2 dBという数字にはもう一つの導出があります。硬判定BSCと軟判定AWGNのカットオフレート $R_0$ を比べると、低レート極限で約2 dBの差が出ます。情報理論的にも「硬判定は約2 dB分の情報を捨てている」ことが確認できるのです。実装上は、3ビット(8値)の軟判定量子化をすれば、無限精度の軟判定に対する損失を0.2〜0.3 dB程度に抑えられることが知られており、多くの受信機がこの設計を採っています。

さて、ここまでで「どれだけ得をするか」を計算する道具は揃いました。次は「どこまで得できるのか」という上限を、シャノンの容量式から導きます。

シャノン限界 $-1.59$ dB の導出

出発点:帯域制限AWGN通信路の容量

シャノン・ハートレーの定理は、帯域幅 $B$ [Hz]、信号電力 $P$ [W]、雑音電力密度 $N_0$ [W/Hz] のAWGN通信路の容量を次のように与えます。

$$ \begin{equation} C = B \log_2\!\left(1 + \frac{P}{N_0 B}\right) \quad [\mathrm{bit/s}] \end{equation} $$

ここで $N_0 B$ が帯域 $B$ 内の雑音電力です。この $C$ より小さいレートなら、適切な符号を使えば誤り率を任意に小さくできる — それがシャノンの通信路符号化定理の主張でした。逆に $R_b > C$ では、どんな符号を使っても誤り率を0に近づけられません。

信号電力を $E_b$ で書き換える

情報ビットレートを $R_b$ [bit/s] とすると、1情報ビットあたりのエネルギーは $E_b = P/R_b$、つまり

$$ P = E_b R_b $$

です。誤りなし通信が可能な条件 $R_b \le C$ に式(11)を入れ、さらに $P$ をこの形で置き換えます。

$$ R_b \le B \log_2\!\left(1 + \frac{E_b R_b}{N_0 B}\right) $$

帯域利用効率で無次元化する

このままでは $R_b$ と $B$ の2変数が残って見通しが悪いので、帯域利用効率(spectral efficiency)

$$ \eta \equiv \frac{R_b}{B} \quad [\mathrm{bit/s/Hz}] $$

を導入します。両辺を $B$ で割ると、$R_b/B = \eta$、$E_b R_b/(N_0 B) = (E_b/N_0)\eta$ ですから

$$ \begin{equation} \eta \le \log_2\!\left(1 + \frac{E_b}{N_0}\eta\right) \end{equation} $$

という、$\eta$ と $E_b/N_0$ だけの関係式になりました。

$E_b/N_0$ について解く

式(12)の両辺を2の指数に乗せます($\log_2$ と $2^{(\cdot)}$ は単調増加なので不等号の向きは変わりません)。

$$ 2^{\eta} \le 1 + \frac{E_b}{N_0}\eta $$

$\eta > 0$ なので両辺から1を引いて $\eta$ で割ると、$E_b/N_0$ の下限が現れます。

$$ \begin{equation} \frac{E_b}{N_0} \ge \frac{2^{\eta} – 1}{\eta} \end{equation} $$

これが帯域制限つきシャノン限界です。所望の帯域利用効率 $\eta$ を決めれば、必要な $E_b/N_0$ の絶対的な下限が決まります。

帯域を無制限に使う極限

式(13)の右辺は $\eta$ の減少関数です(後で図で確認します)。したがって $E_b/N_0$ の下限を最小にするには、$\eta \to 0$、つまり帯域を無限に広く使う極限を取ればよいことになります。この極限を丁寧に計算しましょう。

$2^\eta = e^{\eta \ln 2}$ と書き換え、指数関数をマクローリン展開します。

$$ 2^{\eta} = e^{\eta \ln 2} = 1 + \eta \ln 2 + \frac{(\eta \ln 2)^2}{2!} + \frac{(\eta \ln 2)^3}{3!} + \cdots $$

これを式(13)の右辺に代入すると、先頭の1が打ち消し合います。

$$ \frac{2^{\eta}-1}{\eta} = \frac{\eta \ln 2 + \frac{(\eta \ln 2)^2}{2} + \cdots}{\eta} = \ln 2 + \frac{\eta (\ln 2)^2}{2} + \cdots $$

ここで $\eta \to 0$ とすると、第2項以降はすべて消えます。

$$ \begin{equation} \lim_{\eta \to 0}\frac{2^{\eta}-1}{\eta} = \ln 2 \approx 0.6931 \end{equation} $$

最後にdBに直します。

$$ \begin{equation} \left[\frac{E_b}{N_0}\right]_{\min} = 10\log_{10}(\ln 2) = 10\log_{10}(0.6931) = -1.592\ \mathrm{dB} \end{equation} $$

左:帯域利用効率ηに対する必要Eb/N0の下限曲線とη→0での-1.59dB漸近線。右:(2^η-1)/ηのマクローリン展開でln2=0.6931が残る様子

左の図は式(13)そのもので、帯域利用効率 $\eta$ を下げる(帯域を広く使う)ほど必要な $E_b/N_0$ が下がり、$\eta \to 0$ で $-1.59$ dBの水平線に漸近します。$\eta=1$ でちょうど0.00 dB、$\eta=2$ で1.76 dB、$\eta=4$ で5.74 dBと、帯域を節約するほど電力を余計に要求される関係も読めます。右の図は式(14)の極限の様子で、$\eta$ を小さくすると2項目以降が消えて $\ln 2 = 0.6931$ だけが残る過程を、厳密値と展開近似の重なりとして確認できます。

これがシャノン限界です。どんなに賢い符号を設計しても、$E_b/N_0$ が $-1.59$ dBを下回る領域では、誤り率を0に近づけながら情報を送ることは物理的に不可能です。

この数字の意味するところ

$-1.59$ dBという値は「1未満」、つまり $E_b < N_0$ でも通信できることを言っています。1ビットあたりのエネルギーが雑音電力密度より小さくても構わない、というのは直感に反するかもしれません。カラクリは $\eta \to 0$、すなわち「1ビットを送るのに無限の帯域と無限の時間をかける」ことにあります。極端に薄く広く信号を撒けば、各点でのSNRは限りなく0に近くても、全体を積分すれば十分な情報が取り出せるのです。

もう一つ重要な注意点があります。式(15)の導出では入力信号の分布に制約を置いていません。容量を達成する入力はガウス分布であり、BPSKのような離散的な信号点ではありません。実際にBPSK(二元入力)に制約すると、限界はもっと厳しくなります。数値的に計算すると、符号化率 $r = 1/2$ のBPSK系では限界が $+0.19$ dB、$r=1/3$ でも $-0.50$ dBで、$-1.59$ dBには届きません。$-1.59$ dBに漸近するには、低レート化と多値化・帯域拡大を同時に行う必要があります。

限界の位置がわかったので、いよいよ「実際の符号が限界までどれだけ距離を残しているか」を数値で確認しましょう。

具体例 — 数値で見る「残り何dB」

BER $=10^{-5}$ を目標にしたときの数字を並べてみます。未符号化BPSKでこのBERを達成するには

$$ Q\!\left(\sqrt{2\gamma_b}\right) = 10^{-5} \ \Longrightarrow\ \gamma_b = 9.59\ \mathrm{dB} $$

が必要です。一方、シャノン限界は $-1.59$ dBでした。したがって、誤り訂正符号が稼げる利得の全予算は $9.59 – (-1.59) = 11.18$ dBです。この11.18 dBというパイを、各符号がどれだけ切り取っているかを見るのが本記事の核心です。

符号 $r$ $d_{\min}$ 漸近利得 $G_a$ BER $10^{-5}$ 実効利得 限界までの残り
ハミング(7,4) 硬判定 4/7 3 0.58 dB 約 0.41 dB 約 10.8 dB
ハミング(7,4) 軟判定 4/7 3 2.34 dB 約 1.85 dB 約 9.3 dB
畳み込み $K=7$ 硬判定 1/2 10 3.98 dB 約 3.07 dB 約 8.1 dB
畳み込み $K=7$ 軟判定 1/2 10 6.99 dB 約 5.42 dB 約 5.8 dB
ターボ符号相当 1/2 約 8.9 dB 約 2.3 dB

表の読み方をいくつか補足します。

ハミング符号の硬判定利得が0.41 dBしかないのは衝撃的かもしれません。$d_{\min}=3$ なので $t=1$、すなわち $t+1=2$ で、式(10)から $10\log_{10}(4/7 \times 2) = 0.58$ dBです。1ビット訂正の能力は、$r=4/7$ が課す2.4 dBの借金をようやく上回る程度でしかないのです。これがハミング符号が「誤り訂正の入門例」ではあっても実用の主力ではない理由です。

軟判定に切り替えるだけで1.4 dB以上増える点も重要です。符号は何も変えず、復調器から復号器への情報の渡し方を変えただけでこれだけ違います。復号器の構造を変えずに利得を稼げるので、費用対効果が非常に高い施策です。

ターボ符号は限界まで残り2.3 dBまで迫っています。ただしこの数字には注釈が必要です。表の「限界」は入力無制約のシャノン限界 $-1.59$ dBですが、BPSK入力に制約した $r=1/2$ の限界は $+0.19$ dBでした。ターボ符号の動作点0.7 dBは、こちらの制約付き限界に対してはわずか0.5 dB差です。同じ土俵で比べれば、ターボ符号やLDPC符号は理論限界をほぼ食い尽くしていると言えます。LDPC符号の理論で述べたように、最適化された不正則LDPC符号では、この差が0.0045 dBまで詰められた例も報告されています。

数値の裏付けを取るため、ここからPythonで実際に曲線を描いていきます。

Pythonでの実装

共通の道具立て

まず $Q$ 関数、dB変換、未符号化BPSKのBERを用意します。日本語ラベルのフォント設定も冒頭で済ませておきます。

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from scipy.special import erfc, comb
from scipy.optimize import brentq

# 日本語フォント設定
for cand in ["Hiragino Sans", "Yu Gothic", "Noto Sans CJK JP", "IPAexGothic", "Meiryo"]:
    if any(cand == f.name for f in matplotlib.font_manager.fontManager.ttflist):
        plt.rcParams["font.family"] = cand
        break
plt.rcParams["axes.unicode_minus"] = False

def Qfunc(x):
    """ガウス裾関数 Q(x) = P(N(0,1) > x)"""
    return 0.5 * erfc(np.asarray(x, dtype=float) / np.sqrt(2))

def db2lin(db):
    """dB表記を真数に変換"""
    return 10 ** (np.asarray(db, dtype=float) / 10)

def ber_uncoded(ebn0_db):
    """未符号化BPSKのBER: Q(sqrt(2*Eb/N0))"""
    return Qfunc(np.sqrt(2 * db2lin(ebn0_db)))

# シャノン限界(帯域無制限)
shannon_limit_db = 10 * np.log10(np.log(2))
print(f"シャノン限界: {shannon_limit_db:.3f} dB")
print(f"未符号化でBER=1e-5に必要なEb/N0: "
      f"{brentq(lambda d: ber_uncoded(d) - 1e-5, 0, 20):.2f} dB")

出力は「シャノン限界: -1.592 dB」「未符号化でBER=1e-5に必要なEb/N0: 9.59 dB」となります。この2つの数字が本記事の座標軸です。両者の差11.18 dBが、誤り訂正が奪い取れる電力の全予算であり、以降のすべての符号はこの区間のどこかに位置します。

ハミング(7,4)符号 — 硬判定は厳密計算、軟判定はユニオンバウンド

ハミング(7,4)は符号語が16個しかないので、硬判定復号の情報ビット誤り率を厳密に計算できます。全128通りの誤りパターンについてシンドローム復号を実行し、残留誤りの情報ビット部分を数えます。

from itertools import product

# 組織形の生成行列と検査行列
Pm = np.array([[1, 1, 0], [0, 1, 1], [1, 1, 1], [1, 0, 1]])
G = np.hstack([np.eye(4, dtype=int), Pm])
H = np.hstack([Pm.T, np.eye(3, dtype=int)])

# シンドローム → コセットリーダー(単一誤りパターン)の対応表
I7 = np.eye(7, dtype=int)
syn = {tuple((H @ I7[j]) % 2): I7[j] for j in range(7)}
syn[(0, 0, 0)] = np.zeros(7, dtype=int)

# 全128通りの誤りパターンについて (誤り重み, 復号後の情報ビット誤り数) を列挙
_pat = []
for e in product([0, 1], repeat=7):
    e = np.array(e)
    resid = (e + syn[tuple((H @ e) % 2)]) % 2   # 復号後に残る誤り
    _pat.append((int(e.sum()), int(resid[:4].sum())))

def ber_hamming_hard(ebn0_db):
    """ハミング(7,4) 硬判定シンドローム復号の情報ビット誤り率(厳密)"""
    r = 4 / 7
    p = Qfunc(np.sqrt(2 * r * db2lin(ebn0_db)))   # 生のチャネル誤り率
    return sum(p ** w * (1 - p) ** (7 - w) * ie / 4 for w, ie in _pat)

def ber_hamming_soft(ebn0_db):
    """ハミング(7,4) 軟判定最尤復号のユニオンバウンド
    重み分布 A_3=7, A_4=7, A_7=1、情報ビット重み総和 W_3=12, W_4=16, W_7=4"""
    r, g = 4 / 7, db2lin(ebn0_db)
    return (12 / 4) * Qfunc(np.sqrt(2 * r * 3 * g)) \
         + (16 / 4) * Qfunc(np.sqrt(2 * r * 4 * g)) \
         + (4 / 4) * Qfunc(np.sqrt(2 * r * 7 * g))

硬判定側は近似を一切使わない厳密な期待値計算です。ユニオンバウンドを使う軟判定側は上界なので、低SNR領域では1を超えて発散します。実用上、ユニオンバウンドはBERが $10^{-2}$ より小さい領域でのみ意味があると考えてください。この違いを意識しておくと、後で描く図の低SNR側で軟判定曲線が不自然に立ち上がる理由がわかります。

畳み込み符号(133,171)の重み分布を状態図から数える

畳み込み符号のユニオンバウンドには重み分布 $B_d$(距離 $d$ の誤りパスに伴う情報ビット誤り数の総和)が必要です。文献の表を写すのではなく、状態図上の動的計画法で自分で数えます。全ゼロ状態を出発して、いったん離れ、再び全ゼロ状態に戻るパスを列挙する問題です。

def conv_spectrum(g1=0o133, g2=0o171, K=7, dmax=18):
    """畳み込み符号の重み分布 B_d を状態図上のDPで数える。
    B_d = 距離dの誤りパス全体にわたる情報ビット誤り数の総和"""
    S = 1 << (K - 1)
    tr = {}
    for s in range(S):                     # 各状態からの遷移表を作る
        for u in (0, 1):
            reg = (u << (K - 1)) | s
            w = bin(reg & g1).count('1') % 2 + bin(reg & g2).count('1') % 2
            tr[(s, u)] = ((reg >> 1) & (S - 1), w)   # (次状態, 出力重み)

    # N[s][d]: 状態sに至る重みdのパス数, M[s][d]: それらの情報ビット重み総和
    N = {s: np.zeros(dmax + 1) for s in range(S)}
    M = {s: np.zeros(dmax + 1) for s in range(S)}
    ns, w = tr[(0, 1)]                     # 最初の枝は必ず u=1(全ゼロ状態を離れる)
    N[ns][w], M[ns][w] = 1.0, 1.0
    Bd = np.zeros(dmax + 1)

    for _ in range(6 * K):                 # 十分な長さまで伸ばす
        N2 = {s: np.zeros(dmax + 1) for s in range(S)}
        M2 = {s: np.zeros(dmax + 1) for s in range(S)}
        for s in range(S):
            if not N[s].any():
                continue
            for u in (0, 1):
                ns, w = tr[(s, u)]
                n = np.zeros(dmax + 1); m = np.zeros(dmax + 1)
                if w:                      # 出力重みwだけ距離をシフト
                    n[w:] = N[s][:dmax + 1 - w]; m[w:] = M[s][:dmax + 1 - w]
                else:
                    n[:] = N[s]; m[:] = M[s]
                m = m + u * n              # 入力が1なら情報ビット誤りを1加算
                if ns == 0:
                    Bd += m                # 全ゼロ状態に戻ったら誤りイベント確定
                else:
                    N2[ns] += n; M2[ns] += m
        N, M = N2, M2
    return Bd

Bd = conv_spectrum()
print("(133,171) の重み分布:",
      [(d, int(round(Bd[d]))) for d in range(10, 19) if Bd[d] > 0.5])

出力は [(10, 36), (12, 211), (14, 1404), (16, 11633), (18, 77433)] となり、Proakisなどの教科書に載る $K=7$、$r=1/2$ 符号の重み分布表と完全に一致します。$d_{\mathrm{free}}=10$ であること、そして距離が2増えるごとに寄与が約6倍に膨らむことが確認できました。この急激な増加こそが、実効利得を漸近利得より1.6 dBも押し下げる犯人です。

畳み込み符号のBERとターボ符号の参照曲線

重み分布が手に入ったので、軟判定・硬判定それぞれのユニオンバウンドを組み立てます。ターボ符号については、文献で報告された動作点を通る参照曲線を用意します。

DS = [d for d in range(10, 19) if Bd[d] > 0.5]

def ber_conv_soft(ebn0_db):
    """畳み込み符号 軟判定ビタビ復号のユニオンバウンド"""
    r, g = 0.5, db2lin(ebn0_db)
    return sum(Bd[d] * Qfunc(np.sqrt(2 * r * d * g)) for d in DS)

def _P2_bsc(d, p):
    """BSC上で距離dの誤ったパスを選んでしまう確率"""
    s = sum(comb(d, e) * p ** e * (1 - p) ** (d - e) for e in range(d // 2 + 1, d + 1))
    if d % 2 == 0:                          # 距離が偶数なら同点をコイン投げで割る
        s += 0.5 * comb(d, d // 2) * p ** (d / 2) * (1 - p) ** (d / 2)
    return s

def ber_conv_hard(ebn0_db):
    """畳み込み符号 硬判定ビタビ復号のユニオンバウンド"""
    p = Qfunc(np.sqrt(2 * 0.5 * db2lin(ebn0_db)))
    return sum(Bd[d] * _P2_bsc(d, p) for d in DS)

# ターボ符号(r=1/2)の参照曲線。Berrouら(1993)が報告した
# 「BER=1e-5 を Eb/N0=0.7dB で達成」という動作点とエラーフロアに合わせた模式曲線。
_tx = [-0.5, 0.0, 0.3, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.5, 2.0, 3.0, 6.0]
_ty = [-0.6, -1.3, -2.3, -3.4, -4.2, -5.0, -5.8, -6.3, -6.55, -6.8, -6.9, -7.0, -7.05]

def ber_turbo(ebn0_db):
    """ターボ符号相当の参照曲線(実測シミュレーションではなく文献値に合わせた模式)"""
    return 10 ** np.interp(np.asarray(ebn0_db, dtype=float), _tx, _ty)

畳み込み符号の硬判定では、距離が偶数の場合に「受信語が2つのパスから等距離」という同点が起こり得るため、その確率の半分を誤りに算入しています(_P2_bsc の後半)。ターボ符号は反復復号のためユニオンバウンドで扱えないので、公表された動作点を通る折れ線を参照として置いています。この曲線は実測値ではないので、利得の絶対値は「文献報告に基づく目安」として読んでください。

図1: BER曲線を同一軸に並べる

いよいよ全部の曲線を1枚に描きます。シャノン限界と未符号化の動作点も縦線で示します。

ebn0 = np.linspace(-2.0, 12.0, 561)
curves = [
    ("未符号化 BPSK", ber_uncoded, "k", "-"),
    ("ハミング(7,4) 硬判定", ber_hamming_hard, "tab:orange", "--"),
    ("ハミング(7,4) 軟判定", ber_hamming_soft, "tab:orange", "-"),
    ("畳み込み K=7 硬判定", ber_conv_hard, "tab:blue", "--"),
    ("畳み込み K=7 軟判定", ber_conv_soft, "tab:blue", "-"),
    ("ターボ符号相当 r=1/2", ber_turbo, "tab:red", "-"),
]

plt.figure(figsize=(9, 6.5))
for name, fn, c, ls in curves:
    y = np.array([float(np.atleast_1d(fn(d))[0]) for d in ebn0])
    y = np.where(y > 0.5, np.nan, y)          # ユニオンバウンドが破綻する領域は描かない
    plt.semilogy(ebn0, y, color=c, ls=ls, lw=2, label=name)

plt.axvline(shannon_limit_db, color="green", lw=2.2, ls=":",
            label="シャノン限界 -1.59 dB(帯域無制限)")
plt.axhline(1e-5, color="gray", lw=1.2, ls="-.", label="目標 BER = $10^{-5}$")
plt.xlabel("$E_b/N_0$ [dB]"); plt.ylabel("ビット誤り率 BER")
plt.title("符号化利得の可視化:目標BERにおける横方向の距離が利得")
plt.ylim(1e-8, 1); plt.xlim(-2, 12)
plt.grid(True, which="both", alpha=0.3); plt.legend(fontsize=9, loc="lower left")
plt.tight_layout(); plt.show()

未符号化・ハミング・畳み込み・ターボの6本のBER曲線、シャノン限界の縦線、目標BER=10^-5の水平線、ハミング硬判定のクロスオーバー点を示した図

この図からいくつもの事実が読み取れます。第一に、BER $=10^{-5}$ の水平線と各曲線の交点を左から順に見ると、ターボ(0.70 dB)→畳み込み軟判定(4.17 dB)→畳み込み硬判定(6.52 dB)→ハミング軟判定(7.74 dB)→ハミング硬判定(9.17 dB)→未符号化(9.59 dB)と並び、符号化利得の大小関係が横方向の距離としてそのまま見えます。第二に、同じ符号でも実線(軟判定)と破線(硬判定)が約2 dB離れており、前節で議論した硬判定の損失が視覚的に確認できます。第三に、ハミング硬判定の曲線は $E_b/N_0$ が約5.9 dBより低い領域で未符号化曲線より上(=悪い)に来ています。これがしきい値効果で、「符号化率の借金を訂正能力が返しきれていない領域」に相当します。

図2: BER $=10^{-5}$ における符号化利得を数値で出す

曲線を目で読むのではなく、根を求めて数値化します。

def required_ebn0(fn, target, lo=-1.4, hi=20.0):
    """目標BERを達成するのに必要なEb/N0 [dB] を二分法で求める"""
    f = lambda db: np.log(max(float(np.atleast_1d(fn(db))[0]), 1e-300)) - np.log(target)
    return brentq(f, lo, hi)

TARGET = 1e-5
ref = required_ebn0(ber_uncoded, TARGET)
rows = [("未符号化 BPSK", ber_uncoded, 1.0, -1.0),
        ("ハミング(7,4)\n硬判定", ber_hamming_hard, 4 / 7, -1.0),
        ("ハミング(7,4)\n軟判定", ber_hamming_soft, 4 / 7, -1.0),
        ("畳み込みK=7\n硬判定", ber_conv_hard, 0.5, -1.0),
        ("畳み込みK=7\n軟判定", ber_conv_soft, 0.5, -1.0),
        ("ターボ相当\nr=1/2", ber_turbo, 0.5, -0.4)]

names, gains, reqs = [], [], []
for nm, fn, r, lo in rows:
    v = required_ebn0(fn, TARGET, lo=lo)
    names.append(nm); reqs.append(v); gains.append(ref - v)
    print(f"{nm.replace(chr(10), ' '):22s} 必要Eb/N0={v:6.2f} dB  符号化利得={ref - v:+5.2f} dB")

budget = ref - shannon_limit_db
print(f"\n未符号化からシャノン限界までの全予算: {budget:.2f} dB")

コンソール出力を見ると、ハミング硬判定 $+0.41$ dB、ハミング軟判定 $+1.85$ dB、畳み込み硬判定 $+3.07$ dB、畳み込み軟判定 $+5.42$ dB、ターボ相当 $+8.89$ dB、そして全予算 $11.18$ dBという数字が並びます。ハミング符号の軟判定利得1.85 dBは漸近値2.34 dBに0.49 dB届かず、畳み込み軟判定の5.42 dBは漸近値6.99 dBに1.57 dB届いていません。多重度の効果がどれだけ利得を食うかが定量的に確認できました。

これを棒グラフにして、シャノン限界までの残りと並べて見ます。

plt.figure(figsize=(10, 6))
x = np.arange(len(names))
plt.bar(x, gains, color=["0.5", "tab:orange", "tab:orange",
                         "tab:blue", "tab:blue", "tab:red"], alpha=0.85,
        label="達成した符号化利得")
plt.bar(x, [budget - g for g in gains], bottom=gains,
        color="lightgreen", alpha=0.55, label="シャノン限界までの残り")
for i, (g, q) in enumerate(zip(gains, reqs)):
    plt.text(i, g + 0.15, f"{g:+.2f} dB", ha="center", fontsize=10, fontweight="bold")
    plt.text(i, 0.25, f"必要\n{q:.2f} dB", ha="center", fontsize=8.5, color="white")
plt.axhline(budget, color="green", ls=":", lw=2,
            label=f"全予算 {budget:.2f} dB(未符号化 → シャノン限界)")
plt.xticks(x, names, fontsize=9)
plt.ylabel("符号化利得 [dB]")
plt.title("BER = $10^{-5}$ における符号化利得と、限界までの残り")
plt.legend(fontsize=9, loc="upper left"); plt.grid(axis="y", alpha=0.3)
plt.tight_layout(); plt.show()

各符号がBER=10^-5で達成した符号化利得を棒で、シャノン限界までの残りを緑で積み上げた図。全予算11.18dBの水平線つき

積み上げ棒の緑の部分が「まだ誰かが取りに行ける余地」です。ハミング符号は全予算11.18 dBのうち1.85 dBしか取れておらず、9.3 dBを残しています。畳み込み符号(軟判定)でも5.8 dB残っています。ターボ符号でようやく残りが2.3 dBまで縮みます。1948年のシャノンの論文から1993年のターボ符号まで45年かかったのが、この最後の数dBを詰める戦いだったわけです。

図3: 帯域制限つきシャノン限界と各符号の位置

$-1.59$ dBは「帯域無制限」という非現実的な仮定のもとでの限界でした。実際の設計では帯域利用効率 $\eta$ が有限なので、式(13)の $E_b/N_0 \ge (2^\eta – 1)/\eta$ を使います。BPSK入力に制約した限界も数値積分で計算し、同じ平面に描きます。

from numpy.polynomial.hermite_e import hermegauss

eta = np.linspace(0.02, 6.0, 500)
lim_uncon = 10 * np.log10((2 ** eta - 1) / eta)     # 入力無制約(ガウス入力)

xh, wh = hermegauss(80)                              # Gauss-Hermite求積の節点と重み
wh = wh / np.sqrt(2 * np.pi)

def C_bpsk(esn0):
    """BPSK入力AWGN通信路の容量 [bit/channel use]"""
    sig = np.sqrt(1 / (2 * esn0))
    y = 1 + sig * xh                                 # x=+1 送信時の受信値の求積点
    return 1 - np.sum(wh * np.log2(1 + np.exp(-2 * y / sig ** 2)))

r_grid = np.linspace(0.05, 0.97, 60)
lim_bpsk = []
for r in r_grid:
    es = brentq(lambda e: C_bpsk(e) - r, 1e-4, 500)
    lim_bpsk.append(10 * np.log10(es / r))
print(f"r=1/2 のBPSK入力限界: {np.interp(0.5, r_grid, lim_bpsk):.3f} dB")

計算すると、$r = 1/2$ のBPSK入力限界は $+0.19$ dBとなります。$-1.59$ dBとの間に1.78 dBの開きがあり、これは「二元の信号点しか使わない」ことのコストです。この差を埋めるには、符号化変調(TCM)や多値変調+確率的整形といった、変調側の工夫が必要になります。

plt.figure(figsize=(9.5, 6.5))
plt.plot(lim_uncon, eta, color="green", lw=2.4,
         label="シャノン限界(入力無制約): $E_b/N_0=(2^\\eta-1)/\\eta$")
plt.plot(lim_bpsk, r_grid, color="purple", lw=2.2, ls="--",
         label="BPSK入力に制約した限界")
plt.axvline(shannon_limit_db, color="green", ls=":", lw=1.8,
            label="$\\eta \\to 0$ の極限 -1.59 dB")
plt.fill_betweenx(eta, -3, lim_uncon, color="lightcoral", alpha=0.35)
plt.text(-2.6, 4.6, "通信不可能領域\n(どんな符号でも到達不能)", fontsize=10, color="darkred")

pts = [("ハミング(7,4) 硬判定", reqs[1], 4 / 7, "tab:orange"),
       ("ハミング(7,4) 軟判定", reqs[2], 4 / 7, "tab:orange"),
       ("畳み込みK=7 硬判定", reqs[3], 0.5, "tab:blue"),
       ("畳み込みK=7 軟判定", reqs[4], 0.5, "tab:blue"),
       ("ターボ相当 r=1/2", reqs[5], 0.5, "tab:red"),
       ("未符号化 BPSK", reqs[0], 1.0, "k")]
for nm, xq, yq, c in pts:
    plt.plot(xq, yq, "o", color=c, ms=9, mec="w", mew=1.2)
    plt.annotate(nm, (xq, yq), textcoords="offset points", xytext=(8, -12), fontsize=9)

plt.xlabel("$E_b/N_0$ [dB](BER = $10^{-5}$ での動作点)")
plt.ylabel("帯域利用効率 $\\eta$ [bit/s/Hz](= 符号化率 $r$)")
plt.title("帯域利用効率–$E_b/N_0$ 平面:各符号はシャノン限界からどれだけ離れているか")
plt.xlim(-3, 12); plt.ylim(0, 6)
plt.grid(alpha=0.3); plt.legend(fontsize=9, loc="upper left")
plt.tight_layout(); plt.show()

帯域利用効率η–Eb/N0平面。緑のシャノン限界曲線より左が通信不可能領域、紫破線がBPSK入力限界、各符号のBER=10^-5動作点をプロットした図

この図が本記事でいちばん情報量の多い1枚です。緑の曲線より左側(赤い領域)は、どんな符号を使っても信頼できる通信ができない禁止領域です。緑曲線は $\eta$ が小さいほど左に寄り、$\eta \to 0$ で $-1.59$ dBの垂線に漸近します。逆に $\eta$ を大きくすると、必要な $E_b/N_0$ は急速に増えます($\eta = 4$ で約5.7 dB)。「帯域を節約すると電力を余計に食う」という、通信工学の基本的なトレードオフが1本の曲線に凝縮されています。紫の破線(BPSK入力限界)は緑より右にあり、$r$ が1に近づくと急激に立ち上がります。$r=0.9$ では $+3.2$ dBにもなり、高レートの二元符号は本質的に不利であることがわかります。各符号の点は紫の破線からの水平距離で評価するのが公平で、その距離はハミング軟判定で約7.2 dB、畳み込み軟判定で約4.0 dB、ターボで約0.5 dBです。

図4: 目標BERを変えると符号化利得はどう変わるか

冒頭で「符号化利得は目標BERに依存する」と述べました。それを直接確かめます。

targets = np.logspace(-2, -7, 12)
plt.figure(figsize=(9, 5.5))
for nm, fn, c, ls, mk in [("ハミング(7,4) 軟判定(実線)", ber_hamming_soft, "tab:orange", "-", "o"),
                          ("ハミング(7,4) 硬判定(破線)", ber_hamming_hard, "tab:orange", (0, (7, 3)), "s"),
                          ("畳み込みK=7 軟判定(実線)", ber_conv_soft, "tab:blue", "-", "o"),
                          ("畳み込みK=7 硬判定(破線)", ber_conv_hard, "tab:blue", (0, (7, 3)), "s")]:
    g = [required_ebn0(ber_uncoded, t) - required_ebn0(fn, t) for t in targets]
    plt.semilogx(targets, g, color=c, ls=ls, marker=mk, ms=4.5, lw=2, label=nm)

plt.axhline(10 * np.log10(0.5 * 10), color="tab:blue", ls=":", lw=1.6,
            label="畳み込み 軟判定の漸近利得 6.99 dB")
plt.axhline(10 * np.log10(4 / 7 * 3), color="tab:orange", ls=":", lw=1.6,
            label="ハミング 軟判定の漸近利得 2.34 dB")
plt.gca().invert_xaxis()
plt.xlabel("目標BER"); plt.ylabel("符号化利得 [dB]")
plt.title("目標BERを厳しくするほど符号化利得は増え、漸近利得に近づく")
plt.grid(alpha=0.3, which="both")
plt.legend(fontsize=9, loc="upper left", handlelength=3.6)
plt.tight_layout(); plt.show()

目標BERを10^-2から10^-7まで厳しくしたときの符号化利得の変化。4本の曲線がすべて単調増加し、点線の漸近利得に下から近づく図

4本の曲線はすべて右に行くほど(目標BERが厳しくなるほど)単調に上昇し、それぞれ自分の漸近利得に下から近づいていきます。点線で示したのは軟判定の漸近利得(畳み込み6.99 dB・ハミング2.34 dB)で、対応する実線がその下を這っている一方、硬判定(破線)はさらに低い自分の漸近値(それぞれ3.98 dB・0.58 dB)に向かうため、同じ色の点線には最後まで届きません。畳み込み軟判定はBER $=10^{-2}$ で2.30 dB、$10^{-5}$ で5.42 dB、$10^{-7}$ で5.95 dBと増え、6.99 dBの漸近線にゆっくり漸近します。「漸近」という言葉が誇張でないこと、そして実用的なBERではまだかなり手前にいることが一目でわかります。設計の場面で「この符号の利得は何dBか」と聞かれたら、必ず「どのBERで測って?」と聞き返すべきだ、というのがこの図の教訓です。

符号化利得を語るときの落とし穴

理論が揃ったところで、実務で誤解されやすい点を整理しておきます。

帯域を無視した比較は無意味です。 符号化利得の定義は $E_b/N_0$ 基準なので、符号化率の借金は勘定に入っています。しかし、帯域が厳しく制限された系(たとえば固定の衛星トランスポンダ帯域)では、$r=1/2$ の符号を使うと変調速度を2倍にできず、結局スループットが半減します。この場合は $E_b/N_0$ だけを見ても不十分で、図3の $\eta$–$E_b/N_0$ 平面上で「同じ $\eta$ を保ったまま左に動けるか」を評価しなければなりません。符号化率を下げずに利得を稼ぐには、符号化変調のように変調と符号化を一体設計するアプローチが必要になります。

しきい値効果を忘れると危険です。 フェージング下で瞬時SNRが落ち込む系や、リンクマージンがぎりぎりの深宇宙リンクでは、動作点がクロスオーバー点を下回る瞬間があり得ます。そのとき符号は助けるどころか足を引っ張ります。本記事の計算では、ハミング(7,4)硬判定のクロスオーバーは5.85 dB、畳み込み硬判定は約4.25 dBでした。低SNRで働かせたい符号ほど、しきい値の低さ(=低レート化と反復復号)が重要になります。

エラーフロアは漸近利得の議論の外にあります。 ターボ符号やLDPC符号は、ある程度以上のSNRでBERの下がり方が急に鈍るエラーフロアを示します。図1のターボ参照曲線でも $10^{-7}$ 付近で寝ています。フロアの原因は、ターボ符号ではインタリーバに起因する低重み符号語、LDPC符号ではタナーグラフ中のトラッピングセットです。BER $=10^{-12}$ が要求される光通信やストレージでは、この領域での挙動こそが設計を支配し、$d_{\min}$ を確保するための外符号(BCH等)との連接が使われます。

実装損失を見込む必要があります。 教科書の符号化利得は、完全な同期・完全な軟判定情報・理想的な雑音分散推定を仮定した値です。実際の受信機では、搬送波位相誤差、タイミングジッタ、軟判定の量子化、雑音分散の推定誤差などで0.5〜1.5 dB程度の実装損失が生じます。リンクバジェットには必ず「実装損失」の行を立て、符号化利得から差し引いて記載します。

「限界まで何dB」は同じ土俵で比べます。 冒頭で述べたように、$-1.59$ dBは入力無制約・帯域無制限の限界です。BPSKで $r=1/2$ の符号を使う系を評価するなら、比較すべき相手は $+0.19$ dBのBPSK入力限界です。この使い分けをしないと、「ターボ符号はまだ2.3 dBも損している」という誤った結論になってしまいます。実際の差は0.5 dBで、ほぼ限界に張り付いています。

まとめ

本記事では、符号化利得の定義から漸近的な理論式、そしてシャノン限界という絶対的な上限までを一本の線でつなぎました。

  • 符号化利得の定義: 目標BERを固定したときの、未符号化と符号化の $E_b/N_0$ の差。単一の数字ではなく目標BERの関数であり、$E_b/N_0$ で測ることで符号化率の「借金」がフェアに勘定される
  • 軟判定の漸近符号化利得: BPSK写像でハミング距離 $d$ は二乗ユークリッド距離 $4dE_s$ に翻訳され、PEPは $Q(\sqrt{2rd\,E_b/N_0})$ となる。未符号化と引数を比べて $G_a = 10\log_{10}(r\,d_{\min})$ が導かれる。多重度のせいで実効利得はこれより小さく、ハミング(7,4)では2.34 dBに対し実効1.85 dB、畳み込み $K=7$ では6.99 dBに対し実効5.42 dB
  • 硬判定の劣化: 誤り確率の指数が $d\,r\gamma_b$ から $(t+1)r\gamma_b$($t=\lfloor (d_{\min}-1)/2\rfloor$)に落ちるため、$d_{\min}$ が実質 $t+1$ に置き換わる。漸近的には約3 dB、実用的なBERでは約2 dBの損失
  • シャノン限界の導出: $C = B\log_2(1+P/(N_0B))$ に $P=E_bR_b$ と $R_b \le C$ を入れ、$\eta=R_b/B$ で無次元化すると $E_b/N_0 \ge (2^\eta-1)/\eta$。$\eta \to 0$ で指数関数を展開すると $\ln 2$ が残り、$10\log_{10}(\ln 2) = -1.59$ dB
  • 全予算11.18 dB: BER $=10^{-5}$ で未符号化は9.59 dBを要し、限界は $-1.59$ dB。この11.18 dBを、ハミングは1.85 dB、畳み込みは5.42 dB、ターボは8.9 dB切り取る。BPSK入力に制約した限界($r=1/2$ で $+0.19$ dB)で測れば、ターボ符号は残り0.5 dBまで迫っている

符号化利得という指標は、「情報理論が示した理論限界」と「いま手元にある符号器・復号器」を1つのdBスケールの上で直接比較させてくれる、稀有な道具です。新しい符号の論文を読むときも、まず $\eta$–$E_b/N_0$ 平面のどこに点を打ったのかを確認すれば、その成果の意味が正確に測れます。

次のステップとして、以下の記事も参考にしてください。