数値計算
線形代数
Julia
julialang

[Julia] 特定の基底におけるベクトルの表示を求める + 基底変換

More than 1 year has passed since last update.

[2017/1/25] 表記を修正しました。

特定の基底におけるベクトルの成分と、基底の変換についてまとめました。Julia を使うと、成分表示や基底の変換が簡単に実行できます。

特に断らなければ、以下では、ベクトルは列(縦↓)ベクトルとします。列(縦)ベクトル、行(横→)ベクトルについては、こちらの解説をどうぞ。 →
【プログラマーのための数学】行列

基底, 表示 (表現, 成分)

ベクトル $\boldsymbol{x}$ が、線形独立なベクトルの組 ${\boldsymbol{v}}_1, {\boldsymbol{v}}_2, \cdots, {\boldsymbol{v}}_m $ の線形結合で表されるとします。すなわち、式で書くと 
$$\boldsymbol{x} = a_1 {\boldsymbol{v}}_1 + a_2 {\boldsymbol{v}}_2 + \cdots + a_m {\boldsymbol{v}}_m$$

です。このとき、係数 $a_1,a_2, \ldots, a_m$ を、基底 $V= \{ {\boldsymbol{v}}_1, {\boldsymbol{v}}_2, \cdots, {\boldsymbol{v}}_m \}$ におけるベクトル $\boldsymbol{x}$ の 表示 (あるいは 成分 ) といいます。${\boldsymbol{v}}_1, {\boldsymbol{v}}_2, \cdots, {\boldsymbol{v}}_m$ は、基底ベクトル といいます。
表示(成分) $a_1,a_2, \ldots, a_m$ を、列ベクトル
$$\boldsymbol{a}= \begin{bmatrix} a_1 \\ a_2 \\ \cdots \\ a_m \end{bmatrix} $$
にまとめたものを、成分の 列ベクトル表示 といいます。
さて、基底ベクトルの組 $ {\boldsymbol{v}}_1, {\boldsymbol{v}}_2, \cdots, {\boldsymbol{v}}_m$ を横に並べた行列 $\tilde{V}$ を作ります。
$$\tilde{V} = \left[ {\boldsymbol{v}}_1, {\boldsymbol{v}}_2, \cdots, {\boldsymbol{v}}_m \right ] $$

すると、冒頭の式は、行列 $\tilde{V}$ とベクトル $\boldsymbol{a}$ との積で表示できます。

$$ \boldsymbol{x} = \left[ {\boldsymbol{v}}_1, {\boldsymbol{v}}_2, \cdots, {\boldsymbol{v}}_m \right ] \begin{bmatrix} a_1 \\ a_2 \\ \cdots \\ a_m \end{bmatrix} =
\tilde{V} \boldsymbol{a}$$

上式で、左から$\tilde{V}$ の逆行列を作用すれば、成分 $\boldsymbol{a}$ が求まります。 すなわち、
$$ \boldsymbol{a} = \tilde{V}^{-1} \boldsymbol{x} = \left[ {\boldsymbol{v}}_1, {\boldsymbol{v}}_2, \cdots, {\boldsymbol{v}}_m \right ]^{-1} \boldsymbol{x}$$

上式のようなベクトル・行列の算術が、Julia言語では自然に書けます。

基底の例として、ベクトルの組 ${\boldsymbol{v}}_1 = \begin{bmatrix} 0 \\ 1 \\ 1 \end{bmatrix}$, ${\boldsymbol{v}}_2 = \begin{bmatrix} 1 \\ 0 \\ 1 \end{bmatrix}$, ${\boldsymbol{v}}_3 = \begin{bmatrix} 1 \\ 1 \\ 0 \end{bmatrix}$ を用います。

Julia では、要素からベクトル・行列を作るのに [ ] を用います。 [ ] の中では、セミコロン ; が、縦ベクトルの要素の区切りです。

julia> v1 = [0;1;1]; v2 = [ 1; 0; 1]; v3 = [1; 1; 0]
3-element Array{Int64,1}:
  1
  1
  0

まず、基底ベクトルが線形独立であるかどうかを確かめます (確認は大事)。基底ベクトルからなる行列の階数 rank をとって、基底ベクトルの数と等しいなら線形独立です。 小さいなら線形従属です。

