アラモウティ符号(空間時間ブロック符号)の導出と実装

スマートフォンで動画を再生しながら歩いているとき、電波は建物や壁に何度も反射して、強め合ったり弱め合ったりしながらアンテナに届きます。運悪く弱め合うポイントに入ると受信レベルが一瞬で数十dBも落ち込み、画面が固まってしまう——この「深いフェージング(深い谷)」こそ無線通信の最大の敵です。受信アンテナを2本に増やせばこの谷を緩和できることは古くから知られていました(受信ダイバーシチ)。しかし手のひらに収まる携帯端末に複数のアンテナを置き、しかも複雑な合成回路を載せるのは簡単ではありません。

そこで1998年にシアバシュ・アラモウティ(Siavash Alamouti)が発表したのが、送信側を2本のアンテナにすることで受信側は1本のままでもダイバーシチ効果を得る、驚くほど単純で美しい方式でした。このアラモウティ符号は、基地局側に複雑さを押し付けて端末を軽くできるため、3G(WCDMA/HSPA)、LTE、Wi-Fiなど現代のほぼすべての無線規格に送信ダイバーシチの基本形として採用されています。

アラモウティ符号を理解すると、次のような分野への扉が開きます。

  • 携帯電話・LTE/5G: 基地局の2本(または4本)の送信アンテナでセル端のユーザーの通信品質を底上げする送信ダイバーシチの中核技術です
  • Wi-Fi (IEEE 802.11n以降): 空間ストリーム数より送信アンテナが多いときの冗長送信(STBC)として規格に組み込まれています
  • 衛星・移動体通信: マルチパスや遮蔽で深い落ち込みが起きる環境で、受信機を増やさずに信頼性を上げる手段として有効です
  • MIMOの入り口: 空間多重(伝送速度を上げる)と空間ダイバーシチ(信頼性を上げる)という、MIMOの二つの顔の後者を最も鮮やかに見せてくれる例です

本記事の内容

  • 送信ダイバーシチがなぜ難しいのかという直感的な問題設定
  • アラモウティの $2\times2$ 送信行列とその直交性
  • 受信信号から $s_1, s_2$ を線形に分離する復号式の一行ずつの導出
  • 等価SNRがチャネル利得の二乗和に比例し、ダイバーシチ次数2が得られることの証明
  • 最大比合成(MRC)との等価性
  • レイリーフェージング下でのBER対SNRをPythonで実装し、単一アンテナ・MRCと比較

前提知識

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

なぜ送信ダイバーシチは難しいのか

まず、本記事の主役である「ダイバーシチ」とは何かを直感的に押さえておきましょう。フェージングのある無線通信では、受信信号の振幅が確率的に大きく揺らぎます。たまたま振幅がほとんどゼロになる「深い谷」に落ち込むと、いくらノイズが小さくても信号がノイズに埋もれ、ビット誤りが多発します。ダイバーシチとは、互いに独立にフェージングする複数の経路を用意し、「全部の経路が同時に谷に落ちる確率は低い」という統計的事実を使って、深い落ち込みを救う仕組みです。

受信ダイバーシチは話が単純です。受信アンテナを2本置けば、2つの独立な受信信号が得られます。両者を賢く足し合わせる最大比合成(MRC: Maximum Ratio Combining)を使えば、受信SNRはほぼ確実に改善します。問題は、この2本のアンテナと合成回路を、小さく安価でなければならない携帯端末側に積むのが難しいことでした。

ならばアンテナを基地局(送信側)に置けばよい、という発想が自然に出てきます。しかしここに本質的な困難があります。受信ダイバーシチでは、受信機は2つの異なる受信信号を別々に観測できました。ところが送信ダイバーシチで2本のアンテナから同時に信号を送ると、それらは空中で足し合わさって1本の受信アンテナに届きます。受信機が観測するのは合計値ただ一つです。

具体的に書いてみましょう。送信アンテナ1, 2からそれぞれシンボル $s$ を送り、チャネル利得をそれぞれ $h_1, h_2$ とすると、1本の受信アンテナの受信信号は

$$ r = h_1 s + h_2 s + n = (h_1 + h_2)s + n $$

となります。ここで $n$ は雑音です。もし $h_1$ と $h_2$ が逆位相(たとえば $h_1 = +a$, $h_2 = -a$)なら、$h_1 + h_2 = 0$ となって信号が消滅してしまいます。何も工夫せずに同じシンボルを2本から送ると、ダイバーシチが得られないどころか、新たな深い谷を自分で作ってしまうのです。これでは元も子もありません。

では、送信機がチャネル $h_1, h_2$ を事前に知っていればよいのでしょうか。確かに送信側で位相を補正(プリコーディング)すれば足し合わせを強め合いにできます。しかしそのためには受信機が測ったチャネル情報を送信機にフィードバックする必要があり、移動環境では遅延・誤差で実用性が落ちます。送信機がチャネルを知らないまま、受信機側の処理だけでダイバーシチを実現する——これがアラモウティが解いた問題です。鍵になるのは「同じシンボルを同時に送る」のではなく、「2つのシンボルを2つの時刻に巧妙に配置する」というアイデアでした。次節でその配置を見ていきます。

アラモウティ符号の符号化 — 時間と空間に広げる

2シンボルを2時刻×2アンテナに配置する

