코딩 더 매트릭스 - 11장 특수 기저 (2)

복소수 필드에 대한 내적, 푸리에 변환

2019년 02월 09일

필립 클라인의 저서 코딩 더 매트릭스 11장 특수 기저


  1. 다항식의 평가와 인터폴레이션을 알아봅니다.
  2. 내적이 복소수 필드에 대해 적용될 때 정의를 알아봅니다.
  3. 이산 푸리에 변환과 고속 푸리에 변환 (FFT)를 알아봅니다.
  4. 순환행렬의 특징을 알아봅니다.





다항식 평가와 인터폴레이션 (interpolation)

차수가 dd인 다항식(polynomial)은 다음 형태를 가지는 단일 변수의 함수입니다.

f(x)=a01+a1x1+a2x2+...+adxdf(x) = a_0 1 + a_1 x^1 + a_2 x^2 + ... + a_d x^d

함수 f(x)f(x)의 xx값을 대입해 값을 얻는 것을 다항식을 평가한다고 합니다. 예를 들어 다항식 2+3x+x22 + 3x + x^2을 7에 대해 평가하면 72를 얻습니다.

다항식의 차수가 2이상일 때 함수 자체는 선형함수가 아니지만 각 변수 xx의 값을 달리하고 행렬-벡터 곱셈으로 표현하면 선형함수입니다. 예를 들어 ridr_i^d를 f(x)f(x)에 대입하는 행렬-벡터 곱셈은 다음과 같이 표현할 수 있습니다.

[r00r01r02r03r10r11r12r13...rk−10rk−11rk−12rk−13][a0a1a2a3]\begin{bmatrix} r_0^0 & r_0^1 & r_0^2 & r_0^3 \\ r_1^0 & r_1^1 & r_1^2 & r_1^3 \\ & ... & & \\ r_{k-1}^0 & r_{k-1}^1 & r_{k-1}^2 & r_{k-1}^3 \end{bmatrix} \begin{bmatrix} a_0 \\ a_1 \\ a_2 \\ a_3 \end{bmatrix}

왼쪽의 행렬은 xdx^d에 대입한 값에 대응합니다. 오른쪽 벡터는 다항식의 계수입니다. 다항식의 평가가 위 행렬-벡터 곱셈 연산을 수행하는 것이라면 반대로 결과값을 알고 계수를 구하는 것을 인터폴레이션(interpolation)이라 합니다. 다항식 평가와 인터폴레이션은 역함수 관계입니다.





복소수 필드에 대한 내적

복소수 필드상의 벡터들에 대한 내적은 다음과 같이 정의됩니다.

⟨u,v⟩=uˉ⋅v\langle u, v \rangle = \bar{u} \cdot v

여기서 uˉ\bar{u}는 uu의 켤레 복소수 벡터입니다. 이러한 정의는 복소수 벡터 vv의 norm이 음수가 아님을 보장합니다.

⟨v,v⟩=[z1ˉ,...,znˉ]⋅[z1,...,zn]=z1ˉz1+...+znˉzn=∣z1∣2+...+∣zn∣2\begin{aligned} \langle v, v \rangle & = [\bar{z_1}, ..., \bar{z_n}] \cdot [z_1, ..., z_n] \\ & = \bar{z_1} z_1 + ... + \bar{z_n} z_n \\ & = |z_1|^2 + ... + |z_n|^2 \end{aligned}

이것은 음수가 아닌 실수입니다.

예를 들어 w=eθiw = e^{\theta i}라고 할 때 v=[w0,w1,...,wn]v = [w^0, w^1, ..., w^n]이면 ⟨v,v⟩\langle v, v \rangle는 다음과 같습니다.

⟨v,v⟩=vˉ⋅v=eθi⋅0−θi⋅0+eθi⋅1−θi⋅1+...+eθi⋅n−θi⋅n=1+1+...+1=n\begin{aligned} \langle v, v \rangle & = \bar{v} \cdot v \\ & = e^{\theta i \cdot 0 - \theta i \cdot 0} + e^{\theta i \cdot 1 - \theta i \cdot 1} + ... + e^{\theta i \cdot n - \theta i \cdot n} \\ & = 1 + 1 + ... + 1 = n \end{aligned}