julia> rank( [ v1 v2 v3 ] )
  3

[ v1 v2 v3 ] は、縦ベクトル v1, v2, v3 を横に並べた行列です。
[ ] の中では、空白「」が、横ベクトルの要素の区切りです。rankは落ちていないですね。

では、ベクトル $\boldsymbol{x} = \begin{bmatrix} 1 \\ 1 \\ 2 \end{bmatrix}$ の、基底 $V= \{ {\boldsymbol{v}}_1, {\boldsymbol{v}}_2, {\boldsymbol{v}}_3 \}$ における表示を求めてみます。

julia> x = [ 1.0 ; 1.0 ; 2.0 ]
3-element Array{Float64,1}:
   1.0
   1.0
   2.0

行列 $M$ について、$M^{-1} x$ を計算するには、Julia 言語では M \ x と書きます。

julia> a = [ v1 v2 v3 ] \ x
3-element Array{Float64,1}:
   1.0
   1.0
  -0.0

すなわち、基底 $V$ におけるベクトル$\boldsymbol{x}$の表示は $\boldsymbol{a} = \begin{bmatrix} 1 \\ 1 \\ 0 \end{bmatrix}$ です。 検算します。

julia> [ v1 v2 v3 ] * a
3-element Array{Float64,1}:
  1.0
  1.0
  2.0

julia> ans - x
3-element Array{Float64,1}:
  0.0
  0.0
  0.0

よいですね。 ※ Julia言語のコマンドライン (REPL)では、ans は、最後に計算した結果です。

別のベクトル $\boldsymbol{y} = \begin{bmatrix} 2 \\ 2 \\ 2 \end{bmatrix}$ の基底$V$における表示を求めます。

julia> y = [ 2.0 ; 2.0 ; 2.0 ]
3-element Array{Float64,1}:
  2.0
  2.0
  2.0

ベクトル $\boldsymbol{x}, \boldsymbol{y}$ の表示を、一度に求めてみます。すなわち、$\begin{bmatrix}\boldsymbol{v}_1, \boldsymbol{v}_2, \boldsymbol{v}_3 \end{bmatrix}^{−1} \begin{bmatrix} \boldsymbol{x}, \boldsymbol{y} \end{bmatrix}$ を計算します。

julia> [ v1 v2 v3 ] \ [ x y ]
3x2 Array{Float64,2}:
   1.0  1.0
   1.0  1.0
  -0.0  1.0

よって、基底 $\{ {\boldsymbol{v}}_1, {\boldsymbol{v}}_2, {\boldsymbol{v}}_3 \}$ におけるベクトル $\boldsymbol{y}$の表示は $\begin{bmatrix} 1 \\ 1 \\ 1 \end{bmatrix}$ です。
一度に検算してみます。

julia> [ v1 v2 v3 ] * [ [1.0; 1.0; 0.0 ] [1.0; 1.0; 1.0] ]
3x2 Array{Float64,2}:
  1.0  2.0
  1.0  2.0
  2.0  2.0

julia> ans - [x y]
3x2 Array{Float64,2}:
  0.0  0.0
  0.0  0.0
  0.0  0.0

部分空間

ベクトル $\boldsymbol{x}$ は、基底 $\{ \boldsymbol{v}_1, \boldsymbol{v}_2 \}$ を用いても表示できます。

まずは、基底 $\{ \boldsymbol{v}_1, \boldsymbol{v}_2 \}$の線形独立の確認から

julia> rank( [ v1 v2 ])
  2

では、基底 $\{ \boldsymbol{v}_1, \boldsymbol{v}_2 \}$における$\boldsymbol{x}$の表示を求めます。

julia> [ v1 v2 ] \ x
2-element Array{Float64,1}:
  1.0
  1.0

julia> [ v1 v2 ] * ans
3-element Array{Float64,1}:
  1.0
  1.0
  2.0

すなわち、基底 $\{ \boldsymbol{v}_1, \boldsymbol{v}_2 \}$ に対するベクトル$\boldsymbol{x}$の表示は $\begin{bmatrix} 1 \\ 1 \end{bmatrix}$ です。