アラモウティの核心は、2つの情報シンボル $s_1, s_2$ を、2つの時刻(時刻1, 時刻2)と2本の送信アンテナ(アンテナ1, アンテナ2)からなる $2\times2$ の枠に、特別なパターンで配置することです。具体的には次のように送ります。

アンテナ1 アンテナ2
時刻1 $s_1$ $s_2$
時刻2 $-s_2^{*}$ $s_1^{*}$

ここで $s^{*}$ は複素共役を表します。つまり時刻1ではアンテナ1から $s_1$、アンテナ2から $s_2$ を素直に送り、時刻2ではアンテナ1から $-s_2^{*}$、アンテナ2から $s_1^{*}$ という「共役を取って符号を入れ替えたもの」を送るわけです。これを行列で書くと、行を時刻、列をアンテナとして

$$ \bm{S} = \begin{pmatrix} s_1 & s_2 \\ -s_2^{*} & s_1^{*} \end{pmatrix} $$

となります。この行列を送信行列(あるいは符号語行列)と呼びます。2時刻かけて2シンボルを送っているので、伝送レートは1シンボル/時刻、すなわちレート1です。冗長性を加えながらもデータレートを落とさない点が、後で見る繰り返し送信に対する大きな利点です。

なぜこんな共役だらけの不思議な配置にするのか、現時点では天下り的に見えるはずです。実はこの配置は、後で復号するときにチャネルの影響がきれいに分離できるように逆算して設計されています。その「きれいさ」の正体が次に述べる直交性です。

送信行列の直交性

この符号の魔法は、送信行列 $\bm{S}$ の列(または行)が互いに直交していることにあります。実際に確かめてみましょう。$\bm{S}$ の2つの列ベクトルを

$$ \bm{c}_1 = \begin{pmatrix} s_1 \\ -s_2^{*} \end{pmatrix}, \quad \bm{c}_2 = \begin{pmatrix} s_2 \\ s_1^{*} \end{pmatrix} $$

とおきます。複素ベクトルの内積はエルミート内積 $\langle \bm{c}_1, \bm{c}_2\rangle = \bm{c}_1^{H}\bm{c}_2$(片方を共役して掛ける)で測ります。計算すると

$$ \bm{c}_1^{H}\bm{c}_2 = s_1^{*}\cdot s_2 + (-s_2^{*})^{*}\cdot s_1^{*} = s_1^{*}s_2 + (-s_2)s_1^{*}\cdot\text{?} $$

と書きかけると符号が紛らわしいので、丁寧に項ごとに整理します。$\bm{c}_1^{H}$ は $\bm{c}_1$ の各成分を共役して横に並べたものなので $\bm{c}_1^{H} = (s_1^{*}, \ -s_2)$ です(2番目の成分 $-s_2^{*}$ の共役は $-s_2$ になります)。これと $\bm{c}_2 = (s_2, \ s_1^{*})^{T}$ の内積を取ると、第1成分どうしの積と第2成分どうしの積を足して

$$ \bm{c}_1^{H}\bm{c}_2 = s_1^{*}\cdot s_2 + (-s_2)\cdot s_1^{*} = s_1^{*}s_2 – s_1^{*}s_2 = 0 $$

となり、確かにゼロです。2つの列ベクトルは直交しています。さらに各列の大きさ(ノルムの二乗)を計算すると、

$$ \bm{c}_1^{H}\bm{c}_1 = s_1^{*}s_1 + (-s_2)(-s_2^{*}) = |s_1|^2 + |s_2|^2, \quad \bm{c}_2^{H}\bm{c}_2 = |s_2|^2 + |s_1|^2 = |s_1|^2 + |s_2|^2 $$

と、どちらも $|s_1|^2 + |s_2|^2$ で等しくなります。以上をまとめると、$\bm{S}^{H}\bm{S}$ という積が

$$ \bm{S}^{H}\bm{S} = \left(|s_1|^2 + |s_2|^2\right)\bm{I}_2 $$

という、単位行列 $\bm{I}_2$ の定数倍になります。ここで $\bm{S}^{H}$ は $\bm{S}$ の共役転置(エルミート転置)です。この性質——送信行列が直交行列の定数倍になる——が、アラモウティ符号が直交空間時間ブロック符号(OSTBC: Orthogonal Space-Time Block Code)と呼ばれる理由です。

この直交性こそが、後の復号で2つのシンボルを互いに干渉なく分離できる根拠になります。直感的には、$s_1$ を運ぶ「方向」と $s_2$ を運ぶ「方向」が時空間の中で垂直に交わっているので、片方を取り出すときにもう片方が混ざってこないのです。この嬉しさを次節の受信モデルで具体的に確かめましょう。

受信信号モデルと復号式の導出

2時刻の受信信号を書き下す

受信アンテナは1本とします(2送信×1受信、いわゆる $2\times1$ STBC)。チャネルは2時刻のあいだ一定であると仮定します——これは実用上きわめて重要な仮定で、シンボル時間がコヒーレンス時間より十分短ければ成り立ちます。送信アンテナ1から受信アンテナへのチャネル利得を $h_0$、送信アンテナ2からのチャネル利得を $h_1$ とします(どちらも複素数で、振幅と位相の両方を含みます)。