한편 복소수 필드상의 벡터 내적은 실수상의 벡터 내적과 다르게 대칭성이 성립하지 않습니다. 즉, 복소수 벡터 uu, vv에 대해 ⟨u,v⟩=⟨v,u⟩\langle u, v \rangle = \langle v, u \rangle가 항상 성립하는 것은 아닙니다. 예를 들어 u=[1+2i,1]u = [1 + 2i, 1], v=[2,1]v = [2,1]라고 할 때,

⟨u,v⟩=[1−2i1][21]=[2−4i+1]⟨v,u⟩=[21][1+2i1]=[2+4i+1]\begin{aligned} \langle u, v \rangle & = \begin{bmatrix} 1 - 2i & 1 \end{bmatrix} \begin{bmatrix} 2 \\ 1 \end{bmatrix} \\ & = \begin{bmatrix} 2 - 4i + 1 \end{bmatrix} \\ \langle v, u \rangle & = \begin{bmatrix} 2 & 1 \end{bmatrix} \begin{bmatrix} 1 + 2i \\ 1 \end{bmatrix} \\ & = \begin{bmatrix} 2 + 4i + 1 \end{bmatrix} \end{aligned}

위와 같이 ⟨u,v⟩\langle u, v \rangle와 ⟨v,u⟩\langle v, u \rangle의 값은 다를 수 있습니다.

복소수 필드에서 직교하는 두 벡터의 내적은 실수에서와 같이 0입니다. 예를 들어 u=[e0⋅πi2,e1⋅πi2,e2⋅πi2,e3⋅πi2]u = [e^{\frac{0 \cdot \pi i}{2}}, e^{\frac{1 \cdot \pi i}{2}}, e^{\frac{2 \cdot \pi i}{2}}, e^{\frac{3 \cdot \pi i}{2}}]이고 v=[e0⋅πi,e1⋅πi,e2⋅πi,e3⋅πi]v = [e^{0 \cdot \pi i}, e^{1 \cdot \pi i}, e^{2 \cdot \pi i}, e^{3 \cdot \pi i}]의 내적은 다음과 같습니다.

e−0⋅πi2e0⋅πi+e−1⋅πi2e1⋅πi+e−2⋅πi2e2⋅πi+e−3⋅πi2e3⋅πi=e0⋅πi2+e1⋅πi2+e2⋅πi2+e3⋅πi2\begin{aligned} e^{-\frac{0 \cdot \pi i}{2}} e^{0 \cdot \pi i} + e^{-\frac{1 \cdot \pi i}{2}} e^{1 \cdot \pi i} + e^{-\frac{2 \cdot \pi i}{2}} e^{2 \cdot \pi i} + e^{-\frac{3 \cdot \pi i}{2}} e^{3 \cdot \pi i} \\ = e^{\frac{0 \cdot \pi i}{2}} + e^{\frac{1 \cdot \pi i}{2}} + e^{\frac{2 \cdot \pi i}{2}} + e^{\frac{3 \cdot \pi i}{2}} \end{aligned}

위의 마지막 식은 등비수열의 합이므로 exp(0⋅πi2)(exp(4⋅πi2)−1)exp(1⋅πi2)−1\frac{exp(\frac{0 \cdot \pi i}{2}) (exp(\frac{4 \cdot \pi i}{2}) - 1)}{exp(\frac{1 \cdot \pi i}{2}) - 1}와 같이 쓸 수 있고 exp(4⋅πi2)exp(\frac{4 \cdot \pi i}{2})는 오일러의 공식에 의해 cos2π+(sin2π)i=1cos 2\pi + (sin 2\pi)i = 1이므로 내적값은 0입니다. 따라서 uu와 vv는 직교합니다.

