何の話かと言うと
量子計算の説明で必ず出てくるのが、 といったヘソマーク
を用いた積(テンソル積)です。テンソル積の定義にはいくつかの方法(流派?)があり、個人的には、双対空間を用いた多重線型写像として定義するのがいちばんスッキリするのですが、数学的な厳密性にこだわらない方むけには、いまいち抽象的すぎて、遠回りな説明に感じられるかも知れません。
そこでここでは、一番ベタな「数ベクトル」による、基底を用いた定義を使って、テンソル積を説明してみます。
1階のテンソル
量子計算の話を念頭に置いて、2次元の複素ベクトル空間で話を進めます。まずは、2個の複素数を縦にならべた「縦ベクトル」を考えます。
一般には、これは、「複素数ベクトル」と呼ばれるものですが、ここでは、これに「1階のテンソル」という別名を与えます。
また、これを転置して横に数字を並べて、さらに、各成分の複素共役をとったものを考えます。
一般に、このような操作(転地して複素共役をとる)を「エルミート共役」といいます。このような「横ベクトル」もまた、「1階のテンソル」です。
ただし、縦ベクトルと横ベクトルを区別するために、縦ベクトルを「(0, 1) 型テンソル」、横ベクトルを「(1, 0) 型テンソル」と呼ぶこともあります。
さらに、縦ベクトルと横ベクトルのそれぞれについて、次のベクトルを標準的な基底ベクトルとして採用します。
は「ケット記号」、
は「ブラ記号」と呼ばれるもので、妙な形に見えますが、ここでは、縦ベクトルと横ベクトルを表す一般的な記号(ラベル)だと思ってください。(高校の数学の教科書だと、
などと表されるやつですね。)
基底ベクトルというのは、任意のベクトル
--- (1)
が、次のように、これらの線形結合で表されるということです。
ちなみに、 はギリシャ文字の「プサイ」で、量子力学では一般のベクトルを表す記号としてよく用いられます。
内積
2つの1階のテンソル、より正確に言うと、(0, 1) 型テンソルと (1, 0) 型テンソルの間に内積が定義されます。具体的には、
に対して、これらの内積が次で計算されます。
つまり、内積というのは、(0, 1) 型テンソルと (1, 0) 型テンソルから、1つの複素数値(スカラー)を計算するルールになります。
また、(0, 1) 型テンソル について、自分自身のエルミート共役
と内積を取ると、次の結果が得られます。
この結果は、必ず(非負の)実数値になるので、平方根を計算することができます。実際に平方根をとった値を の「大きさ」と言って、次の記号で表します。
(補足:『内積というのは、同じベクトル空間の要素(今の場合で言うと (0, 1) 型テンソル)同士で計算するものなので、 は、「
と
の内積」ではなくて、「
と
の内積」ではないか』という指摘をいただきました。確かにその通りかも知れません・・・。上記の記述は、厳密には、『
と
について、
のエルミート共役を取って
に変換して、
を計算したものを「
と
の内積」と呼ぶ』と理解してください。)
テンソル積
ここでいよいよテンソル積が登場します。まず、(0, 1) 型テンソルの2つの基底 について、任意の2つを組み合わせてヘソマーク
でくっつけたペア
を考えます。抽象的に話を進めるなら、「合計4個あるこれらの組を基底ベクトルとする、新たなベクトル空間を定義する」と言えばよいのですが、ここでは、がんばって、数ベクトルの世界のままで話をすすめます。
どういうことかと言うと・・・
基底ベクトル は、第 i 成分のみが 1 の数ベクトルでした。それと同様にして、
は、第 (i, j) 成分のみが 1 の「ほげほげ」と考えます。
??????
「ほげほげ」って何でしょう? 今の場合、成分を表す足が2本あるので、これは行列ですね。つまり、次のようにして基底ベクトルのテンソル積を定義します。
すると、任意の 行列
は、これらの線形結合で表すことができます。
--- (2)
つまり、複素数を成分とする 行列全体は、
を基底ベクトルとする、4次元の複素ベクトル空間を構成しており、これを「2階のテンソル」、より正確には、「(0, 2) 型テンソル」と言います。
また、(0, 2) 型テンソル に対して、エルミート共役を取った行列
を「(2, 0) 型テンソル」と言います。 はエルミート共役を示す記号で「ダガー」と読みます。
そして、(2, 0) 型テンソルについては、次の4つが基底ベクトルとなります。
これにより、(2) の に対して、エルミート共役
は、次のように展開されることがわかります。
--- (3)
1階のテンソルの場合、(0, 1) 型テンソルは縦ベクトル、(1, 0) 型テンソルは横ベクトルという見た目の違いがありますが、2階のテンソルでは、(0, 2) 型と (2, 0) 型はどちらも 行列で、見た目では違いがわからないので注意が必要です。2階のテンソルを表記する際は、行列の形で表すのではなく、(2) (3) のように基底ベクトルを明示的に示すほうが安全です。
もしくは、量子力学の流儀に従うならば、2階のテンソルについても、ブラケット記号を用いて、
と表しても構いません。 この場合、ケット記号であれば (0, 2) 型テンソル、ブラ記号であれば (2, 0) 型テンソルと判断することができます。
・・・・え? こんな書き方だと、そもそも1階のテンソルと2階のテンソルが区別できないですって?
はい。そのとおりです。まぁ、すべて一長一短あるということなんです。。。。
2階のテンソルの内積
(0, 2) 型テンソルと (2, 0) 型テンソルの間にも内積が定義されますが、これは、「行列の積」で計算されるわけではありません。行列の各成分について、個別に積を取ったものの和になります。具体的に言うと、
に対して、
と計算されます。この時、 は正規直交系になることがわかります。つまり、次の関係が成り立ちます。
2階のテンソルの「フラット」な表記
先ほどの内積の例を見ると、2階のテンソルは 行列として表されるものの、それぞれの成分は「対等」な関係にあるような気分にもなります。(0, 2) 型テンソルというのは、結局のところ、4つの基底ベクトルを持つ、4次元の複素ベクトル空間にすぎないのです。そこで、4つの基底ベクトルに対して、次のように、0 〜 3 の通し番号を振ってしまいます。
すると、任意の (0, 2) 型テンソルは、次のように展開することができます。
さらに、この時の係数 を縦に並べたものを
と同一視してしまいます。
--- (4)
これは、大元の行列表記から考えると、成分を並べる順番を行列形式から縦ベクトル形式に変えただけで、本質的な違いはありません。つまり、(2) の (0, 2) 型テンソルであれば、
--- (5)
という関係が成り立ちます。(4)(5) を見比べると、これは、 という2つの添字のペアを2進数で2桁の数字とみなして、
という値の1つの添字に置き換えたものと考えることもできるでしょう。
実を言うと、量子力学ではあまりこのような表記は用いないのですが、量子計算の教科書では、このような「フラット」な表記がよく用いられるようです。
補足: (0, 2) 型テンソルを (4) や (5) のように表記すると、一瞬、(0, 1) 型テンソルに変換されたような気分になるかもしれませんが、そのような事はありません。これらは、あくまで成分を並べる順序を変えただけで、(0, 2) 型テンソルであるという事実は変わりありません。(・・・というような、見た目の違いによる誤解を避けるには、やはり、多重線形写像としてテンソルを定義した方がいいんですけどね・・・)
(0, 1) 型テンソルのテンソル積は、(0, 2) 型テンソルを網羅しない
さて、ここでちょっとだけ脱線して、表題の点について補足しておきます。
先ほどの説明では、(0, 1) 型テンソルについて「基底ベクトル同士のテンソル積」は定義しましたが、一般の (0, 1) 型テンソル同士のテンソル積は定義していませんでした。これについては、次のように自然な形で定義することができます。すなわち、
に対して、これらのテンソル積は次で与えられます。
行列形式で成分表示すると次のようになります。
もしくは、先ほどのフラットな形式なら次になります。
この時、任意の (0, 2) 型テンソル に対して、
--- (6)
となる (0, 1) 型テンソルのペアを見つけることができるか、という問題を考えてみます。実は、一般には、これは不可能です。たとえば、
について、(6) を満たす が存在しないことは、簡単な計算ですぐにわかります。これは言い換えると、(0, 2) 型テンソル全体の空間は、(0, 1) 型テンソルのテンソル積全体よりも真に大きな空間になっているということです。
補足:もちろん、(0, 1) 型テンソルのテンソル積を取ったもの を複数集めて、それらの線形結合をとれば、(0, 2) 型テンソル全体を張ることは可能です。たとえば、(0, 1) 型テンソルの基底ベクトルのテンソル積(4種類)を全部あつめて、それらの線形結合を取れば、自明に (0, 2) 型テンソル全体が得られます。
(0, 2) 型テンソルの線形写像
(0, 1) 型のテンソル、すなわち、(1) の縦ベクトルに対して、 行列
を左から演算すると、これは、線形写像(一次変換)を与えます。
ここで、
と置いて、成分計算をべた書きすると次のようになります。
--- (7)
次に、この考え方を (0, 2) 型のテンソルに適用します。つまり、(0, 2) 型テンソルを(0, 2) 型テンソルに変換する線形写像を考えてみます。一般に、線形写像というのは、基底ベクトルに対する像が決まれば、その他のベクトルに対する像は自動的に決まります。そこで、線形写像 による、基底ベクトル
の像を次のように定義します。
添字が4つもある謎の変数 が登場しましたが、とりあえず、深く考えずに計算を進めます。
この時、一般の (0, 2) 型テンソル
の像は、 の線形性を用いて次のように計算されます。
したがって、一般に、
と置くと、上記の結果は、次のように成分表示することができます。
--- (8)
そして・・・、ここで、以前に説明した「フラットな表記」を思い出してみましょう。フラットな表記というのは、「 という2つの添字のペアを2進数で2桁の数字とみなして、
という値の1つの添字に置き換えたもの」と考えることができました。上記の計算において、
と
をそれぞれ1つの添字と思い直せば、これは、通常の行列による一次変換と同じものになります。
ここに、 であり、
は、まさに、(4) に示した「フラットな表記」と同じものになります。
一方、 を成分とする行列
ともとの4つ足成分
の関係は、次のようになります。
--- (9)
線形写像のテンソル積
さぁいよいよ話は大詰めです。まず、先ほどは、(0, 2) 型テンソルに対する線形写像は、フラットな表記を用いると、 行列で表されることを示しました。
一方、2つの (0, 1) 型テンソルのテンソル積によって、(0, 2) 型テンソルが得られるという話もありました。実はこれと同様に、「(0, 1) 型テンソルに対する2つの線形写像から、(0, 2) 型テンソルに対する線形写像を構成する」ことができます。具体的に言うと、今、(0, 1) 型テンソルに対する、次の2つの線形写像があるものとします。
ここでは、基底ベクトルに対する像を示していますが、これは成分表記すると、(7) の行列計算と同じものになります。(具体的な確認は読者の宿題とします。成分を変換する計算 (7) と、ここの基底を変換する計算では、行列 のどちらの足で和をとるかが反対になるので注意してください。)
この時、(0, 2) 型テンソルに対する線形写像 を次で定義します。
ここでもまた、基底ベクトルに対する像だけを示していますが、これを用いて、一般の
に対する像を計算すると、次のようになります。
したがって、
と置いて成分表示すると、次の結果が得られます。
これを以前に求めた (8) と比較すると、次の関係によって、一般の線形写像 に対応付けられることがわかります。
ここで最後に (9) の関係を用いて、 をフラットな
行列で書き直してみます。添字の位置によく注意すると、次の結果が得られます。
--- (10)
添字の位置がなんだか複雑に見えますが、実は、次のようなルールがあります。
行列を4つの
行列のブロックに分けて考えます。この時、各ブロックには、すべて、
のコピーが埋め込まれています。一方、
の各成分は、4ヶ所のブロックに分散配置されています。
なお、「(0, 1) 型テンソルのテンソル積は、(0, 2) 型テンソルを網羅しない」での話と同様に、「(0, 1) 型テンソルの線形写像のテンソル積」は、(0, 2) 型テンソルの線形写像になりますが、あらゆる (0, 2) 型テンソルの線形写像がこのようなテンソル積で得られるというわけではありません。
3階以上のテンソル
最後に補足として、3階以上のテンソルについて触れておきます。これまでの議論を素直に拡張することで、3階のテンソル、より正確には、(0, 3) 型のテンソルは、 を基底ベクトルとする、
次元の複素ベクトル空間として定義されます。(0, 3) 型のテンソルは、一般には、
と表されるので、その成分は、 というように3つの足を持ちます。2階のテンソルは2次元に数字を並べた行列として表記できましたが、こちらは、3つの方向、すなわち、3次元の立方体型に数字を並べて表記する必要があります。2次元の紙の上に表すのは大変なので、通常は、
のように成分を個別に表記して満足しておきます。
ただし、2階のテンソルと同様に、フラットな表現を用いれば、縦ベクトルとして表すことは可能です。この場合、 という3つの添字を
という値の1つの添字に置き換えて、全部で 8 個の数字を並べた縦ベクトルになります。
これと同様に、線形写像もまた、フラットな表現を用いた場合は、 行列として表すことができます。
そして最後にややこしいのが、(0, 1) 型テンソルに対する線形写像 を用いて、これらのテンソル積として、(0, 3) 型テンソルに対する線形写像
を定義するとどうなるか、という話です。これをフラットな表現で
行列に表すには、次のような手順に従います。
ステップ1: をフラットな表現で表します。つまり、
の各成分に対して、
のコピーを掛けたものを
のブロックに並べて、
行列を構成します。これを行列
とします。
ステップ2: をフラットな表現で表します。つまり、
の各成分に対して、
のコピーを掛けたものを
のブロックに並べます。今の場合、
は
行列ですので、これで
行列が完成します。
なぜこれでうまくいくのかは・・・・、各自でゆっくりと考えてみてください。
この手続はさらに高階のテンソルにも自然に拡張することができて、一般には、次のようなサブルーチンで組み立てることができます。
def flat_matrix(matrices): result = None for matrix in reversed(matrices): if result is None: result = matrix continue result = np.vstack( (np.hstack((matrix[0][0] * result, matrix[0][1] * result)), np.hstack((matrix[1][0] * result, matrix[1][1] * result))) ) return result