時刻1の受信信号 $r_0$ は、アンテナ1から $s_1$、アンテナ2から $s_2$ が同時に送られて空中で足し合わさったものに雑音が乗ったものなので

$$ r_0 = h_0 s_1 + h_1 s_2 + n_0 $$

です。時刻2では、アンテナ1から $-s_2^{*}$、アンテナ2から $s_1^{*}$ が送られるので

$$ r_1 = h_0(-s_2^{*}) + h_1 s_1^{*} + n_1 = -h_0 s_2^{*} + h_1 s_1^{*} + n_1 $$

となります。$n_0, n_1$ は各時刻の複素ガウス雑音で、互いに独立、平均0、分散 $\sigma^2$ とします。

ここで重要なテクニックを使います。2番目の式 $r_1$ には共役シンボル $s_1^{*}, s_2^{*}$ が現れていて扱いにくいので、両辺の複素共役を取ります。共役は和・積を保ち、二重共役は元に戻る($(s^{*})^{*}=s$)ことに注意すると、

$$ r_1^{*} = -h_0^{*} s_2 + h_1^{*} s_1 + n_1^{*} $$

となります。$s_1, s_2$ が共役の付かない素の形で現れた点に注目してください。これで未知数 $s_1, s_2$ について $r_0$ と $r_1^{*}$ の2本の式が、いずれも共役なしの線形式として揃いました。

行列形式に整理する

$r_0$ と $r_1^{*}$ の2式を、未知ベクトル $(s_1, s_2)^{T}$ についての連立一次方程式として行列にまとめます。

$$ \begin{pmatrix} r_0 \\ r_1^{*} \end{pmatrix} = \begin{pmatrix} h_0 & h_1 \\ h_1^{*} & -h_0^{*} \end{pmatrix}\begin{pmatrix} s_1 \\ s_2 \end{pmatrix} + \begin{pmatrix} n_0 \\ n_1^{*} \end{pmatrix} $$

左の係数行列を $\bm{H}$ とおきます。

$$ \bm{H} = \begin{pmatrix} h_0 & h_1 \\ h_1^{*} & -h_0^{*} \end{pmatrix} $$

この $\bm{H}$ こそが、アラモウティ符号の解析の主役です。受信ベクトルを $\bm{r} = (r_0, r_1^{*})^{T}$、雑音ベクトルを $\bm{n} = (n_0, n_1^{*})^{T}$、送信シンボルベクトルを $\bm{s} = (s_1, s_2)^{T}$ と書けば、コンパクトに

$$ \bm{r} = \bm{H}\bm{s} + \bm{n} $$

と表せます。送信機がチャネルを知る必要はなく、受信機が $h_0, h_1$ を(パイロット信号などで)推定できていれば $\bm{H}$ が作れる、という構図です。

ここで、先ほど見た送信行列の直交性が、今度はチャネル行列 $\bm{H}$ の直交性として再び現れます。これが復号を劇的に簡単にします。次でそれを使います。

チャネル行列の直交性から復号式を導く

$\bm{H}$ のエルミート転置 $\bm{H}^{H}$ を左から掛けてみましょう。これが復号の心臓部です。まず $\bm{H}^{H}$ は $\bm{H}$ を転置して各要素を共役したものなので

$$ \bm{H}^{H} = \begin{pmatrix} h_0^{*} & h_1 \\ h_1^{*} & -h_0 \end{pmatrix} $$

です(対角でない要素の位置が入れ替わり、各要素が共役されている点を確認してください)。これと $\bm{H}$ の積 $\bm{H}^{H}\bm{H}$ を計算します。$2\times2$ 行列の積を成分ごとに書くと、

$$ \bm{H}^{H}\bm{H} = \begin{pmatrix} h_0^{*} & h_1 \\ h_1^{*} & -h_0 \end{pmatrix}\begin{pmatrix} h_0 & h_1 \\ h_1^{*} & -h_0^{*} \end{pmatrix} $$

となります。各成分を順に計算しましょう。左上の成分(1行1列)は、$\bm{H}^{H}$ の1行目と $\bm{H}$ の1列目の内積で

$$ [\bm{H}^{H}\bm{H}]_{11} = h_0^{*}h_0 + h_1 h_1^{*} = |h_0|^2 + |h_1|^2 $$

右上の成分(1行2列)は $\bm{H}^{H}$ の1行目と $\bm{H}$ の2列目の積で

$$ [\bm{H}^{H}\bm{H}]_{12} = h_0^{*}h_1 + h_1(-h_0^{*}) = h_0^{*}h_1 – h_0^{*}h_1 = 0 $$

と、見事に消えます。同様に左下(2行1列)は

$$ [\bm{H}^{H}\bm{H}]_{21} = h_1^{*}h_0 + (-h_0)h_1^{*} = h_1^{*}h_0 – h_0 h_1^{*} = 0 $$

これもゼロです。右下(2行2列)は

$$ [\bm{H}^{H}\bm{H}]_{22} = h_1^{*}h_1 + (-h_0)(-h_0^{*}) = |h_1|^2 + |h_0|^2 $$

となります。オフ対角項がすべて消え、対角項が等しく $|h_0|^2 + |h_1|^2$ になったので、結局

$$ \bm{H}^{H}\bm{H} = \left(|h_0|^2 + |h_1|^2\right)\bm{I}_2 $$