복소수 필드 상의 행렬 AA의 에르미트 수반행렬은 AHA^H로 나타내고 이것은 AA의 전치행렬에서 각 원소의 켤레복소수를 취함으로써 얻어지는 행렬입니다. 복소 필드상의 행렬 AA는 만약 AA가 정방행렬이고 AHAA^H A가 단위행렬이면 유니터리(unitary)라고 말합니다. 직교행렬에 의한 곱이 norm을 보존하는 것처럼 유니터리 행렬에 의한 곱셈은 norm을 보존합니다.





이산 푸리에 변환

w=exp(2πni)w = exp(\frac{2\pi}{n}i) 라 하고 F(t)=wtF(t) = w^t로 정의되는 함수 F:R→CF: \Bbb{R} \to \Bbb{C}를 고려해 보겠습니다. t=0t = 0에서 오일러의 공식에 의해 w0=exp(2πni⋅0)=cos(2πn⋅0)+(sin(2πn⋅0))i=1+0iw^0 = exp(\frac{2 \pi}{n} i \cdot 0) = cos (\frac{2 \pi}{n}\cdot 0) + (sin (\frac{2 \pi}{n} \cdot 0))i = 1 + 0i라 쓸 수 있습니다. t=n,2n,3n,...t = n, 2n, 3n, ...인 경우 1+0i1 + 0i로 돌아옵니다. 따라서 이 함수의 주기는 nn, 주파수는 1n\frac{1}{n}이라 할 수 있습니다.

이번에는 함수 k=0,1,2,3,...,n−1k = 0, 1, 2, 3, ..., n-1에 대해 F0F_0, F1F_1, F2F_2, F3F_3, ..., FkF_k를 정의해 보겠습니다.

F0(x)=1nw0⋅tF1(x)=1nw1⋅tF2(x)=1nw2⋅tF3(x)=1nw3⋅t...Fk(x)=wk⋅t\begin{aligned} F_0(x) &= \frac{1}{\sqrt{n}}w^{0 \cdot t} \\ F_1(x) &= \frac{1}{\sqrt{n}}w^{1 \cdot t} \\ F_2(x) &= \frac{1}{\sqrt{n}}w^{2 \cdot t} \\ F_3(x) &= \frac{1}{\sqrt{n}}w^{3 \cdot t} \\ & ... \\ F_k(x) &= w^{k \cdot t} \end{aligned}

F0(x)F_0(x)를 제외한 각각의 함수는 주기 nn, n2\frac{n}{2}, n3\frac{n}{3}, ..., nk\frac{n}{k}을 갖습니다. F0(x)F_0(x)의 경우 주기 n0\frac{n}{0}, 즉 무한대를 갖는데 이는 시계가 움직이지 않는 경우를 생각하면 좋을 것 같습니다. 그리고 t=0t = 0에서 각각의 함수는 1n+0i\frac{1}{\sqrt{n}} + 0i을 가집니다.

함수 Fk(x)F_k(x)와 xx의 대입값을 바탕으로 다음 행렬 방정식을 쓸 수 있습니다.

[F0(0)F1(0)...Fn−1(0)F0(1)F1(1)...Fn−1(1)............F0(n−1)F1(n−1)...Fn−1(n−1)][ϕ0ϕ1...ϕn−1]=[s(0)s(1)...s(n−1)]\begin{bmatrix} F_0(0) & F_1(0) & ... & F_{n-1}(0) \\ F_0(1) & F_1(1) & ... & F_{n-1}(1) \\ ... & ... & ... & ... \\ F_0(n-1) & F_1(n-1) & ... & F_{n-1}(n-1) \end{bmatrix} \begin{bmatrix} \phi_0 \\ \phi_1 \\ ... \\ \phi_{n-1} \\ \end{bmatrix} = \begin{bmatrix} s(0) \\ s(1) \\ ... \\ s(n-1) \end{bmatrix}

