スマートフォンの背面やWi-Fiルーターを覗くと、複数のアンテナが並んでいることに気づきます。なぜ1本ではなく何本も使うのでしょうか。素朴に考えれば「予備のアンテナ」や「感度を上げるため」のように思えますが、実際にはもっと驚くべきことが起きています。送信側と受信側の両方に複数のアンテナを置くと、同じ周波数・同じ時間スロットの中に、互いに干渉しない複数の独立した通信路を作り出せるのです。これがMIMO(Multiple-Input Multiple-Output)の空間多重であり、現代の無線通信が爆発的に高速化した最大の立役者です。
電波は本来、1つの周波数帯では1本の信号しか運べないように思えます。ところが空間という次元を使うと、電波の伝わり方の「多様性」を逆手にとって、あたかも複数の見えない配線を空中に張り巡らせたかのように複数のデータストリームを同時に流せます。この記事では、なぜそんなことが可能なのかを、MIMOチャネルを表す行列 $\bm{H}$ の特異値分解(SVD)から一歩ずつ導きます。そして、限られた送信電力をどのストリームに何ワット振り分けるのが最適か、という問題に対する美しい答え——注水定理(water-filling)——を導出し、Pythonで実際の容量を計算して可視化します。
MIMO空間多重を理解すると、以下のような分野への扉が開きます。
- 5G/6Gの大容量化: 5G NRのマッシブMIMO(基地局に数十〜数百本のアンテナを並べる技術)は、本記事の固有モード伝送とビームフォーミングを大規模化したものです
- 衛星通信・地上ネットワーク: 限られた周波数資源で伝送容量を最大化するため、複数アンテナによる空間多重が衛星や地上バックホールで活用されています
- Wi-Fi 6/7: 家庭用無線LANでも複数ストリームの空間多重(SU-MIMO/MU-MIMO)が標準化され、ギガビット級の速度を実現しています
- レーダー・測位: MIMOレーダーは複数の送受信素子を使って角度分解能を飛躍的に高めており、その数学的基盤は本記事のチャネル行列の議論と共通です
本記事の内容
- MIMOチャネルを行列 $\bm{H}$ で表す考え方と、空間多重の直感
- チャネル行列の特異値分解 $\bm{H} = \bm{U}\bm{\Sigma}\bm{V}^H$ による固有モードへの分解(導出を省略せず)
- MIMO容量 $C = \sum_i \log_2(1 + \lambda_i P_i / \sigma^2)$ の導出
- 送信電力制約下での最適電力配分——注水定理の導出
- Pythonでのレイリーフェージング容量、等電力 vs 注水、アンテナ本数スケーリング、アウテージ容量の可視化
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
- MIMOの基礎 — 複数アンテナがもたらす空間の自由度 — 複数アンテナシステムの基本概念とダイバーシチ・多重の違い
- 通信路容量とシャノンの定理 — シャノン容量 $C = \log_2(1+\mathrm{SNR})$ の意味と導出
- フェージングとダイバーシチ — 無線伝搬の確率的変動 — レイリーフェージングの統計的モデル
線形代数の特異値分解と固有値、複素ガウス確率変数の基本を前提とします。特に行列のランク、エルミート転置 $\bm{A}^H$、ユニタリ行列の性質を使うので、不安があれば線形代数の関連記事も併せて参照してください。
MIMOチャネルとは — 空間を配線に変える
まずは身近なアナロジーから入りましょう。1本のアンテナで通信するのは、1本の電話線で会話するようなものです。同じ瞬間に流せる情報は1人分です。では、送信側に2本、受信側に2本のアンテナを置くとどうなるでしょうか。直感的には「電話線が2本になった」ように思えますが、話はそう単純ではありません。なぜなら、送信アンテナ1から出た電波は受信アンテナ1だけでなく受信アンテナ2にも届き、すべてが混ざり合って受信されるからです。2本の電話線が途中で絡まり合って、声が混線しているような状況です。
ところがこの「混線」こそが鍵になります。送信アンテナから受信アンテナへの電波の伝わり方(各経路の振幅と位相)が経路ごとに異なっていれば、受信側で連立方程式を解くように混線を「ほどく」ことができます。2つの未知数(送信した2つの信号)に対して2つの式(2本の受信アンテナの観測値)があれば、原理的に解けるのです。これが空間多重の核心です。空間という次元の「散らばり具合」を利用して、見えない複数の配線を空中に作り出しているわけです。
MIMOシステムの数式モデル
送信アンテナを $N_t$ 本、受信アンテナを $N_r$ 本持つシステムを考えます。送信信号ベクトルを $\bm{x} \in \mathbb{C}^{N_t}$(各成分が各送信アンテナから出る複素ベースバンド信号)、受信信号ベクトルを $\bm{y} \in \mathbb{C}^{N_r}$ とすると、線形なフラットフェージング(周波数に依存しない一様な減衰)通信路は次のように書けます。
$$ \begin{equation} \bm{y} = \bm{H}\bm{x} + \bm{n} \end{equation} $$
ここで $\bm{H} \in \mathbb{C}^{N_r \times N_t}$ はチャネル行列と呼ばれ、その第 $(i,j)$ 成分 $h_{ij}$ は送信アンテナ $j$ から受信アンテナ $i$ への複素チャネル利得(振幅減衰と位相回転)を表します。$\bm{n} \in \mathbb{C}^{N_r}$ は受信機の熱雑音で、各成分が独立な複素ガウス雑音 $n_i \sim \mathcal{CN}(0, \sigma^2)$ に従うとします。
この式を成分で書き下すと、混線の様子がはっきりします。たとえば $N_t = N_r = 2$ なら
$$ \begin{pmatrix} y_1 \\ y_2 \end{pmatrix} = \begin{pmatrix} h_{11} & h_{12} \\ h_{21} & h_{22} \end{pmatrix} \begin{pmatrix} x_1 \\ x_2 \end{pmatrix} + \begin{pmatrix} n_1 \\ n_2 \end{pmatrix} $$
となり、各受信信号 $y_i$ が両方の送信信号 $x_1, x_2$ の線形結合になっていることがわかります。受信側で $\bm{x}$ を取り戻すには、この行列 $\bm{H}$ の構造を使う必要があります。
空間多重とダイバーシチの違い
ここで一つ整理しておきましょう。複数アンテナの使い方には大きく2つの方向性があります。一つはダイバーシチで、同じ情報を複数経路で送って受信信頼性を高める使い方です(フェージングとダイバーシチで扱いました)。もう一つが本記事の主役、空間多重で、異なる情報を複数経路に乗せて伝送速度(容量)を高める使い方です。前者は「保険を厚くする」、後者は「配線を増やす」イメージです。実際にはこの2つはトレードオフの関係にあり、同じアンテナ資源をどちらに振り分けるかという設計問題が生じますが、本記事では容量を最大化する空間多重に焦点を当てます。
混線をほどく鍵がチャネル行列 $\bm{H}$ の構造にあることがわかりました。次は、この行列を「独立した並列通信路」に分解する強力な道具——特異値分解——を導入します。
チャネル行列の特異値分解と固有モード
連立方程式を解くように混線をほどけると述べましたが、もっと美しい見方があります。チャネル行列 $\bm{H}$ を特異値分解(SVD: Singular Value Decomposition)すると、混線したMIMOチャネルが、互いに完全に独立した複数の「単一入力単一出力(SISO)チャネル」の束に変身するのです。この独立した各チャネルを固有モード(eigenmode)と呼びます。一見複雑に絡み合った行列が、対角行列という最もシンプルな形に「対角化」される——これは線形代数のもっとも実りある定理の一つです。
特異値分解の復習
任意の複素行列 $\bm{H} \in \mathbb{C}^{N_r \times N_t}$ は、次のように分解できます。
$$ \begin{equation} \bm{H} = \bm{U}\bm{\Sigma}\bm{V}^H \end{equation} $$
ここで各行列の意味は次のとおりです。
- $\bm{U} \in \mathbb{C}^{N_r \times N_r}$ はユニタリ行列($\bm{U}^H \bm{U} = \bm{U}\bm{U}^H = \bm{I}$)。左特異ベクトルを列に持ちます。
- $\bm{V} \in \mathbb{C}^{N_t \times N_t}$ もユニタリ行列($\bm{V}^H \bm{V} = \bm{V}\bm{V}^H = \bm{I}$)。右特異ベクトルを列に持ちます。
- $\bm{\Sigma} \in \mathbb{R}^{N_r \times N_t}$ は対角成分に特異値 $\sigma_1 \geq \sigma_2 \geq \dots \geq \sigma_r \geq 0$ を並べた(一般には長方形の)対角行列です。$r = \mathrm{rank}(\bm{H}) \leq \min(N_t, N_r)$ は非ゼロ特異値の個数です。
$\bm{V}^H$ は $\bm{V}$ のエルミート転置(複素共役を取って転置)です。ユニタリ行列は「長さと角度を保つ回転」のような変換であり、ベクトルのノルムを変えない($\|\bm{U}\bm{a}\| = \|\bm{a}\|$)という重要な性質を持ちます。この性質が後で雑音の統計を保つ鍵になります。
特異値 $\sigma_i$ と、行列 $\bm{H}^H \bm{H}$ の固有値 $\lambda_i$ の間には
$$ \lambda_i = \sigma_i^2 $$
という関係があります。実際、$\bm{H} = \bm{U}\bm{\Sigma}\bm{V}^H$ を代入すると
$$ \bm{H}^H \bm{H} = (\bm{U}\bm{\Sigma}\bm{V}^H)^H (\bm{U}\bm{\Sigma}\bm{V}^H) = \bm{V}\bm{\Sigma}^H \bm{U}^H \bm{U}\bm{\Sigma}\bm{V}^H $$
となります。ここで $\bm{U}^H \bm{U} = \bm{I}$ を使うと、中央の $\bm{U}^H\bm{U}$ が消えて
$$ \bm{H}^H \bm{H} = \bm{V}(\bm{\Sigma}^H \bm{\Sigma})\bm{V}^H = \bm{V}\,\mathrm{diag}(\sigma_1^2, \dots, \sigma_{N_t}^2)\,\bm{V}^H $$
が得られます。これは $\bm{H}^H\bm{H}$ の固有値分解そのものであり、固有値が $\sigma_i^2$、固有ベクトルが $\bm{V}$ の列であることがわかります。「固有モード」という呼び名は、まさにこの $\bm{H}^H\bm{H}$ の固有構造に由来しています。
プリコーディングと受信整形による対角化
ここからが空間多重の心臓部です。SVDを使って、送信側と受信側で次のような信号処理を行うことを考えます。送信側では、本当に送りたいデータストリーム $\bm{\tilde{x}} \in \mathbb{C}^{N_t}$ に対して右特異ベクトル行列 $\bm{V}$ を掛けてから送信します(プリコーディング)。
$$ \bm{x} = \bm{V}\bm{\tilde{x}} $$
受信側では、受信信号 $\bm{y}$ に左特異ベクトル行列のエルミート転置 $\bm{U}^H$ を掛けます(受信整形 / マッチドフィルタ)。
$$ \bm{\tilde{y}} = \bm{U}^H \bm{y} $$
この2つの操作を実際の通信路の式に代入してみましょう。まず受信信号は
$$ \bm{y} = \bm{H}\bm{x} + \bm{n} = \bm{H}\bm{V}\bm{\tilde{x}} + \bm{n} $$
です。ここに $\bm{H} = \bm{U}\bm{\Sigma}\bm{V}^H$ を代入すると
$$ \bm{y} = \bm{U}\bm{\Sigma}\bm{V}^H \bm{V}\bm{\tilde{x}} + \bm{n} $$
となります。$\bm{V}$ がユニタリなので $\bm{V}^H \bm{V} = \bm{I}$ であり、これが消えて
$$ \bm{y} = \bm{U}\bm{\Sigma}\bm{\tilde{x}} + \bm{n} $$
と簡潔になります。次に受信整形 $\bm{\tilde{y}} = \bm{U}^H \bm{y}$ を適用すると
$$ \bm{\tilde{y}} = \bm{U}^H (\bm{U}\bm{\Sigma}\bm{\tilde{x}} + \bm{n}) = \bm{U}^H \bm{U}\bm{\Sigma}\bm{\tilde{x}} + \bm{U}^H \bm{n} $$
となります。再び $\bm{U}^H \bm{U} = \bm{I}$ を使うと、ついに次の対角化された関係が得られます。
$$ \begin{equation} \bm{\tilde{y}} = \bm{\Sigma}\bm{\tilde{x}} + \bm{\tilde{n}}, \qquad \bm{\tilde{n}} = \bm{U}^H \bm{n} \end{equation} $$
$\bm{\Sigma}$ は対角行列なので、この式を成分ごとに書くと驚くべき結果が現れます。
$$ \tilde{y}_i = \sigma_i \tilde{x}_i + \tilde{n}_i, \qquad i = 1, 2, \dots, r $$
つまり、$i$ 番目のデータストリーム $\tilde{x}_i$ は他のストリームと一切干渉せず、利得 $\sigma_i$ の単一チャネルを通って受信されます。混線していたMIMOチャネルが、$r$ 個の独立した並列SISOチャネルに分解されたのです。これが固有モード伝送です。
雑音の統計は変わらない
一点、注意深く確認すべきことがあります。受信整形で雑音に $\bm{U}^H$ を掛けましたが、これによって雑音の性質が悪化していないでしょうか。実は心配無用です。$\bm{\tilde{n}} = \bm{U}^H \bm{n}$ の共分散行列を計算すると
$$ \mathbb{E}[\bm{\tilde{n}}\bm{\tilde{n}}^H] = \mathbb{E}[\bm{U}^H \bm{n}\bm{n}^H \bm{U}] = \bm{U}^H \mathbb{E}[\bm{n}\bm{n}^H]\bm{U} = \bm{U}^H (\sigma^2 \bm{I})\bm{U} = \sigma^2 \bm{U}^H \bm{U} = \sigma^2 \bm{I} $$
となります。途中で雑音の白色性 $\mathbb{E}[\bm{n}\bm{n}^H] = \sigma^2 \bm{I}$ とユニタリ性 $\bm{U}^H\bm{U} = \bm{I}$ を使いました。結果として、変換後の雑音 $\bm{\tilde{n}}$ も元と同じ分散 $\sigma^2$ の白色ガウス雑音のままです。ユニタリ変換が「回転」であり、ノルム(エネルギー)を保つことの恩恵です。雑音を増幅することなく、純粋にチャネルを対角化できたわけです。
これでMIMOチャネルが $r$ 本の独立したパイプに分かれました。各パイプの伝送能力はシャノンの定理で測れます。次に、これらを足し合わせてMIMO全体の容量を求めます。
MIMO容量の導出
独立した $r$ 本のSISOチャネルが手に入りました。1本のSISOチャネルが運べる情報量は、すでに通信路容量とシャノンの定理で学んだシャノンの公式で与えられます。複数の独立チャネルの容量は単純にその和になります——これは直感的にも自然で、互いに干渉しない配線の運べる情報量は別々に数えて足せばよいからです。この素直な足し算が、MIMOの容量公式の正体です。
各固有モードの容量
$i$ 番目の固有モードの受信信号は $\tilde{y}_i = \sigma_i \tilde{x}_i + \tilde{n}_i$ でした。このモードに割り当てる送信電力を $P_i = \mathbb{E}[|\tilde{x}_i|^2]$ とすると、受信側でのこのモードの信号対雑音比(SNR)は次のようになります。
$$ \mathrm{SNR}_i = \frac{\sigma_i^2 P_i}{\sigma^2} = \frac{\lambda_i P_i}{\sigma^2} $$
ここで分子は信号電力です。信号 $\sigma_i \tilde{x}_i$ の電力は $|\sigma_i|^2 \mathbb{E}[|\tilde{x}_i|^2] = \sigma_i^2 P_i = \lambda_i P_i$ となり、分母は雑音電力 $\sigma^2$ です。固有値 $\lambda_i = \sigma_i^2$ がそのままチャネル利得の二乗として効いてくるのがポイントです。利得の大きい($\lambda_i$ が大きい)固有モードほど高いSNRが得られます。
このモードが運べる容量は、複素ガウス通信路のシャノン容量より
$$ C_i = \log_2\left(1 + \frac{\lambda_i P_i}{\sigma^2}\right) \quad \text{[bit/s/Hz]} $$
です。単位はビット毎秒毎ヘルツ(スペクトル効率)で、帯域幅1Hzあたり1秒間に何ビット運べるかを表します。
MIMO全体の容量
$r$ 個の固有モードは互いに独立なので、全体の容量はそれぞれの和です。
$$ \begin{equation} C = \sum_{i=1}^{r} \log_2\left(1 + \frac{\lambda_i P_i}{\sigma^2}\right) \quad \text{[bit/s/Hz]} \end{equation} $$
これがMIMO空間多重の容量公式です。固有値が大きいモードが多いほど、そしてそこに適切に電力を配ればよいほど、容量が大きくなります。ここで一つ大きな問いが生まれます。送信機が使える総電力 $P$ は有限です。それを $r$ 本のモードにどう配分すれば容量 $C$ が最大になるのでしょうか。利得の大きいモードに全部つぎ込むべきか、均等に配るべきか——この最適化問題の答えが次節の注水定理です。
行列式による別表現
電力配分を考える前に、容量公式の見通しのよい別表現を示しておきます。送信信号の共分散行列を $\bm{Q} = \mathbb{E}[\bm{x}\bm{x}^H]$ とすると、MIMO容量は
$$ C = \log_2 \det\left(\bm{I} + \frac{1}{\sigma^2}\bm{H}\bm{Q}\bm{H}^H\right) $$
と書けます。固有モードに電力 $P_i$ を配る場合は $\bm{Q} = \bm{V}\,\mathrm{diag}(P_1, \dots, P_{N_t})\,\bm{V}^H$ に対応し、行列式が固有値の積に分解されることから、$\det$ の表現と $\sum \log_2$ の表現が一致することが確認できます。とくに送信機がチャネルを知らずに全電力を均等配分する場合($\bm{Q} = \frac{P}{N_t}\bm{I}$)には
$$ C_{\text{eq}} = \log_2 \det\left(\bm{I} + \frac{P}{N_t \sigma^2}\bm{H}\bm{H}^H\right) = \sum_{i=1}^{r} \log_2\left(1 + \frac{P}{N_t}\cdot\frac{\lambda_i}{\sigma^2}\right) $$
となります。この等電力配分は送信機がチャネル状態情報(CSI)を持たないときの標準的な選択です。一方、送信機がCSIを知っていれば、次に述べる注水でさらに容量を引き上げられます。
容量を最大化する電力配分問題が定式化できました。次はこれを制約付き最適化として解き、注水定理という美しい解を導きます。
注水定理 — 最適電力配分の導出
注水という言葉のイメージを先につかみましょう。$r$ 本の固有モードを、深さの異なる $r$ 個の容器が並んだ地形だと思ってください。利得の弱いモード($\lambda_i$ が小さい)ほど「底が深い」(雑音に対して不利な)容器です。ここに一定量の水(総電力)を注ぐと、水は低いところから順に溜まり、全体が同じ水位になります。底が浅い(利得が高い)容器ほどたくさん水が入り、深すぎる容器には水が一滴も入りません。この「水位を一定にする」配分が、実は容量を最大化する最適解なのです。利得の良いモードに優先的に電力を配り、利得が悪すぎるモードは諦める、という直感を数学が裏付けてくれます。
最適化問題の定式化
総送信電力 $P$ の制約のもとで容量を最大化する問題は、次のように書けます。
$$ \max_{P_1, \dots, P_r} \sum_{i=1}^{r} \log_2\left(1 + \frac{\lambda_i P_i}{\sigma^2}\right) \quad \text{subject to} \quad \sum_{i=1}^{r} P_i = P, \quad P_i \geq 0 $$
目的関数は各 $P_i$ について凹関数(対数は凹)であり、制約は線形なので、これは凸最適化問題です。したがってラグランジュの未定乗数法で大域最適解が求まります。
ラグランジュ未定乗数法による解
まず非負制約 $P_i \geq 0$ をいったん脇に置き、等式制約 $\sum_i P_i = P$ だけを考えてラグランジアンを作ります。
$$ \mathcal{L}(P_1, \dots, P_r, \mu) = \sum_{i=1}^{r} \log_2\left(1 + \frac{\lambda_i P_i}{\sigma^2}\right) – \mu\left(\sum_{i=1}^{r} P_i – P\right) $$
ここで $\mu$ はラグランジュ乗数です。各 $P_i$ で偏微分して0と置きます。対数の底を変換する $\log_2 z = \ln z / \ln 2$ を使い、$\ln(1 + a P_i)$($a = \lambda_i/\sigma^2$)を $P_i$ で微分すると $a/(1 + aP_i)$ なので
$$ \frac{\partial \mathcal{L}}{\partial P_i} = \frac{1}{\ln 2}\cdot\frac{\lambda_i / \sigma^2}{1 + \lambda_i P_i / \sigma^2} – \mu = 0 $$
となります。この式を $P_i$ について解いていきましょう。まず $\mu \ln 2$ を $\nu^{-1}$ とまとめて整理すると、左辺第1項は
$$ \frac{\lambda_i / \sigma^2}{1 + \lambda_i P_i / \sigma^2} = \mu \ln 2 $$
です。分母を払い、$\lambda_i/\sigma^2$ で両辺を割ると
$$ 1 + \frac{\lambda_i P_i}{\sigma^2} = \frac{\lambda_i / \sigma^2}{\mu \ln 2} = \frac{\lambda_i}{\sigma^2 \mu \ln 2} $$
が得られます。$\lambda_i P_i / \sigma^2$ について解くため両辺から1を引き、さらに $\sigma^2/\lambda_i$ を掛けると
$$ P_i = \frac{1}{\mu \ln 2} – \frac{\sigma^2}{\lambda_i} $$
となります。ここで定数項を $\nu \equiv \dfrac{1}{\mu \ln 2}$ とまとめると、最適電力配分は驚くほど簡潔な形になります。
$$ \begin{equation} P_i = \nu – \frac{\sigma^2}{\lambda_i} \end{equation} $$
非負制約と水位の解釈
上の式には欠陥があります。$\lambda_i$ がとても小さい(利得の弱い)モードでは $\sigma^2/\lambda_i$ が大きくなり、$P_i$ が負になってしまいます。電力が負というのは物理的にありえません。そこで非負制約 $P_i \geq 0$ を正しく扱うと(KKT条件から導かれます)、解は次の形になります。
$$ \begin{equation} P_i = \left(\nu – \frac{\sigma^2}{\lambda_i}\right)^+ = \max\left(0, \; \nu – \frac{\sigma^2}{\lambda_i}\right) \end{equation} $$
$(\cdot)^+$ は「負なら0にする」演算子です。この式こそが注水定理です。$\nu$ が「水位」、$\sigma^2/\lambda_i$ が各容器の「底の高さ」に対応します。底の高さが水位を超えるモード($\sigma^2/\lambda_i > \nu$、すなわち利得が悪すぎるモード)には電力を一切配りません($P_i = 0$)。底が水位より低いモードには、水位と底の差だけ電力を配ります。
水位 $\nu$ は総電力制約から決まります。電力を配るモードの集合を $\mathcal{A} = \{i : P_i > 0\}$ とすると、$\sum_{i \in \mathcal{A}} P_i = P$ より
$$ \sum_{i \in \mathcal{A}}\left(\nu – \frac{\sigma^2}{\lambda_i}\right) = P \quad\Longrightarrow\quad \nu = \frac{1}{|\mathcal{A}|}\left(P + \sum_{i \in \mathcal{A}}\frac{\sigma^2}{\lambda_i}\right) $$
という関係で $\nu$ が決まります。ただし $\mathcal{A}$ 自体が $\nu$ に依存するため、実際には「水位を仮定→電力が負になるモードを除外→再計算」という反復で求めます(後ほどPythonで実装します)。
高SNRと低SNRでの振る舞い
注水定理の意味を両極端の状況で確認しておきましょう。高SNR領域($P$ が非常に大きい)では、水位 $\nu$ が高くなり、ほとんどすべてのモードに水が行き渡ります。このとき配分はほぼ均等に近づき、容量は
$$ C \approx \sum_{i=1}^{r} \log_2\left(\frac{\lambda_i P / r}{\sigma^2}\right) \approx r \log_2\left(\frac{P}{r\sigma^2}\right) + \sum_i \log_2 \lambda_i $$
のように振る舞います。注目すべきは先頭の係数 $r$ で、容量は送信電力の対数に比例しつつ、その傾きがモード数(ランク)$r$ 倍になるという点です。これがMIMOの多重利得(multiplexing gain)です。アンテナを増やしてランクを上げれば、同じ電力増加に対する容量の伸びが何倍にもなるわけです。
一方低SNR領域($P$ が小さい)では、水位が低く、最大固有値 $\lambda_1$ を持つ1本の最強モードにだけ水が入ります。残りのモードは底が水面より上にあって電力ゼロです。このとき容量は
$$ C \approx \log_2\left(1 + \frac{\lambda_1 P}{\sigma^2}\right) $$
となり、実質的に最強の固有モードへ全電力を注ぐビームフォーミング(送信ビーム形成)に一致します。電力が乏しいときは「あれもこれも」ではなく「最良の1本に集中」が正解だという、直感に合う結論です。
理論はこれで完成しました。固有モード分解、容量公式、注水定理がそろいました。あとは実際に数値で確かめましょう。次節ではPythonでレイリーフェージングのチャネルを大量に生成し、これらの結論を可視化します。
Pythonによる実装と可視化
ここまでの理論を、コードで一つずつ確かめます。実際のチャネル行列はランダムに変動するので、レイリーフェージング(各成分が独立な複素ガウス)を仮定して多数のチャネルを生成し、その統計的な振る舞いを見ます。まず基本となる「SVD→固有値→容量」の流れを実装します。
チャネル行列のSVDと固有モード
最初に、ランダムなチャネル行列を1つ作り、SVDで固有モードに分解して特異値を確認します。
import numpy as np
np.random.seed(0)
def rayleigh_channel(Nr, Nt):
"""レイリーフェージングのMIMOチャネル行列を生成
各成分は独立な複素ガウス CN(0,1): 実部・虚部が N(0, 1/2)"""
real = np.random.randn(Nr, Nt)
imag = np.random.randn(Nr, Nt)
return (real + 1j * imag) / np.sqrt(2)
# 4x4 MIMOチャネルを生成
Nr, Nt = 4, 4
H = rayleigh_channel(Nr, Nt)
# 特異値分解 H = U Σ V^H
U, s, Vh = np.linalg.svd(H)
print("特異値 σ_i:", np.round(s, 4))
print("固有値 λ_i = σ_i^2:", np.round(s**2, 4))
print("ランク:", np.linalg.matrix_rank(H))
# 対角化の検証: U^H H V が対角(=Σ)になるか
Sigma_check = U.conj().T @ H @ Vh.conj().T
print("U^H H V の対角成分:", np.round(np.abs(np.diag(Sigma_check)), 4))
print("非対角成分の最大絶対値:", np.round(np.max(np.abs(Sigma_check - np.diag(np.diag(Sigma_check)))), 6))
このコードの出力から、理論が正しく成り立っていることが確認できます。特異値 $\sigma_i$ は降順に並び、その二乗が固有値 $\lambda_i$ になっています。U^H H V を計算すると対角成分だけに値が残り、非対角成分はほぼ0(数値誤差レベル)になっています。これは式 (3) で導いた $\bm{\tilde{y}} = \bm{\Sigma}\bm{\tilde{x}} + \bm{\tilde{n}}$ の対角化が実際に起きていることの直接的な証拠です。4本のアンテナで4つの独立した固有モードが得られ、それぞれの利得 $\lambda_i$ がはっきり異なる(強いモードと弱いモードがある)点も読み取れます。
注水アルゴリズムの実装
次に、固有値 $\lambda_i$ が与えられたときの最適電力配分(注水)を実装します。前述の「水位を仮定→負のモードを除外→再計算」という反復で水位 $\nu$ を求めます。
import numpy as np
def waterfilling(gains, P_total):
"""注水定理による最適電力配分
gains: 各固有モードの λ_i / σ^2 (実効SNR係数)
P_total: 総送信電力
戻り値: 各モードへの配分電力 P_i"""
inv_gains = 1.0 / gains # 各容器の「底の高さ」 σ^2/λ_i
idx = np.argsort(inv_gains) # 底の浅い(利得が高い)順
inv_sorted = inv_gains[idx]
n = len(gains)
# 強いモードから順に使い、水位が底を超えないモードだけ残す
for k in range(n, 0, -1):
# 上位k本だけ使うと仮定したときの水位
nu = (P_total + np.sum(inv_sorted[:k])) / k
# k本目(最も底が高い使用モード)で電力が非負ならこの構成が最適
if nu - inv_sorted[k-1] >= 0:
break
P = np.zeros(n)
P_sorted = np.maximum(nu - inv_sorted, 0)
P[idx] = P_sorted
return P, nu
# 例: 4つの固有モードに総電力P=10を配分
lam = np.array([5.0, 2.0, 0.5, 0.05]) # 固有値 λ_i
sigma2 = 1.0 # 雑音電力 σ^2
gains = lam / sigma2
P, nu = waterfilling(gains, P_total=10.0)
print("水位 ν =", np.round(nu, 4))
print("配分電力 P_i =", np.round(P, 4))
print("配分の合計 =", np.round(P.sum(), 4))
print("各モード容量 [bit/s/Hz]:", np.round(np.log2(1 + gains * P), 4))
出力を見ると、注水の本質がよく現れています。固有値が最も大きいモード($\lambda_1 = 5$)に最も多くの電力が配分され、最も弱いモード($\lambda_4 = 0.05$、底の高さ $\sigma^2/\lambda_4 = 20$)には電力が一切配分されず $P_4 = 0$ になっているはずです。配分された電力の合計はきちんと総電力10に一致しており、制約が満たされています。利得の悪いモードを「諦める」ことで、限られた電力をより有効に使っているのです。
等電力配分 vs 注水配分の容量比較
送信機がチャネルを知っている場合(注水)と知らない場合(等電力)で、容量がどれだけ変わるかを、SNRを変えながら比較します。多数のチャネルで平均を取ったエルゴード容量を計算します。
import numpy as np
def mimo_capacity(H, snr_linear, mode='waterfilling'):
"""1つのチャネル行列に対するMIMO容量を計算
snr_linear: 総送信電力P / 雑音σ^2 (ここではσ^2=1, P=snr_linear)"""
s = np.linalg.svd(H, compute_uv=False)
lam = s**2
sigma2 = 1.0
P_total = snr_linear # σ^2=1 と正規化
gains = lam / sigma2
if mode == 'equal':
Nt = H.shape[1]
P = np.full(len(lam), P_total / Nt) # 全Ntアンテナに均等
return np.sum(np.log2(1 + gains * P))
else: # waterfilling
P, _ = waterfilling(gains, P_total)
return np.sum(np.log2(1 + gains * P))
# エルゴード容量(多数チャネル平均)をSNRごとに計算
Nr, Nt = 4, 4
snr_db = np.arange(-5, 26, 2)
n_trials = 2000
C_eq, C_wf = [], []
for sdb in snr_db:
snr = 10**(sdb/10)
ceq = cwf = 0.0
for _ in range(n_trials):
H = rayleigh_channel(Nr, Nt)
ceq += mimo_capacity(H, snr, 'equal')
cwf += mimo_capacity(H, snr, 'waterfilling')
C_eq.append(ceq/n_trials)
C_wf.append(cwf/n_trials)
このコードでは、各SNR点について2000個のランダムチャネルを生成し、等電力配分と注水配分それぞれの容量を平均しています。結果は次の可視化コードで描きます。
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 5))
plt.plot(snr_db, C_wf, 'o-', label='Water-filling (CSI at Tx)')
plt.plot(snr_db, C_eq, 's--', label='Equal power (no CSI at Tx)')
plt.xlabel('SNR $P/\\sigma^2$ (dB)')
plt.ylabel('Ergodic capacity (bit/s/Hz)')
plt.title('4x4 MIMO: Water-filling vs Equal power allocation')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
このグラフから、3つの重要な特徴が読み取れます。第一に、低SNR領域では注水が等電力より明確に優れています。電力が乏しいときは最強モードに集中する注水が効くのに対し、等電力は利得の悪いモードにも無駄に電力を配ってしまうためです。第二に、高SNR領域では両者の差がほとんど消えます。水位が十分高くなるとどのモードにも水が行き渡り、注水の配分が等電力に近づくからです。第三に、容量曲線はSNR(dB)に対してほぼ直線的に増加し、その傾きが大きいことです。これは前節で導いた「高SNRで容量がランク $r$ 倍の傾きで伸びる」という多重利得の現れです。
アンテナ本数に対する容量スケーリング
MIMOの最大の魅力は、アンテナを増やすほど容量が伸びることです。$N \times N$ のMIMO($N_t = N_r = N$)について、$N$ を変えながら容量を見てみましょう。
import numpy as np
import matplotlib.pyplot as plt
snr_db = 15
snr = 10**(snr_db/10)
N_list = [1, 2, 3, 4, 6, 8]
n_trials = 2000
C_vs_N = []
for N in N_list:
c = 0.0
for _ in range(n_trials):
H = rayleigh_channel(N, N)
c += mimo_capacity(H, snr, 'waterfilling')
C_vs_N.append(c/n_trials)
plt.figure(figsize=(8, 5))
plt.plot(N_list, C_vs_N, 'o-', label='MIMO ergodic capacity')
# 比較: 容量がNに線形比例する参照線(N=1の容量を基準)
plt.plot(N_list, [C_vs_N[0]*N for N in N_list], 'k--',
alpha=0.6, label='Linear reference (N × SISO)')
plt.xlabel('Number of antennas N (NxN MIMO)')
plt.ylabel('Ergodic capacity (bit/s/Hz)')
plt.title(f'Capacity scaling with antennas (SNR={snr_db} dB)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
このグラフから、MIMOの容量がアンテナ本数 $N$ に対してほぼ線形に増加することが読み取れます。1本のアンテナ(SISO)の容量を基準にした破線($N$ 倍の参照線)とMIMO容量がよく一致しており、$N \times N$ のMIMOは原理的にSISOの $N$ 倍の容量を運べることがわかります。これは固有モードが $N$ 本に増え、それぞれが独立な配線として働くためです。アンテナを倍にすれば容量も倍になる——周波数も時間も増やさずに、空間という次元だけで通信速度を増やせるという、MIMOの本質的な威力がここに表れています。
アウテージ容量の可視化
これまではチャネルを平均したエルゴード容量を見てきましたが、実際の無線では「ある瞬間のチャネル」が悪いと通信が破綻します。そこで重要になるのがアウテージ容量(outage capacity)です。これは「確率 $1 – p$ で達成できる容量」、言い換えると「下位 $p$ の悪いチャネルを切り捨てたときに保証できる容量」です。たとえば $p = 0.1$ のアウテージ容量とは、90%の確率でその速度を達成できる、という保証値です。
import numpy as np
import matplotlib.pyplot as plt
Nr, Nt = 4, 4
snr_db = 15
snr = 10**(snr_db/10)
n_trials = 20000
# 多数チャネルの瞬時容量を集める(等電力配分でCSIなしの典型)
caps = np.array([mimo_capacity(rayleigh_channel(Nr, Nt), snr, 'equal')
for _ in range(n_trials)])
# 累積分布関数(CDF)を描く
caps_sorted = np.sort(caps)
cdf = np.arange(1, n_trials+1) / n_trials
plt.figure(figsize=(8, 5))
plt.plot(caps_sorted, cdf, '-', lw=2)
# 10%アウテージ容量(CDF=0.1となる容量)
C_out10 = np.percentile(caps, 10)
plt.axhline(0.1, color='r', ls='--', alpha=0.6)
plt.axvline(C_out10, color='r', ls='--', alpha=0.6,
label=f'10% outage capacity = {C_out10:.2f}')
plt.axvline(caps.mean(), color='g', ls=':', alpha=0.8,
label=f'Ergodic (mean) = {caps.mean():.2f}')
plt.xlabel('Instantaneous capacity (bit/s/Hz)')
plt.ylabel('CDF $P(C \\leq c)$')
plt.title(f'4x4 MIMO capacity CDF & outage (SNR={snr_db} dB)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
このグラフから、アウテージ容量の意味がはっきり読み取れます。横軸が瞬時容量、縦軸がその累積分布です。赤い破線が示す10%アウテージ容量は、CDFが0.1になる点の容量値で、「10%の確率でこれを下回る(=90%の確率で達成できる)」保証速度を表します。緑の点線で示したエルゴード容量(平均)よりもアウテージ容量が低いことに注目してください。チャネルが運悪く悪化したときでも通信を維持したいなら、平均ではなくこの保証値を基準に伝送レートを設計する必要があります。CDF曲線の傾きが急なほどチャネル変動が小さく安定しており、アンテナ本数を増やすとこの曲線は急峻になって(チャネル硬化, channel hardening)アウテージ容量が平均に近づきます。これもMIMOの隠れた利点です。
固有値分布と注水の様子
最後に、レイリーフェージングチャネルの固有値がどう分布し、注水がどう電力を配るかを直接見てみましょう。
import numpy as np
import matplotlib.pyplot as plt
Nr, Nt = 4, 4
n_trials = 5000
all_lam = []
for _ in range(n_trials):
H = rayleigh_channel(Nr, Nt)
s = np.linalg.svd(H, compute_uv=False)
all_lam.append(np.sort(s**2)[::-1]) # 降順
all_lam = np.array(all_lam)
fig, axes = plt.subplots(1, 2, figsize=(13, 5))
# 左: 各順位の固有値の分布
for i in range(4):
axes[0].hist(all_lam[:, i], bins=60, alpha=0.5,
density=True, label=f'$\\lambda_{i+1}$')
axes[0].set_xlabel('Eigenvalue $\\lambda_i$')
axes[0].set_ylabel('Probability density')
axes[0].set_title('Eigenvalue distribution (4x4 Rayleigh)')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# 右: ある1つのチャネルでの注水の様子
np.random.seed(7)
H = rayleigh_channel(4, 4)
lam = np.sort(np.linalg.svd(H, compute_uv=False)**2)[::-1]
gains = lam / 1.0
P, nu = waterfilling(gains, P_total=4.0)
floor = 1.0 / gains # 底の高さ σ^2/λ_i
x = np.arange(1, 5)
axes[1].bar(x, floor, color='lightgray', label='Noise floor $\\sigma^2/\\lambda_i$')
axes[1].bar(x, P, bottom=floor, color='steelblue', label='Allocated power $P_i$')
axes[1].axhline(nu, color='r', ls='--', label=f'Water level $\\nu$={nu:.2f}')
axes[1].set_xlabel('Eigenmode index $i$')
axes[1].set_ylabel('Level')
axes[1].set_title('Water-filling power allocation')
axes[1].set_xticks(x)
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
このグラフは注水定理を視覚的に完璧に表現しています。左図の固有値分布を見ると、最大固有値 $\lambda_1$ は大きな値に広く分布する一方、最小固有値 $\lambda_4$ は0付近に集中しています。これはレイリーフェージングチャネルでは強い固有モードと弱い固有モードの差が大きいことを示しており、だからこそ電力配分が効くのです。右図はまさに「水を注ぐ」絵です。灰色のバーが各モードの底の高さ($\sigma^2/\lambda_i$、利得が悪いほど高い)、青いバーがそこに注がれた電力、赤い破線が水位 $\nu$ です。底の低いモード(利得が高いモード)ほど多くの水が入り、底が水位を超えるモードには水が入っていないことが一目でわかります。すべての青いバーの上端が水位 $\nu$ でぴったり揃っているのが、注水が「水平を保つ配分」であることの証拠です。
まとめ
本記事では、MIMO空間多重と容量、そして固有モード伝送について、数式の導出からPython実装まで一気通貫で解説しました。
- 空間を配線に変える: 送受信に複数アンテナを置くと、チャネル行列 $\bm{H}$ を通じた混線を逆手にとり、同じ周波数・時間で複数の独立データストリームを伝送できます。これが空間多重です
- 固有モードへの分解: チャネル行列のSVD $\bm{H} = \bm{U}\bm{\Sigma}\bm{V}^H$ を使い、送信側でプリコーディング $\bm{x} = \bm{V}\bm{\tilde{x}}$、受信側で整形 $\bm{\tilde{y}} = \bm{U}^H\bm{y}$ を行うと、MIMOチャネルが $r$ 本の独立したSISOチャネル $\tilde{y}_i = \sigma_i \tilde{x}_i + \tilde{n}_i$ に対角化されます。ユニタリ変換が雑音統計を保つことが鍵でした
- 容量公式: 各固有モードの容量の和として $C = \sum_i \log_2(1 + \lambda_i P_i/\sigma^2)$ が得られ、固有値 $\lambda_i = \sigma_i^2$ がチャネル利得として効きます
- 注水定理: 総電力制約のもとで容量を最大化する配分は $P_i = (\nu – \sigma^2/\lambda_i)^+$ という「水を注ぐ」形になります。利得の良いモードに優先的に電力を配り、悪すぎるモードは諦めるのが最適です
- 数値で確認: レイリーフェージングのシミュレーションで、低SNRでの注水の優位性、アンテナ本数に対する容量の線形スケーリング(多重利得)、アウテージ容量とチャネル硬化を可視化しました
MIMO空間多重は、周波数も時間も増やさずに「空間」という次元だけで通信容量を倍々に増やせるという、無線通信における革命的なアイデアです。本記事で扱った $4\times4$ 程度のMIMOを、基地局に数十〜数百本のアンテナを並べる規模に拡張したものがマッシブMIMOであり、5G/6Gの中核技術となっています。固有モード伝送と注水という基礎を押さえておけば、より高度なビームフォーミング、マルチユーザMIMO、ミリ波MIMOといった発展トピックへも自然に進めます。
次のステップとして、以下の記事も参考にしてください。
- MIMOの基礎 — 複数アンテナがもたらす空間の自由度 — 本記事の前提となるMIMOの全体像
- 通信路容量とシャノンの定理 — 容量公式の源流となるシャノン理論
- フェージングとダイバーシチ — 無線伝搬の確率的変動 — 空間多重と対になるダイバーシチの考え方