という、単位行列の定数倍が得られました。これがアラモウティ符号の最大の山場です。$\bm{H}$ は直交行列のスカラー倍だったのです。

それでは、受信ベクトル $\bm{r}$ に $\bm{H}^{H}$ を左から掛けて、合成出力 $\tilde{\bm{s}}$ を作ります。

$$ \tilde{\bm{s}} = \bm{H}^{H}\bm{r} = \bm{H}^{H}(\bm{H}\bm{s} + \bm{n}) = \bm{H}^{H}\bm{H}\,\bm{s} + \bm{H}^{H}\bm{n} $$

ここに先ほど示した $\bm{H}^{H}\bm{H} = (|h_0|^2 + |h_1|^2)\bm{I}_2$ を代入すると

$$ \tilde{\bm{s}} = \left(|h_0|^2 + |h_1|^2\right)\bm{s} + \bm{H}^{H}\bm{n} $$

となります。これを成分で書き下すと、雑音項を $\tilde{n}_1 = h_0^{*}n_0 + h_1 n_1^{*}$、$\tilde{n}_2 = h_1^{*}n_0 – h_0 n_1^{*}$ として

$$ \tilde{s}_1 = \left(|h_0|^2 + |h_1|^2\right)s_1 + \tilde{n}_1, \qquad \tilde{s}_2 = \left(|h_0|^2 + |h_1|^2\right)s_2 + \tilde{n}_2 $$

が得られます。$\tilde{s}_1$ には $s_2$ がまったく現れず、$\tilde{s}_2$ には $s_1$ がまったく現れていません。 2つのシンボルが完全に分離されたのです。各シンボルは「自分自身×(チャネル利得の二乗和)」と雑音だけで表されるので、$\tilde{s}_1, \tilde{s}_2$ それぞれに対して通常の単一シンボル判定(最も近いコンスタレーション点を選ぶ)を独立に行えば復号できます。

復号式を成分で明示する

合成出力を成分のチャネル利得で書き下しておきましょう。$\bm{H}^{H}\bm{r}$ の第1成分は $\bm{H}^{H}$ の1行目 $(h_0^{*}, h_1)$ と $\bm{r}=(r_0, r_1^{*})^{T}$ の積なので

$$ \tilde{s}_1 = h_0^{*}r_0 + h_1 r_1^{*} $$

第2成分は $\bm{H}^{H}$ の2行目 $(h_1^{*}, -h_0)$ と $\bm{r}$ の積で

$$ \tilde{s}_2 = h_1^{*}r_0 – h_0 r_1^{*} $$

となります。受信機がやることはたったこれだけです。2時刻の受信値 $r_0, r_1$ とチャネル推定値 $h_0, h_1$ から、上の2式で $\tilde{s}_1, \tilde{s}_2$ を線形に計算し、それぞれを最も近いシンボルに丸める。逆行列を解いたり反復計算したりする必要は一切なく、純粋な線形合成で済みます。問題設定の冒頭で恐れていた「信号が消えてしまう」現象は、もはやどこにも起こりません。$|h_0|^2+|h_1|^2$ という量は両方のチャネルが同時にゼロにならない限り正の値を保つからです。

導出はこれで完成しました。残るは「なぜこれがダイバーシチなのか」を定量的に示すことです。合成出力に現れた $|h_0|^2 + |h_1|^2$ という係数が、その答えの鍵を握っています。次節で等価SNRを計算します。

等価SNRとダイバーシチ次数2の証明

合成後のSNRを計算する

ダイバーシチの効果を測るには、合成出力 $\tilde{s}_1$ における信号電力と雑音電力の比(SNR)を求めます。送信シンボルの平均電力を $E_s = \mathbb{E}[|s_1|^2]$、各時刻の雑音 $n_0, n_1$ の分散をそれぞれ $\sigma^2$ とします。

まず信号成分は $(|h_0|^2 + |h_1|^2)s_1$ なので、その電力は係数の二乗にシンボル電力を掛けて

$$ P_{\text{sig}} = \left(|h_0|^2 + |h_1|^2\right)^2 E_s $$

です。次に雑音成分 $\tilde{n}_1 = h_0^{*}n_0 + h_1 n_1^{*}$ の電力を求めます。$n_0, n_1$ は独立で平均0・分散 $\sigma^2$ なので、交差項の期待値は0になり、

$$ \mathbb{E}[|\tilde{n}_1|^2] = |h_0|^2\,\mathbb{E}[|n_0|^2] + |h_1|^2\,\mathbb{E}[|n_1^{*}|^2] = \left(|h_0|^2 + |h_1|^2\right)\sigma^2 $$

となります(共役を取っても電力は変わらないので $\mathbb{E}[|n_1^{*}|^2] = \sigma^2$ です)。したがって等価SNR $\gamma$ は信号電力を雑音電力で割って

$$ \gamma = \frac{P_{\text{sig}}}{\mathbb{E}[|\tilde{n}_1|^2]} = \frac{\left(|h_0|^2 + |h_1|^2\right)^2 E_s}{\left(|h_0|^2 + |h_1|^2\right)\sigma^2} = \left(|h_0|^2 + |h_1|^2\right)\frac{E_s}{\sigma^2} $$