위 행렬 방정식을 간단히 Fkϕ=sF_k \phi = s라 쓰면 FkF_k는 각각의 Fk(x)F_k(x)함수의 평가이고 ϕ\phi는 선형결합의 계수입니다. s(t)s(t)는 동일한 시간 tt에 대해 각각의 FkF_k함수의 선형결합의 결과를 나타내는 샘플링 함수라 할 수 있습니다. (e.g. s(0)=ϕ0F0(0)+ϕ1F1(0)+...+ϕn−1Fn−1(0)s(0) = \phi_0 F_0(0) + \phi_1 F_1(0) + ... + \phi_{n-1} F_{n-1}(0))

행렬 방정식 Fkϕ=sF_k \phi = s를 두가지 관점에서 해석할 수 있습니다. 먼저 FkϕF_k \phi를 구함으로서 신호 ss를 찾아낼 수 있습니다. 그리고 Fk−1F_k^{-1}을 구함으로서 계수 ϕ\phi를 구할 수 있습니다.

앞으로 다음의 행렬을 W(w,n)W(w, n)로 표시합니다.

  • 행라벨과 열라벨의 집합이 0,1,...,n−1{0, 1, ..., n-1}이고
  • 엔트리 rcrc는 wr⋅cw^{r \cdot c} 입니다.
W(w,n)=[w0⋅0w0⋅1w0⋅2 w0⋅(n−1)w1⋅0w1⋅1w1⋅2...w1⋅(n−1)w2⋅0w2⋅1w2⋅2 w2⋅(n−1)......... ...w(n−1)⋅0w(n−1)⋅1w(n−1)⋅2 w(n−1)⋅(n−1)]W(w, n) = \begin{bmatrix} w^{0 \cdot 0} & w^{0 \cdot 1} & w^{0 \cdot 2} & \text{ } & w^{0 \cdot (n-1)} \\ w^{1 \cdot 0} & w^{1 \cdot 1} & w^{1 \cdot 2} & ... & w^{1 \cdot (n-1)} \\ w^{2 \cdot 0} & w^{2 \cdot 1} & w^{2 \cdot 2} & \text{ } & w^{2 \cdot (n-1)} \\ ... & ... & ... & \text{ } & ... \\ w^{(n-1) \cdot 0} & w^{(n-1) \cdot 1} & w^{(n-1) \cdot 2} & \text{ } & w^{(n-1) \cdot (n-1)} \end{bmatrix}

위의 행렬을 참고하여 Fn=1nW(w,n)F_n = \frac{1}{\sqrt{n}}W(w, n)이라 쓸 수 있습니다. 이를 푸리에 행렬이라 합니다. 한편 푸리에 행렬의 역행렬은 Fn−1=1nW(w−1,n)F_n^{-1} = \frac{1}{\sqrt{n}}W(w^{-1}, n)입니다. 이는 복소 필드 상의 유니터리 행렬과 연관됩니다. 행렬-벡터 곱셈을 통해 이를 증명할 수 있습니다. 먼저 FnFn−1F_n F_n^{-1}의 엔트리는 행과 열의 도트곱이고 다음과 같이 표현됩니다.

wr⋅0w−0⋅c+wr⋅1w−1⋅c+wr⋅2w−2⋅c+...+wr⋅(n−1)w−(n−1)⋅c=w0(r−c)+w1(r−c)+w2(r−c)+...+w(n−1)(r−c)\begin{aligned} w^{r \cdot 0} w^{-0 \cdot c} + w^{r \cdot 1} w^{-1 \cdot c} + w^{r \cdot 2} w^{-2 \cdot c} + ... + w^{r \cdot (n-1)} w^{-(n-1) \cdot c} \\ = w^{0(r-c)} + w^{1(r-c)} + w^{2(r-c)} + ... + w^{(n-1)(r-c)} \end{aligned}

r=cr = c일 때 즉, FnFn−1F_n F_n^{-1}의 대각 엔트리는 1+1+...1=n1 + 1 + ... 1 = n입니다. r≠cr \neq c일 때 위 식은 등비수열의 합이므로 아래와 같이 표현할 수 있습니다.

