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

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

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

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


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

ベクトル $\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
julia> v1 = [0;1;1]; v2 = [ 1; 0; 1]; v3 = [1; 1; 0]
3-element Array{Int64,1}:
  1
  1
  0
```

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


```julia
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
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
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
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
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
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
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
julia> rank( [ v1 v2 ])
  2
```



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


```julia
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
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`](http://docs.julialang.org/en/release-0.4/stdlib/linalg/#Base.\ ) を読むと、 `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
julia> w1 = [1;1;-1]; w2 = [ 1; -1; 1]; w3 = [-1; 1; 1]
3-element Array{Int64,1}:
  -1
   1
   1
```

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

```julia
julia> rank( [w1 w2 w3 ] )
  3
```

```julia
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}$ が得られました。