を得ます。約分により、等価SNRはチャネル利得の二乗和 $|h_0|^2 + |h_1|^2$ に比例することがわかりました。これがアラモウティ符号の効能を表す中心的な式です。

ここで一つだけ注意があります。送信総電力を単一アンテナの場合と公平に揃えるため、2本のアンテナに電力を半分ずつ配分するのが普通です。その場合 $E_s \to E_s/2$ となり、等価SNRは $\gamma = \frac{1}{2}(|h_0|^2 + |h_1|^2)\frac{E_s}{\sigma^2}$ となります。係数 $1/2$ は単純な定数なので、ダイバーシチ次数の議論には影響しません。重要なのは $|h_0|^2 + |h_1|^2$ という二つの独立な利得の和が出てくることです。

なぜ「和」がダイバーシチなのか

なぜ二乗和が嬉しいのかを直感で押さえましょう。単一アンテナのレイリーフェージングでは、瞬時SNRは $|h|^2\frac{E_s}{\sigma^2}$ で、$|h|^2$ が指数分布に従うため、$|h|$ がたまたまゼロ近くになる(深い谷)確率が無視できません。一度谷に落ちるとそこだけで誤りが大量発生します。

アラモウティでは瞬時SNRが $|h_0|^2 + |h_1|^2$ に比例します。二つの独立な利得が同時にゼロ近くになる確率は、片方がゼロ近くになる確率よりもはるかに小さいのです。片方が谷でももう片方が生きていれば和は救われます。これがダイバーシチの本質で、複数の独立経路を統計的に束ねることで「全滅」を避けているわけです。

ダイバーシチ次数2を示す

この「全滅の起きにくさ」を定量化したものがダイバーシチ次数です。ダイバーシチ次数 $d$ とは、高SNR領域で平均ビット誤り率 $P_b$ がSNR $\bar\gamma$ のべき乗で減衰するときの指数、すなわち

$$ P_b \propto \bar\gamma^{-d} $$

における $d$ のことです。$d$ が大きいほど、BER対SNRのグラフ(両対数)の傾きが急になり、少しSNRを上げただけで誤り率が劇的に下がります。

これをアラモウティについて計算します。$h_0, h_1$ が独立な複素ガウス(レイリーフェージング)で、各々 $\mathbb{E}[|h_i|^2]=1$ とすると、$|h_0|^2$ と $|h_1|^2$ はそれぞれ平均1の指数分布に従います。その和 $u = |h_0|^2 + |h_1|^2$ は、独立な指数分布2つの和なので自由度4のカイ二乗分布(等価的に形状パラメータ2のガンマ分布)に従い、その確率密度は

$$ f_u(u) = u\,e^{-u} \quad (u \geq 0) $$

となります。ここで重要なのは原点付近の振る舞いです。$u\to 0$ で $f_u(u) \approx u$ と、$u$ の1乗で立ち上がります(単一アンテナなら指数分布で $f(u)\to 1$ と定数でした)。この「原点付近で密度が小さい」性質が、深い谷の確率を抑えます。

高SNRでの平均BERは、瞬時BERを利得分布で平均することで近似的に評価できます。瞬時SNRが $\gamma = u\,\bar\gamma$(ここで $\bar\gamma = E_s/\sigma^2$ を平均SNR的な量とみなす)のとき、おおまかには誤りは $u\bar\gamma$ が小さいとき、すなわち $u$ が小さいときに集中します。平均BERは原点付近の密度 $f_u(u)\approx u$ が支配し、次のように $\bar\gamma$ のべきで評価できます。

$$ P_b \approx \int_0^{\infty} \frac{c}{u\bar\gamma}\cdot\text{(誤りの起きる領域)}\cdots \sim C\,\bar\gamma^{-2} $$

厳密な計算は省きますが、結論として原点で $f_u(u)\sim u^{d-1}$ と振る舞うとき、ダイバーシチ次数は $d$ になります。アラモウティでは $f_u(u)\sim u^{1}$ なので $d-1=1$、すなわち $d=2$ です。アラモウティ符号は2送信×1受信でダイバーシチ次数2を達成します。これは受信アンテナを2本にしたMRC受信ダイバーシチ(これも次数2)と同じであり、送信側だけでフルダイバーシチが得られたことを意味します。アンテナ本数($n_t \times n_r = 2\times1$)の積に等しい最大値を達成しているので、フルダイバーシチとも呼ばれます。

単一アンテナ($d=1$)では $P_b\propto\bar\gamma^{-1}$ で、SNRを10dB上げると誤り率は約1桁下がるだけですが、アラモウティ($d=2$)では $P_b\propto\bar\gamma^{-2}$ なので10dBで約2桁下がります。この傾きの違いが、後のシミュレーションのグラフではっきり見えるはずです。

ここまでで「送信側だけでダイバーシチが取れる」ことの証明が完成しました。次に、この処理が受信ダイバーシチのMRCと数学的にどう対応しているかを見ると、アラモウティの設計思想がさらに腑に落ちます。

最大比合成(MRC)との等価性

受信ダイバーシチで使われる最大比合成(MRC)を思い出しましょう。受信アンテナが2本あって、それぞれが $r_0 = h_0 s + n_0$、$r_1 = h_1 s + n_1$ という(同じ)シンボル $s$ を異なるチャネル経由で受け取るとき、MRCは各受信信号にチャネルの共役を掛けて足し合わせます。