w0(r−c)(w(r−c)⋅n−1)wr−c−1\frac{w^{0(r-c)}(w^{(r-c) \cdot n} - 1)}{w^{r-c} - 1}

이 때 w(r−c)⋅n=exp(2π⋅(r−c)n⋅n)=cos(2π(r−c))+sin(2π(r−c))i=1w^{(r-c) \cdot n} = exp(\frac{2 \pi \cdot (r-c)}{n} \cdot n) = cos (2\pi (r-c)) + sin(2\pi (r-c))i = 1이므로 등비수열의 합은 0입니다. (0은 두 벡터가 직교임을 증명합니다.) 따라서 FnFn−1F_n F_n^{-1}은 대각 엔트리가 nn이고 나머지 엔트리는 모두 0인 행렬과 스칼라 1n\frac{1}{n}의 곱, 즉 단위행렬입니다.





고속 푸리에 변환 알고리즘 (FFT)

[w0⋅0w0⋅1w0⋅2 w0⋅(n−1)w1⋅0w1⋅1w1⋅2...w1⋅(n−1)w2⋅0w2⋅1w2⋅2 w2⋅(n−1)......... ...w(n−1)⋅0w(n−1)⋅1w(n−1)⋅2 w(n−1)⋅(n−1)][ϕ0ϕ1ϕ2...ϕn−1]=[s(0)s(1)s(2)...s(n−1)]\begin{bmatrix} w^{0 \cdot 0} & w^{0 \cdot 1} & w^{0 \cdot 2} & \text{ } & w^{0 \cdot (n-1)} \\ w^{1 \cdot 0} & w^{1 \cdot 1} & w^{1 \cdot 2} & ... & w^{1 \cdot (n-1)} \\ w^{2 \cdot 0} & w^{2 \cdot 1} & w^{2 \cdot 2} & \text{ } & w^{2 \cdot (n-1)} \\ ... & ... & ... & \text{ } & ... \\ w^{(n-1) \cdot 0} & w^{(n-1) \cdot 1} & w^{(n-1) \cdot 2} & \text{ } & w^{(n-1) \cdot (n-1)} \end{bmatrix} \begin{bmatrix} \phi_0 \\ \phi_1 \\ \phi_2 \\ ... \\ \phi_{n-1} \end{bmatrix} = \begin{bmatrix} s(0) \\ s(1) \\ s(2) \\ ... \\ s(n-1) \end{bmatrix}

푸리에 행렬 W(w,n)W(w, n)과 계수 벡터의 행렬-벡터 곱셈은 n2n^2의 연산이 필요합니다. 연산을 크게 줄이는 알고리즘으로 고속 푸리에 변환 알고리즘 (FFT)이 있습니다. FFT에는 다음 두 가지 전제 조건이 있습니다.

  • nn은 2의 거듭제곱입니다.
  • wn=1w^n = 1

FFT의 핵심은 아래와 같이 짝수번째와 홀수번째로 분할 정복하는 것입니다.

s(k)=ϕ0wk⋅0+ϕ1wk⋅1+ϕ2wk⋅2+...+ϕn−1wk⋅(n−1)=ϕ0wk⋅0+ϕ2wk⋅2+...+ϕn−2wk⋅(n−2)+wk(ϕ1wk⋅1+ϕ3wk⋅3+...+ϕn−1wk⋅(n−1))\begin{aligned} s(k) & = \phi_0 w^{k \cdot 0} + \phi_1 w^{k \cdot 1} + \phi_2 w^{k \cdot 2} + ... + \phi_{n-1} w^{k \cdot (n-1)} \\ & = \phi_0 w^{k \cdot 0} + \phi_2 w^{k \cdot 2} + ... + \phi_{n-2} w^{k \cdot (n-2)} + w^k(\phi_1 w^{k \cdot 1} + \phi_3 w^{k \cdot 3} + ... + \phi_{n-1} w^{k \cdot (n-1)}) \end{aligned}