ところで、$[ \boldsymbol{v}_1, \boldsymbol{v}_2 ] = \begin{bmatrix} 0 & 1 \\ 1 & 0 \\ 1 & 1 \end{bmatrix}$ は正方行列ではありません (逆行列は存在しません)。 Julia 言語の A \ x は、逆行列を左から作用する操作よりも広く、連立方程式を解く操作を行うわけです。

さて、ベクトル $\boldsymbol{y}$ は、基底 $\{ \boldsymbol{v}_1, \boldsymbol{v}_2 \}$ の線形結合では表示できません。ですが、Julia 言語の A \ x は、線形結合で表せない場合でも (例外を吐いたりせず) 何らかの数字を出力します。

julia> [ v1 v2 ] \ y
2-element Array{Float64,1}:
  1.33333
  1.33333

julia> [ v1 v2 ] * ans
3-element Array{Float64,1}:
  1.33333
  1.33333
  2.66667

やはり、ベクトル $\boldsymbol{y}$ に戻りません (検算が大事です)。

Julia言語マニュアルの標準関数 A \ B を読むと、 A \ x は、A が正方行列ではない場合は、最小二乗ノルムを与える解を出力すると書いてあります。上の場合に即せば、$A (a_1 {\boldsymbol{v}}_1 + a_2 {\boldsymbol{v}}_2 ) - \boldsymbol{x}$ の絶対値 (二乗ノルム)が最小となる数 $ \begin{bmatrix} a_1 \\ a_2 \end{bmatrix}$ が出力されます。ベクトル $\boldsymbol{x}$が、線形結合で表される場合には、これが、基底 ${ \boldsymbol{v}_1, \boldsymbol{v}_2 }$における表示と一致するのです。

基底変換

ベクトル$\boldsymbol{x}$の基底 $V = \{ {\boldsymbol{v}}_1, {\boldsymbol{v}}_2, \cdots, {\boldsymbol{v}}_m \}$ における表示 $\boldsymbol{a}$を、基底 $W = \{ {\boldsymbol{w}}_1, {\boldsymbol{w}}_2, \cdots, {\boldsymbol{w}}_m \}$ における表示 $\boldsymbol{b}$ に変換します。

$$
\begin{align}
\tilde{V} & = \left[ {\boldsymbol{v}}_1, {\boldsymbol{v}}_2, \cdots, {\boldsymbol{v}}_m \right ] \newline
\tilde{W} & = \left[ {\boldsymbol{w}}_1, {\boldsymbol{w}}_2, \cdots, {\boldsymbol{w}}_m \right ] \newline
\boldsymbol{x} & = \tilde{V} \boldsymbol{a}
= \tilde{W} \boldsymbol{b}
\end{align}
$$

末尾の式から
$$\boldsymbol{b} = \tilde{W}^{-1} \tilde{V} \boldsymbol{a}$$
の計算で $ \boldsymbol{b} $ が求まります。

例として、ベクトルの組 ${\boldsymbol{w}}_1 = \begin{bmatrix} 1 \\ 1 \\ -1 \end{bmatrix}$, ${\boldsymbol{w}}_2 = \begin{bmatrix} 1 \\ -1 \\ 1 \end{bmatrix}$, ${\boldsymbol{w}}_3 = \begin{bmatrix} -1 \\ 1 \\ 1 \end{bmatrix}$ を、別の基底ベクトルとします。

julia> w1 = [1;1;-1]; w2 = [ 1; -1; 1]; w3 = [-1; 1; 1]
3-element Array{Int64,1}:
  -1
   1
   1

例によって、線形独立の確認から

julia> rank( [w1 w2 w3 ] )
  3
julia> b = [ w1 w2 w3 ] \ ( [ v1 v2 v3 ] *  a )
3-element Array{Float64,1}:
  1.0
  1.5
  1.5

julia> [ w1 w2 w3 ] * b
3-element Array{Float64,1}:
  1.0
  1.0
  2.0

julia> ans - x 
3-element Array{Float64,1}:
  0.0
  0.0
  0.0

表示 $\boldsymbol{b}$ からベクトル $\boldsymbol{x}$ が得られました。