$$ \tilde{s}_{\text{MRC}} = h_0^{*}r_0 + h_1^{*}r_1 = \left(|h_0|^2 + |h_1|^2\right)s + \left(h_0^{*}n_0 + h_1^{*}n_1\right) $$

この合成出力の等価SNRは $(|h_0|^2 + |h_1|^2)\frac{E_s}{\sigma^2}$ で、各経路のSNRをそのまま足し合わせた形になります(だから「最大比」合成と呼ばれ、これがダイバーシチ合成の中で最適です)。

ここでアラモウティの復号式 $\tilde{s}_1 = h_0^{*}r_0 + h_1 r_1^{*}$ を見比べてみてください。形がほとんどそっくりです。$h_0^{*}r_0$ という項はMRCと同一で、もう一方の $h_1 r_1^{*}$ もチャネル利得の共役を絡めて足し合わせるという同じ精神です。実際、合成後に得られる等価SNRはどちらも $(|h_0|^2 + |h_1|^2)\frac{E_s}{\sigma^2}$(電力配分の係数を除く)で完全に一致します。

つまりアラモウティ符号は、「受信側に2本アンテナを置いてMRCする」のと数学的に等価なダイバーシチ効果を、「送信側に2本アンテナを置いて時空間符号化する」ことで実現したのです。受信ダイバーシチを送信側に移し替えた——これがアラモウティ符号の最も美しい見方です。唯一の違いは前述の電力配分の係数 $1/2$ だけで、その分(約3dB)だけMRCに対して不利になりますが、ダイバーシチ次数(グラフの傾き)は完全に同じです。

この等価性を頭に入れた上で、いよいよPythonでBERを実測し、単一アンテナ・MRC・アラモウティの3者を同じ土俵で比べてみましょう。

Pythonによる実装とBERシミュレーション

送受信のシミュレータを実装する

まず、QPSKシンボルの生成、レイリーフェージングチャネル、そしてアラモウティの符号化・復号を行う基本部品を実装します。シンボルにはQPSK(4値)を使い、グレイマッピングで誤りを評価します。

import numpy as np
import matplotlib.pyplot as plt

rng = np.random.default_rng(0)

def qpsk_modulate(bits):
    """ビット列(偶数長)をグレイ符号QPSKシンボルに変換する。
    2ビットで1シンボル、平均電力1に正規化。"""
    b = bits.reshape(-1, 2)
    # 0 -> +1, 1 -> -1 を実部・虚部に割り当て、1/sqrt(2)で正規化
    i = 1 - 2 * b[:, 0]
    q = 1 - 2 * b[:, 1]
    return (i + 1j * q) / np.sqrt(2)

def qpsk_demodulate(symbols):
    """QPSKシンボルを硬判定でビット列に戻す。"""
    bits = np.zeros((len(symbols), 2), dtype=int)
    bits[:, 0] = (symbols.real < 0).astype(int)
    bits[:, 1] = (symbols.imag < 0).astype(int)
    return bits.reshape(-1)

ここではQPSKを採用しました。1シンボルあたり2ビットを実部・虚部に独立に乗せるため、判定は実部・虚部の符号を見るだけの単純な硬判定で済みます。平均電力を1に揃えておくことで、後でSNRを公平に設定できます。

アラモウティの符号化・復号と単一アンテナ・MRCを実装する

次に、3方式(単一アンテナ、アラモウティ $2\times1$、MRC $1\times2$)それぞれについて、1フレームの送受信を行う関数を書きます。電力配分の公平性のため、アラモウティでは2本のアンテナに電力を半分ずつ配分します。

def channel(n, sigma, rng):
    """レイリーフェージング係数(複素ガウス, 平均電力1)と雑音を返す。"""
    h = (rng.standard_normal(n) + 1j * rng.standard_normal(n)) / np.sqrt(2)
    noise = (rng.standard_normal(n) + 1j * rng.standard_normal(n)) / np.sqrt(2) * sigma
    return h, noise

def run_siso(syms, sigma, rng):
    """単一送信・単一受信(SISO)。各シンボルが独立にフェージング。"""
    h, n = channel(len(syms), sigma, rng)
    r = h * syms + n
    # チャネル等化(既知チャネルで割る = ZF/MRC等価, 単一なので位相補正)
    s_hat = np.conj(h) * r / np.abs(h) ** 2
    return s_hat

単一アンテナの場合は、受信信号をチャネルで割って位相と振幅を補正する(ゼロフォーシング)だけです。$|h|$ が小さい深い谷では雑音も増幅されてしまい、これが誤りの主因になります。