다음과 같이 sevens_{even}과 sodds_{odd}를 정의하고 kk값에 따른 식을 정리해 보겠습니다.

seven(x)=s0+s2x+s4x2+...+sn−2xn−22sodd(x)=s1+s3x+s5x2+...+sn−1xn−22\begin{aligned} s_{even}(x) = s_0 + s_2 x + s_4 x^2 + ... + s_{n-2} x^{\frac{n-2}{2}} \\ s_{odd}(x) = s_1 + s_3 x + s_5 x^2 + ... + s_{n-1} x^{\frac{n-2}{2}} \end{aligned} s(w0)=seven(w0⋅2)+w0(sodd(w0⋅2))s(w1)=seven(w1⋅2)+w1(sodd(w1⋅2))s(w2)=seven(w2⋅2)+w2(sodd(w2⋅2))...s(wn−1)=seven(w(n−1)⋅2)+wn−1(sodd(w(n−1)⋅2))\begin{aligned} s(w^0) &= s_{even}(w^{0 \cdot 2}) + w^0(s_{odd}(w^{0 \cdot 2})) \\ s(w^1) &= s_{even}(w^{1 \cdot 2}) + w^1(s_{odd}(w^{1 \cdot 2})) \\ s(w^2) &= s_{even}(w^{2 \cdot 2}) + w^2(s_{odd}(w^{2 \cdot 2})) \\ & ... \\ s(w^{n-1}) &= s_{even}(w^{(n-1) \cdot 2}) + w^{n-1}(s_{odd}(w^{(n-1) \cdot 2})) \end{aligned}

FFT를 Python 코드로 옮겨 보겠습니다.

def FFT(w, s): 
    n = len(s)
    if n == 1: return s
    f0 = FFT(w*w, s[0::2])
    f1 = FFT(w*w, s[1::2])
    return [f0[j] + w**j*f1[j] for j in range(n // 2)] + \
		[f0[j] - w**j*f1[j] for j in range(n // 2)]

재귀호출을 차근차근 따라가면서 직접 도트곱의 값과 비교해 보는 것이 좋습니다. 이 때 wn=1w^n = 1, wn2=−1w^{\frac{n}{2}} = -1인 점을 알면 계산이 쉬워집니다.

wn2=−1∵exp(2πin⋅n2)=exp(πi)=cosπ+(sinπ)i=−1\begin{aligned} w^{\frac{n}{2}} &= -1 \\ \because exp(\frac{2\pi i}{n} \cdot \frac{n}{2}) &= exp(\pi i) = cos \pi + (sin \pi)i = -1 \end{aligned}





순환행렬

다음과 같이 다음 행이 이전 행의 오른쪽 시프트인 행렬을 순환행렬이라 합니다.

[a0a1a2...an−3an−2an−1an−1a0a1...an−4an−3an−2an−2an−1a0...an−5an−4an−3   ...   a2a3a4...an−1a0a1a1a2a3...an−2an−1a0]\begin{bmatrix} a_0 & a_1 & a_2 & ... & a_{n-3} & a_{n-2} & a_{n-1} \\ a_{n-1} & a_0 & a_1 & ... & a_{n-4} & a_{n-3} & a_{n-2} \\ a_{n-2} & a_{n-1} & a_0 & ... & a_{n-5} & a_{n-4} & a_{n-3} \\ \text{ } & \text{ } & \text{ } & ... & \text{ } & \text{ } & \text{ }\\ a_2 & a_3 & a_4 & ... & a_{n-1} & a_0 & a_1 \\ a_1 & a_2 & a_3 & ... & a_{n-2} & a_{n-1} & a_0 \end{bmatrix}

순환행렬을 어디에 응용할지 감 잡기가 쉽지 않습니다. 아래의 순환행렬과 푸리에 행렬 W(w,4)W(w, 4)의 곱을 통해 순환행렬의 흥미로운 현상을 알아보겠습니다.

[a0a1a2a3a3a0a1a2a2a3a0a1a1a2a3a0][w0⋅0w0⋅1w0⋅2w0⋅3w1⋅0w1⋅1w1⋅2w1⋅3w2⋅0w2⋅1w2⋅2w2⋅3w3⋅0w3⋅1w3⋅2w3⋅3]\begin{bmatrix} a_0 & a_1 & a_2 & a_3 \\ a_3 & a_0 & a_1 & a_2 \\ a_2 & a_3 & a_0 & a_1 \\ a_1 & a_2 & a_3 & a_0 \end{bmatrix} \begin{bmatrix} w^{0 \cdot 0} & w^{0 \cdot 1} & w^{0 \cdot 2} & w^{0 \cdot 3} \\ w^{1 \cdot 0} & w^{1 \cdot 1} & w^{1 \cdot 2} & w^{1 \cdot 3} \\ w^{2 \cdot 0} & w^{2 \cdot 1} & w^{2 \cdot 2} & w^{2 \cdot 3} \\ w^{3 \cdot 0} & w^{3 \cdot 1} & w^{3 \cdot 2} & w^{3 \cdot 3} \end{bmatrix}

위 행렬 곱셈 중 푸리에 행렬의 첫번째 열만으로 행렬-벡터 곱셈을 살펴보겠습니다.

[a0a1a2a3a3a0a1a2a2a3a0a1a1a2a3a0][w0⋅0w1⋅0w2⋅0w3⋅0]\begin{bmatrix} a_0 & a_1 & a_2 & a_3 \\ a_3 & a_0 & a_1 & a_2 \\ a_2 & a_3 & a_0 & a_1 \\ a_1 & a_2 & a_3 & a_0 \end{bmatrix} \begin{bmatrix} w^{0 \cdot 0} \\ w^{1 \cdot 0} \\ w^{2 \cdot 0} \\ w^{3 \cdot 0} \end{bmatrix}

순환행렬의 첫번째 행과 벡터의 곱셈은 다음과 같습니다.

a0w0⋅0+a1w1⋅0+a2w2⋅0+a3w3⋅0a_0 w^{0 \cdot 0} + a_1 w^{1 \cdot 0} + a_2 w^{2 \cdot 0} + a_3 w^{3 \cdot 0}

순환행렬의 두번째 행과 벡터의 곱셈은 다음과 같습니다.

a3w0⋅0+a0w1⋅0+a1w2⋅0+a2w3⋅0a_3 w^{0 \cdot 0} + a_0 w^{1 \cdot 0} + a_1 w^{2 \cdot 0} + a_2 w^{3 \cdot 0}

위 식은 첫번째식에 w1⋅0w^{1 \cdot 0}을 곱한것과 같습니다. (∵w4=1\because w^4 = 1)

마찬가지로 순환행렬의 세번째 행과 벡터의 곱셈은 첫번째 식에 w2⋅0w^{2 \cdot 0}을, 네번째 행과 벡터의 곱셈은 w3⋅0w^{3 \cdot 0}을 곱한 것과 같습니다. 따라서 a0w0⋅j+a1w1⋅j+a2w2⋅j+a3w3⋅j=λja_0 w^{0 \cdot j} + a_1 w^{1 \cdot j} + a_2 w^{2 \cdot j} + a_3 w^{3 \cdot j} = \lambda_j 라 할 때 다음이 성립합니다.

λj[w0⋅jw1⋅jw2⋅jw3⋅j]=[a0a1a2a3a3a0a1a2a2a3a0a1a1a2a3a0][w0⋅jw1⋅jw2⋅jw3⋅j]\lambda_j \begin{bmatrix} w^{0 \cdot j} \\ w^{1 \cdot j} \\ w^{2 \cdot j} \\ w^{3 \cdot j} \end{bmatrix} = \begin{bmatrix} a_0 & a_1 & a_2 & a_3 \\ a_3 & a_0 & a_1 & a_2 \\ a_2 & a_3 & a_0 & a_1 \\ a_1 & a_2 & a_3 & a_0 \end{bmatrix} \begin{bmatrix} w^{0 \cdot j} \\ w^{1 \cdot j} \\ w^{2 \cdot j} \\ w^{3 \cdot j} \end{bmatrix}

푸리에 행렬의 모든 열에 대해 적용하면 다음과 같습니다.

[w0⋅0w0⋅1w0⋅2w0⋅3w1⋅0w1⋅1w1⋅2w1⋅3w2⋅0w2⋅1w2⋅2w2⋅3w3⋅0w3⋅1w3⋅2w3⋅3][λ00000λ10000λ20000λ3]=[a0a1a2a3a3a0a1a2a2a3a0a1a1a2a3a0][w0⋅0w0⋅1w0⋅2w0⋅3w1⋅0w1⋅1w1⋅2w1⋅3w2⋅0w2⋅1w2⋅2w2⋅3w3⋅0w3⋅1w3⋅2w3⋅3]\begin{bmatrix} w^{0 \cdot 0} & w^{0 \cdot 1} & w^{0 \cdot 2} & w^{0 \cdot 3} \\ w^{1 \cdot 0} & w^{1 \cdot 1} & w^{1 \cdot 2} & w^{1 \cdot 3} \\ w^{2 \cdot 0} & w^{2 \cdot 1} & w^{2 \cdot 2} & w^{2 \cdot 3} \\ w^{3 \cdot 0} & w^{3 \cdot 1} & w^{3 \cdot 2} & w^{3 \cdot 3} \end{bmatrix} \begin{bmatrix} \lambda_0 & 0 & 0 & 0 \\ 0 & \lambda_1 & 0 & 0 \\ 0 & 0 & \lambda_2 & 0 \\ 0 & 0 & 0 & \lambda_3 \end{bmatrix} = \begin{bmatrix} a_0 & a_1 & a_2 & a_3 \\ a_3 & a_0 & a_1 & a_2 \\ a_2 & a_3 & a_0 & a_1 \\ a_1 & a_2 & a_3 & a_0 \end{bmatrix} \begin{bmatrix} w^{0 \cdot 0} & w^{0 \cdot 1} & w^{0 \cdot 2} & w^{0 \cdot 3} \\ w^{1 \cdot 0} & w^{1 \cdot 1} & w^{1 \cdot 2} & w^{1 \cdot 3} \\ w^{2 \cdot 0} & w^{2 \cdot 1} & w^{2 \cdot 2} & w^{2 \cdot 3} \\ w^{3 \cdot 0} & w^{3 \cdot 1} & w^{3 \cdot 2} & w^{3 \cdot 3} \end{bmatrix}

위 식을 간단하게 F4Λ=AF4F_4 \Lambda = A F_4 로 쓸 수 있고 양변에 F4−1F_4^{-1}을 곱하면 다음 두 식을 얻을 수 있습니다.

F4ΛF4−1=AΛ=F4−1AF4\begin{aligned} F_4 \Lambda F_4^{-1} = A \\ \Lambda = F_4^{-1} A F_4 \end{aligned}

이 방정식은 나중에 대각화에서 다루게 됩니다.





직교 행렬과 관련된 프로시저

  • 직교행렬의 행공간에 대한 좌표 표현을 구하는 프로시저 orthogonal_vec2rep
def orthogonal_vec2rep(Q, b):
    return b * Q.transpose()

프로시저 orthogonal_vec2rep는 직교행렬 QQ에 대해 QTQ=IQ^TQ = I 라는 성질을 이용합니다.



  • 직교행렬에 대해 기저 변경 후 좌표 표현을 구하는 프로시저 orthogonal_change_of_basis
def orthogonal_change_of_basis(A, B, a):
    v = a * A
    return B.transpose() * v



  • 직교행렬에 대한 직교 정사영을 구하는 프로시저 orthonormal_projection_orthogonal
def orthonormal_projection_orthogonal(W, b):
    return b - W.transpose() * W * b

위 프로시저는 직교행렬의 각각의 벡터의 norm은 1임을 이용합니다.