def run_alamouti(syms, sigma, rng):
    """2送信×1受信のアラモウティ符号。symsは偶数個。"""
    s1 = syms[0::2]
    s2 = syms[1::2]
    npair = len(s1)
    # 2本のアンテナへのチャネル(2時刻で一定と仮定し1組生成)
    h0 = (rng.standard_normal(npair) + 1j * rng.standard_normal(npair)) / np.sqrt(2)
    h1 = (rng.standard_normal(npair) + 1j * rng.standard_normal(npair)) / np.sqrt(2)
    # 電力を2本に半分ずつ配分
    scale = 1 / np.sqrt(2)
    n0 = (rng.standard_normal(npair) + 1j * rng.standard_normal(npair)) / np.sqrt(2) * sigma
    n1 = (rng.standard_normal(npair) + 1j * rng.standard_normal(npair)) / np.sqrt(2) * sigma
    # 受信信号 (時刻1: s1,s2 / 時刻2: -s2*, s1*)
    r0 = scale * (h0 * s1 + h1 * s2) + n0
    r1 = scale * (-h0 * np.conj(s2) + h1 * np.conj(s1)) + n1
    # 線形合成による復号
    s1_hat = np.conj(h0) * r0 + h1 * np.conj(r1)
    s2_hat = np.conj(h1) * r0 - h0 * np.conj(r1)
    out = np.empty(2 * npair, dtype=complex)
    out[0::2] = s1_hat
    out[1::2] = s2_hat
    return out

run_alamouti では、先ほど導出した復号式 $\tilde{s}_1 = h_0^{*}r_0 + h_1 r_1^{*}$、$\tilde{s}_2 = h_1^{*}r_0 – h_0 r_1^{*}$ をそのままコードに落としています。合成後は $(|h_0|^2+|h_1|^2)$ という正の実数倍が掛かるだけなので、QPSKの硬判定(符号を見るだけ)には影響せず、振幅で割らなくても正しく判定できます。

def run_mrc(syms, sigma, rng):
    """1送信×2受信のMRC(受信ダイバーシチ)。比較用。"""
    h0 = (rng.standard_normal(len(syms)) + 1j * rng.standard_normal(len(syms))) / np.sqrt(2)
    h1 = (rng.standard_normal(len(syms)) + 1j * rng.standard_normal(len(syms))) / np.sqrt(2)
    n0 = (rng.standard_normal(len(syms)) + 1j * rng.standard_normal(len(syms))) / np.sqrt(2) * sigma
    n1 = (rng.standard_normal(len(syms)) + 1j * rng.standard_normal(len(syms))) / np.sqrt(2) * sigma
    r0 = h0 * syms + n0
    r1 = h1 * syms + n1
    # 最大比合成
    s_hat = np.conj(h0) * r0 + np.conj(h1) * r1
    return s_hat

MRCは送信1本・受信2本で、両方の受信信号にチャネル共役を掛けて足すだけです。アラモウティと違って電力配分の $1/2$ がないため、同じダイバーシチ次数2でもアラモウティより約3dB良い性能になるはずです。3方式を同じ枠組みで実装できたので、次にBERを測定します。

BER対SNRを測定して比較する

各SNRで大量のビットを送り、誤りビット数を数えてBERを推定します。SNRは1ビットあたりのエネルギーと雑音電力密度の比 $E_b/N_0$ で表します。

def simulate_ber(method, ebn0_db_range, num_bits=2_000_000):
    """指定方式のBER対Eb/N0を測定する。"""
    bers = []
    bits_per_symbol = 2  # QPSK
    for ebn0_db in ebn0_db_range:
        ebn0 = 10 ** (ebn0_db / 10)
        # シンボル平均電力1, Es/N0 = Eb/N0 * bits_per_symbol
        esn0 = ebn0 * bits_per_symbol
        sigma = np.sqrt(1 / esn0)  # 複素雑音の各成分標準偏差スケール
        bits = rng.integers(0, 2, size=num_bits)
        syms = qpsk_modulate(bits)
        if method == 'siso':
            s_hat = run_siso(syms, sigma, rng)
        elif method == 'alamouti':
            s_hat = run_alamouti(syms, sigma, rng)
        elif method == 'mrc':
            s_hat = run_mrc(syms, sigma, rng)
        bits_hat = qpsk_demodulate(s_hat)
        ber = np.mean(bits != bits_hat)
        bers.append(max(ber, 1e-6))
    return bers

ebn0_db_range = np.arange(0, 26, 2)
ber_siso = simulate_ber('siso', ebn0_db_range)
ber_alamouti = simulate_ber('alamouti', ebn0_db_range)
ber_mrc = simulate_ber('mrc', ebn0_db_range)

このループでは、各 $E_b/N_0$ について200万ビットを送って誤り率を統計的に推定しています。雑音の標準偏差 $\sigma$ をSNRから逆算し、シンボル電力1との比を正しく設定している点が、3方式を公平に比較するうえで重要です。次にこれを両対数グラフで可視化します。

plt.figure(figsize=(8, 6))
plt.semilogy(ebn0_db_range, ber_siso, 'ks-', label='SISO (1x1, no diversity)')
plt.semilogy(ebn0_db_range, ber_alamouti, 'ro-', label='Alamouti (2x1 STBC)')
plt.semilogy(ebn0_db_range, ber_mrc, 'b^-', label='MRC (1x2 Rx diversity)')
plt.xlabel('$E_b/N_0$ [dB]')
plt.ylabel('BER')
plt.title('BER vs SNR: SISO vs Alamouti vs MRC (QPSK, Rayleigh)')
plt.grid(True, which='both', alpha=0.3)
plt.legend()
plt.ylim(1e-5, 1)
plt.tight_layout()
plt.show()

このグラフから、本記事の主張がすべて視覚的に確認できます。

  1. 傾き(ダイバーシチ次数)の違い: 単一アンテナ(SISO)の曲線は傾きが緩く、10dBごとに約1桁しかBERが下がりません(次数1)。一方アラモウティとMRCはどちらも傾きが約2倍急で、10dBごとに約2桁BERが下がります(次数2)。理論で導いた $d=2$ が実測で裏付けられました。
  2. アラモウティとMRCは平行: アラモウティとMRCの曲線は同じ傾きで、互いに約3dBずれて平行に走ります。傾きが同じ=ダイバーシチ次数が同じ(どちらも2)であり、3dBの差は電力配分の係数 $1/2$ に由来するものです。前節で示した「MRCとの等価性(係数を除く)」がそのまま現れています。
  3. 送信ダイバーシチの威力: アラモウティは受信アンテナ1本のままで、受信2本のMRCにわずか3dB差まで肉薄しています。端末を増やさず基地局側だけでこれだけの改善が得られることが、アラモウティ符号が広く採用された理由です。

等価SNRの分布を可視化して傾きの正体を見る

最後に、ダイバーシチ次数2の根拠だった「利得の二乗和 $|h_0|^2+|h_1|^2$ が原点付近で立ち上がりにくい」ことを、ヒストグラムで直接確認します。

N = 1_000_000
h = (rng.standard_normal(N) + 1j * rng.standard_normal(N)) / np.sqrt(2)
g_siso = np.abs(h) ** 2  # 単一: 指数分布
h0 = (rng.standard_normal(N) + 1j * rng.standard_normal(N)) / np.sqrt(2)
h1 = (rng.standard_normal(N) + 1j * rng.standard_normal(N)) / np.sqrt(2)
g_div = np.abs(h0) ** 2 + np.abs(h1) ** 2  # 和: 自由度4カイ二乗

plt.figure(figsize=(8, 5))
bins = np.linspace(0, 6, 120)
plt.hist(g_siso, bins=bins, density=True, alpha=0.5, label='SISO: $|h|^2$')
plt.hist(g_div, bins=bins, density=True, alpha=0.5,
         label='Diversity: $|h_0|^2+|h_1|^2$')
plt.axvline(0.1, color='r', ls='--', alpha=0.6, label='deep-fade region')
plt.xlabel('Channel power gain')
plt.ylabel('Probability density')
plt.title('Why diversity helps: gain distribution near zero')
plt.legend()
plt.tight_layout()
plt.show()

このヒストグラムから、ダイバーシチの本質が一目でわかります。単一アンテナの利得 $|h|^2$ は原点($x=0$)付近で密度が最も高く、深い谷(赤破線より左)に落ち込む確率が無視できません。一方、利得の和 $|h_0|^2+|h_1|^2$ は原点付近で密度がほぼゼロから立ち上がり、深い谷に落ちる確率が劇的に小さくなっています。この「原点で密度が $u^1$ で立ち上がる」性質こそが、BER曲線の傾きを倍(次数1→2)にしている正体です。理論の $f_u(u)\sim u$ がグラフの形として確認できました。

まとめ

本記事では、アラモウティ符号(空間時間ブロック符号)の理論と実装について解説しました。

  • 問題設定: 送信側でダイバーシチを取ろうとすると、同じシンボルを複数アンテナから送るだけでは信号が空中で打ち消し合い、かえって谷を作ってしまう。送信機がチャネルを知らずに受信側処理だけで解く必要があった
  • 符号化: 2シンボル $s_1, s_2$ を2時刻×2アンテナの送信行列 $\bm{S}=\begin{psmallmatrix} s_1 & s_2 \\ -s_2^{*} & s_1^{*}\end{psmallmatrix}$ に配置する。この行列は $\bm{S}^{H}\bm{S}=(|s_1|^2+|s_2|^2)\bm{I}$ という直交性を持つ
  • 復号: 時刻2の受信信号の共役を取って線形連立化すると、チャネル行列 $\bm{H}$ も $\bm{H}^{H}\bm{H}=(|h_0|^2+|h_1|^2)\bm{I}$ という直交性を持ち、$\tilde{s}_1=h_0^{*}r_0+h_1 r_1^{*}$、$\tilde{s}_2=h_1^{*}r_0-h_0 r_1^{*}$ という単純な線形合成で2シンボルが干渉なく分離される
  • ダイバーシチ: 等価SNRがチャネル利得の二乗和 $|h_0|^2+|h_1|^2$ に比例し、その分布が原点付近で $u^1$ で立ち上がるため、ダイバーシチ次数2(フルダイバーシチ)を達成する
  • MRCとの等価性: 復号式は受信ダイバーシチのMRCと同じ形をしており、電力配分の係数 $1/2$(約3dB)を除いて性能が一致する。受信ダイバーシチを送信側に移し替えたものと見なせる
  • 実装: QPSK・レイリーフェージング下のBERシミュレーションで、SISO(次数1)に対しアラモウティとMRC(ともに次数2)の傾きが急になることを確認した

アラモウティ符号は、わずか $2\times2$ の行列の直交性という一点の美しいアイデアで、送信ダイバーシチという難題を線形復号だけで解いた歴史的成果です。送信アンテナが3本以上になると、レート1のまま完全直交を保つ複素STBCは存在しないことが知られており(レート3/4などに落とす必要がある)、これがMIMOにおける多重化とダイバーシチのトレードオフという、より深いテーマへとつながっていきます。

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