03. ์„ ํ˜•๋Œ€์ˆ˜ (Linear Algebra)

03. ์„ ํ˜•๋Œ€์ˆ˜ (Linear Algebra)

Boas Chapter 3 โ€” ๋ฌผ๋ฆฌ๊ณผํ•™์—์„œ ์„ ํ˜•๋Œ€์ˆ˜๋Š” ์—ญํ•™์˜ ๊ด€์„ฑ ํ…์„œ, ์–‘์ž์—ญํ•™์˜ ํ–‰๋ ฌ ํ˜•์‹, ์—ฐ์„ฑ ์ง„๋™ ๋ถ„์„ ๋“ฑ ๊ฑฐ์˜ ๋ชจ๋“  ๋ถ„์•ผ์˜ ๊ธฐ์ดˆ๋ฅผ ์ด๋ฃน๋‹ˆ๋‹ค.


ํ•™์Šต ๋ชฉํ‘œ

์ด ๋ ˆ์Šจ์„ ์™„๋ฃŒํ•˜๋ฉด ๋‹ค์Œ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ํ–‰๋ ฌ ์—ฐ์‚ฐ(๋ง์…ˆ, ๊ณฑ์…ˆ, ์ „์น˜, ์—ญํ–‰๋ ฌ)์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ํ–‰๋ ฌ์‹(determinant)์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๊ฐ€์šฐ์Šค ์†Œ๊ฑฐ๋ฒ•๊ณผ ํฌ๋ž˜๋จธ ๋ฒ•์น™์„ ์ด์šฉํ•˜์—ฌ ์—ฐ๋ฆฝ์ผ์ฐจ๋ฐฉ์ •์‹์„ ํ’€ ์ˆ˜ ์žˆ๋‹ค
  • ๊ณ ์œ ๊ฐ’/๊ณ ์œ ๋ฒกํ„ฐ๋ฅผ ๊ตฌํ•˜๊ณ  ํ–‰๋ ฌ์˜ ๋Œ€๊ฐํ™”(diagonalization)๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๋Œ€์นญ ํ–‰๋ ฌ๊ณผ ์—๋ฅด๋ฏธํŠธ ํ–‰๋ ฌ์˜ ์ŠคํŽ™ํŠธ๋Ÿผ ์ •๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ณ , ์ง๊ต/์œ ๋‹ˆํ„ฐ๋ฆฌ ํ–‰๋ ฌ์˜ ์„ฑ์งˆ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค
  • ์ด์ฐจํ˜•์‹(quadratic form)์˜ ์–‘์ •์น˜/์Œ์ •์น˜ ํŒ๋ณ„์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๋ฌผ๋ฆฌํ•™ ์‘์šฉ: ๊ด€์„ฑ ํ…์„œ์˜ ์ฃผ์ถ• ๋ณ€ํ™˜, ์—ฐ์„ฑ ์ง„๋™์˜ ๊ณ ์œ  ๋ชจ๋“œ, ์–‘์ž์—ญํ•™์˜ ํ–‰๋ ฌ ์—ญํ•™์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค

1. ํ–‰๋ ฌ์˜ ๊ธฐ๋ณธ

1.1 ํ–‰๋ ฌ๊ณผ ๊ธฐ๋ณธ ์—ฐ์‚ฐ

ํ–‰๋ ฌ(matrix)์€ ์ˆ˜๋ฅผ ์ง์‚ฌ๊ฐํ˜•์œผ๋กœ ๋ฐฐ์—ดํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. $m \times n$ ํ–‰๋ ฌ $A$์˜ ์›์†Œ๋ฅผ $a_{ij}$๋กœ ํ‘œ๊ธฐํ•ฉ๋‹ˆ๋‹ค:

$$ A = \begin{pmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{pmatrix} $$

ํ–‰๋ ฌ ๋ง์…ˆ: ๊ฐ™์€ ํฌ๊ธฐ์˜ ํ–‰๋ ฌ์— ๋Œ€ํ•ด ์›์†Œ๋ณ„ ๋ง์…ˆ

$$ (A + B)_{ij} = a_{ij} + b_{ij} $$

์Šค์นผ๋ผ ๊ณฑ: ๋ชจ๋“  ์›์†Œ์— ์Šค์นผ๋ผ๋ฅผ ๊ณฑํ•จ

$$ (cA)_{ij} = c \cdot a_{ij} $$

ํ–‰๋ ฌ ๊ณฑ์…ˆ: $A$๊ฐ€ $m \times n$, $B$๊ฐ€ $n \times p$์ผ ๋•Œ, ๊ฒฐ๊ณผ๋Š” $m \times p$

$$ (AB)_{ij} = \sum_{k=1}^{n} a_{ik} b_{kj} $$

์ฃผ์˜: ํ–‰๋ ฌ ๊ณฑ์…ˆ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ตํ™˜ ๋ฒ•์น™์ด ์„ฑ๋ฆฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: $AB \neq BA$

import numpy as np

# ํ–‰๋ ฌ ๊ธฐ๋ณธ ์—ฐ์‚ฐ
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

print("A =\n", A)
print("B =\n", B)

# ํ–‰๋ ฌ ๊ณฑ์…ˆ
print("\nAB =\n", A @ B)
print("BA =\n", B @ A)
print("AB โ‰  BA:", not np.allclose(A @ B, B @ A))

# ํ–‰๋ ฌ ๊ณฑ์˜ ์„ฑ์งˆ
C = np.array([[1, 0], [2, 3]])
print("\n(AB)C =\n", (A @ B) @ C)
print("A(BC) =\n", A @ (B @ C))
print("๊ฒฐํ•ฉ๋ฒ•์น™ ์„ฑ๋ฆฝ:", np.allclose((A @ B) @ C, A @ (B @ C)))

1.2 ์ „์น˜ ํ–‰๋ ฌ๊ณผ ์ผค๋ ˆ ์ „์น˜

์ „์น˜ ํ–‰๋ ฌ(transpose) $A^T$: ํ–‰๊ณผ ์—ด์„ ๊ตํ™˜

$$ (A^T)_{ij} = a_{ji} $$

์„ฑ์งˆ: - $(AB)^T = B^T A^T$ (์ˆœ์„œ ๋ฐ˜์ „) - $(A^T)^T = A$ - $(A + B)^T = A^T + B^T$

์ผค๋ ˆ ์ „์น˜(conjugate transpose, adjoint) $A^\dagger$: ์ „์น˜ + ๋ณต์†Œ ์ผค๋ ˆ

$$ (A^\dagger)_{ij} = \overline{a_{ji}} $$

# ์ „์น˜ ํ–‰๋ ฌ
A = np.array([[1, 2, 3], [4, 5, 6]])
print("A =\n", A)
print("A^T =\n", A.T)

# ๋ณต์†Œ ํ–‰๋ ฌ์˜ ์ผค๋ ˆ ์ „์น˜
Z = np.array([[1+2j, 3-1j], [4j, 2+3j]])
print("\nZ =\n", Z)
print("Zโ€  =\n", Z.conj().T)

# (AB)^T = B^T A^T ํ™•์ธ
B = np.array([[1, 2], [3, 4], [5, 6]])
print("\n(AB)^T =\n", (A @ B).T)
print("B^T A^T =\n", B.T @ A.T)

1.3 ํŠน์ˆ˜ ํ–‰๋ ฌ

๋‹จ์œ„ ํ–‰๋ ฌ(identity matrix) $I$: ๋Œ€๊ฐ ์›์†Œ๊ฐ€ ๋ชจ๋‘ 1

$$ I_{ij} = \delta_{ij} = \begin{cases} 1 & (i = j) \\ 0 & (i \neq j) \end{cases} $$

๋Œ€๊ฐ ํ–‰๋ ฌ(diagonal matrix): ๋Œ€๊ฐ ์›์†Œ๋งŒ 0์ด ์•„๋‹Œ ํ–‰๋ ฌ

๋Œ€์นญ ํ–‰๋ ฌ(symmetric matrix): $A^T = A$, ์ฆ‰ $a_{ij} = a_{ji}$

๋ฐ˜๋Œ€์นญ ํ–‰๋ ฌ(antisymmetric): $A^T = -A$

์—๋ฅด๋ฏธํŠธ ํ–‰๋ ฌ(Hermitian matrix): $A^\dagger = A$ (๋Œ€์นญ ํ–‰๋ ฌ์˜ ๋ณต์†Œ ํ™•์žฅ)

์ง๊ต ํ–‰๋ ฌ(orthogonal matrix): $A^T A = AA^T = I$, ์ฆ‰ $A^{-1} = A^T$

์œ ๋‹ˆํ„ฐ๋ฆฌ ํ–‰๋ ฌ(unitary matrix): $A^\dagger A = AA^\dagger = I$ (์ง๊ต ํ–‰๋ ฌ์˜ ๋ณต์†Œ ํ™•์žฅ)

# ์ง๊ต ํ–‰๋ ฌ ์˜ˆ: 2D ํšŒ์ „ ํ–‰๋ ฌ
theta = np.pi / 4  # 45๋„ ํšŒ์ „
R = np.array([[np.cos(theta), -np.sin(theta)],
              [np.sin(theta),  np.cos(theta)]])

print("R =\n", R)
print("R^T R =\n", np.round(R.T @ R, 10))
print("det(R) =", np.linalg.det(R))  # det = +1 (proper rotation)

# ์—๋ฅด๋ฏธํŠธ ํ–‰๋ ฌ ์˜ˆ
H = np.array([[2, 1-1j], [1+1j, 3]])
print("\nH =\n", H)
print("Hโ€  =\n", H.conj().T)
print("์—๋ฅด๋ฏธํŠธ:", np.allclose(H, H.conj().T))

2. ํ–‰๋ ฌ์‹ (Determinants)

2.1 ์ •์˜์™€ ๊ธฐ๋ณธ ์„ฑ์งˆ

$n \times n$ ์ •๋ฐฉํ–‰๋ ฌ $A$์˜ ํ–‰๋ ฌ์‹(determinant) $\det(A)$๋Š” ์Šค์นผ๋ผ๊ฐ’์ž…๋‹ˆ๋‹ค.

2ร—2 ํ–‰๋ ฌ์‹:

$$ \det\begin{pmatrix} a & b \\ c & d \end{pmatrix} = ad - bc $$

3ร—3 ํ–‰๋ ฌ์‹ (์‚ฌ๋คผ์Šค ๋ฒ•์น™ ๋˜๋Š” ์—ฌ์ธ์ˆ˜ ์ „๊ฐœ):

$$ \det\begin{pmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \end{pmatrix} = a_{11}(a_{22}a_{33} - a_{23}a_{32}) - a_{12}(a_{21}a_{33} - a_{23}a_{31}) + a_{13}(a_{21}a_{32} - a_{22}a_{31}) $$

์ฃผ์š” ์„ฑ์งˆ:

  1. $\det(AB) = \det(A) \cdot \det(B)$
  2. $\det(A^T) = \det(A)$
  3. $\det(cA) = c^n \det(A)$ ($n \times n$ ํ–‰๋ ฌ)
  4. ํ–‰(๋˜๋Š” ์—ด)์„ ๊ตํ™˜ํ•˜๋ฉด ๋ถ€ํ˜ธ๊ฐ€ ๋ฐ”๋€œ
  5. ํ•œ ํ–‰์ด ๋‹ค๋ฅธ ํ–‰์˜ ์ƒ์ˆ˜๋ฐฐ์ด๋ฉด $\det = 0$
  6. $\det(A^{-1}) = 1/\det(A)$

2.2 ์—ฌ์ธ์ˆ˜ ์ „๊ฐœ (Cofactor Expansion)

์†Œํ–‰๋ ฌ์‹(minor) $M_{ij}$: $i$๋ฒˆ์งธ ํ–‰๊ณผ $j$๋ฒˆ์งธ ์—ด์„ ์ œ๊ฑฐํ•œ $(n-1) \times (n-1)$ ํ–‰๋ ฌ์˜ ํ–‰๋ ฌ์‹

์—ฌ์ธ์ˆ˜(cofactor): $C_{ij} = (-1)^{i+j} M_{ij}$

ํ–‰๋ ฌ์‹์˜ ์—ฌ์ธ์ˆ˜ ์ „๊ฐœ (์ œ$i$ํ–‰์œผ๋กœ ์ „๊ฐœ):

$$ \det(A) = \sum_{j=1}^{n} a_{ij} C_{ij} = \sum_{j=1}^{n} (-1)^{i+j} a_{ij} M_{ij} $$

import numpy as np
from numpy.linalg import det

# ํ–‰๋ ฌ์‹ ๊ณ„์‚ฐ
A = np.array([[2, 1, 3],
              [0, -1, 2],
              [4, 3, 1]])

print("det(A) =", det(A))

# ์—ฌ์ธ์ˆ˜ ์ „๊ฐœ๋ฅผ ์ˆ˜๋™์œผ๋กœ ๊ณ„์‚ฐ (1ํ–‰ ๊ธฐ์ค€)
# det = 2*(-1-6) - 1*(0-8) + 3*(0+4)
manual = 2*(-1*1 - 2*3) - 1*(0*1 - 2*4) + 3*(0*3 - (-1)*4)
print("์ˆ˜๋™ ๊ณ„์‚ฐ:", manual)

# ํ–‰๋ ฌ์‹์˜ ์„ฑ์งˆ ํ™•์ธ
B = np.array([[1, 2, 0],
              [3, 1, -1],
              [2, 0, 4]])

print(f"\ndet(A) = {det(A):.4f}")
print(f"det(B) = {det(B):.4f}")
print(f"det(AB) = {det(A @ B):.4f}")
print(f"det(A)*det(B) = {det(A)*det(B):.4f}")

2.3 ํ–‰๋ ฌ์‹์˜ ๊ธฐํ•˜ํ•™์  ์˜๋ฏธ

$n \times n$ ํ–‰๋ ฌ $A$์˜ ํ–‰๋ ฌ์‹์˜ ์ ˆ๋Œ“๊ฐ’ $|\det(A)|$๋Š” ํ–‰๋ฒกํ„ฐ(๋˜๋Š” ์—ด๋ฒกํ„ฐ)๋กœ ์ด๋ฃจ์–ด์ง„ ํ‰ํ–‰๋‹ค๋ฉด์ฒด์˜ ๋ถ€ํ”ผ์ž…๋‹ˆ๋‹ค.

  • 2D: $|\det(A)|$ = ๋‘ ๋ฒกํ„ฐ๊ฐ€ ์ด๋ฃจ๋Š” ํ‰ํ–‰์‚ฌ๋ณ€ํ˜•์˜ ๋„“์ด
  • 3D: $|\det(A)|$ = ์„ธ ๋ฒกํ„ฐ๊ฐ€ ์ด๋ฃจ๋Š” ํ‰ํ–‰์œก๋ฉด์ฒด์˜ ๋ถ€ํ”ผ

$\det(A)$์˜ ๋ถ€ํ˜ธ๋Š” ๋ฐฉํ–ฅ(orientation)์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค: - $\det > 0$: ์˜ค๋ฅธ์† ์ขŒํ‘œ๊ณ„ ๋ณด์กด - $\det < 0$: ์ขŒํ‘œ๊ณ„ ๋ฐ˜์ „ (๊ฑฐ์šธ ๋ฐ˜์‚ฌ ํฌํ•จ)

import matplotlib.pyplot as plt

# 2D์—์„œ์˜ ํ–‰๋ ฌ์‹ = ๋„“์ด
fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# ๋ณ€ํ™˜ ์ „: ๋‹จ์œ„ ์ •์‚ฌ๊ฐํ˜•
square = np.array([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]).T

A = np.array([[2, 1], [0, 3]])  # det = 6

# ๋ณ€ํ™˜ ํ›„
transformed = A @ square

for ax, shape, title in [(axes[0], square, '๋‹จ์œ„ ์ •์‚ฌ๊ฐํ˜• (๋„“์ด=1)'),
                          (axes[1], transformed, f'๋ณ€ํ™˜ ํ›„ (๋„“์ด=|det|={abs(det(A)):.0f})')]:
    ax.fill(shape[0], shape[1], alpha=0.3, color='blue')
    ax.plot(shape[0], shape[1], 'b-', linewidth=2)
    ax.set_xlim(-1, 8)
    ax.set_ylim(-1, 5)
    ax.set_aspect('equal')
    ax.grid(True, alpha=0.3)
    ax.set_title(title)
    ax.axhline(y=0, color='k', linewidth=0.5)
    ax.axvline(x=0, color='k', linewidth=0.5)

plt.tight_layout()
plt.savefig('determinant_area.png', dpi=100, bbox_inches='tight')
plt.close()
print(f"det(A) = {det(A):.0f}: ๋„“์ด๊ฐ€ {abs(det(A)):.0f}๋ฐฐ ํ™•๋Œ€")

3. ์—ญํ–‰๋ ฌ๊ณผ ์—ฐ๋ฆฝ๋ฐฉ์ •์‹

3.1 ์—ญํ–‰๋ ฌ (Inverse Matrix)

์ •๋ฐฉํ–‰๋ ฌ $A$์˜ ์—ญํ–‰๋ ฌ $A^{-1}$๋Š” ๋‹ค์Œ์„ ๋งŒ์กฑํ•ฉ๋‹ˆ๋‹ค:

$$ AA^{-1} = A^{-1}A = I $$

์—ญํ–‰๋ ฌ์ด ์กด์žฌํ•˜๊ธฐ ์œ„ํ•œ ํ•„์š”์ถฉ๋ถ„์กฐ๊ฑด: $\det(A) \neq 0$ (๋น„ํŠน์ดํ–‰๋ ฌ, non-singular)

์—ฌ์ธ์ˆ˜ ํ–‰๋ ฌ์„ ์ด์šฉํ•œ ์—ญํ–‰๋ ฌ:

$$ A^{-1} = \frac{1}{\det(A)} \text{adj}(A) $$

์—ฌ๊ธฐ์„œ $\text{adj}(A)$๋Š” ์ˆ˜๋ฐ˜ ํ–‰๋ ฌ(adjugate matrix)๋กœ, ์—ฌ์ธ์ˆ˜ ํ–‰๋ ฌ์˜ ์ „์น˜์ž…๋‹ˆ๋‹ค: $\text{adj}(A)_{ij} = C_{ji}$

2ร—2 ์—ญํ–‰๋ ฌ:

$$ \begin{pmatrix} a & b \\ c & d \end{pmatrix}^{-1} = \frac{1}{ad - bc} \begin{pmatrix} d & -b \\ -c & a \end{pmatrix} $$

A = np.array([[2, 1], [5, 3]])
A_inv = np.linalg.inv(A)

print("A =\n", A)
print("A^{-1} =\n", A_inv)
print("A @ A^{-1} =\n", np.round(A @ A_inv, 10))

# ์ˆ˜๋ฐ˜ ํ–‰๋ ฌ์„ ์ด์šฉํ•œ ์ˆ˜๋™ ๊ณ„์‚ฐ
d = det(A)  # 2*3 - 1*5 = 1
adj_A = np.array([[3, -1], [-5, 2]])  # ์—ฌ์ธ์ˆ˜ ์ „์น˜
manual_inv = adj_A / d
print("\n์ˆ˜๋™ ๊ณ„์‚ฐ:\n", manual_inv)

3.2 ๊ฐ€์šฐ์Šค ์†Œ๊ฑฐ๋ฒ• (Gaussian Elimination)

์—ฐ๋ฆฝ์ผ์ฐจ๋ฐฉ์ •์‹ $A\mathbf{x} = \mathbf{b}$๋ฅผ ํ™•๋Œ€ ํ–‰๋ ฌ $(A | \mathbf{b})$์— ๋Œ€ํ•ด ํ–‰ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ํ’‰๋‹ˆ๋‹ค.

ํ—ˆ์šฉ๋˜๋Š” ๊ธฐ๋ณธ ํ–‰ ์—ฐ์‚ฐ: 1. ๋‘ ํ–‰์˜ ๊ตํ™˜ 2. ํ•œ ํ–‰์— 0์ด ์•„๋‹Œ ์ƒ์ˆ˜๋ฅผ ๊ณฑํ•จ 3. ํ•œ ํ–‰์˜ ์ƒ์ˆ˜๋ฐฐ๋ฅผ ๋‹ค๋ฅธ ํ–‰์— ๋”ํ•จ

๋ชฉํ‘œ: ์ƒ์‚ผ๊ฐ ํ–‰๋ ฌ(๋˜๋Š” ๊ธฐ์•ฝ ํ–‰ ์‚ฌ๋‹ค๋ฆฌ๊ผด)๋กœ ๋ณ€ํ™˜ ํ›„ ํ›„์ง„ ๋Œ€์ž…

def gauss_eliminate(A_aug, verbose=True):
    """๊ฐ€์šฐ์Šค ์†Œ๊ฑฐ๋ฒ•์œผ๋กœ ์—ฐ๋ฆฝ๋ฐฉ์ •์‹์„ ํ’‰๋‹ˆ๋‹ค.

    A_aug: ํ™•๋Œ€ ํ–‰๋ ฌ [A | b]
    """
    A = A_aug.astype(float).copy()
    n = A.shape[0]

    # ์ „์ง„ ์†Œ๊ฑฐ (forward elimination)
    for col in range(n):
        # ํ”ผ๋ด‡ ์„ ํƒ (๋ถ€๋ถ„ ํ”ผ๋ด‡ํŒ…)
        max_row = col + np.argmax(np.abs(A[col:, col]))
        if max_row != col:
            A[[col, max_row]] = A[[max_row, col]]

        if abs(A[col, col]) < 1e-12:
            print(f"๊ฒฝ๊ณ : ํ”ผ๋ด‡์ด 0์— ๊ฐ€๊น์Šต๋‹ˆ๋‹ค (์—ด {col})")
            continue

        # ์•„๋ž˜ ํ–‰๋“ค ์†Œ๊ฑฐ
        for row in range(col + 1, n):
            factor = A[row, col] / A[col, col]
            A[row] -= factor * A[col]

    if verbose:
        print("์ƒ์‚ผ๊ฐ ํ–‰๋ ฌ:\n", np.round(A, 4))

    # ํ›„์ง„ ๋Œ€์ž… (back substitution)
    x = np.zeros(n)
    for i in range(n - 1, -1, -1):
        x[i] = (A[i, -1] - A[i, i+1:n] @ x[i+1:n]) / A[i, i]

    return x

# ์˜ˆ์ œ: 3x3 ์—ฐ๋ฆฝ๋ฐฉ์ •์‹
# 2x + y - z = 8
# -3x - y + 2z = -11
# -2x + y + 2z = -3
A = np.array([[2, 1, -1],
              [-3, -1, 2],
              [-2, 1, 2]])
b = np.array([8, -11, -3])

A_aug = np.column_stack([A, b])
x = gauss_eliminate(A_aug)
print(f"\nํ•ด: x = {x}")
print(f"๊ฒ€์ฆ Ax = {A @ x}")

# NumPy ๋‚ด์žฅ ํ•จ์ˆ˜์™€ ๋น„๊ต
x_np = np.linalg.solve(A, b)
print(f"NumPy solve: {x_np}")

3.3 ํฌ๋ž˜๋จธ ๋ฒ•์น™ (Cramer's Rule)

์—ฐ๋ฆฝ๋ฐฉ์ •์‹ $A\mathbf{x} = \mathbf{b}$์—์„œ, $\det(A) \neq 0$์ด๋ฉด ๊ฐ ๋ฏธ์ง€์ˆ˜๋Š”:

$$ x_i = \frac{\det(A_i)}{\det(A)} $$

์—ฌ๊ธฐ์„œ $A_i$๋Š” $A$์˜ $i$๋ฒˆ์งธ ์—ด์„ $\mathbf{b}$๋กœ ๋Œ€์ฒดํ•œ ํ–‰๋ ฌ์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ : ํฌ๋ž˜๋จธ ๋ฒ•์น™์€ ์ด๋ก ์ ์œผ๋กœ ์ค‘์š”ํ•˜์ง€๋งŒ, ๊ณ„์‚ฐ ํšจ์œจ์„ฑ์€ ๊ฐ€์šฐ์Šค ์†Œ๊ฑฐ๋ฒ•๋ณด๋‹ค ๋‚ฎ์Šต๋‹ˆ๋‹ค. $n$์ด ํฌ๋ฉด ๊ฐ€์šฐ์Šค ์†Œ๊ฑฐ๋ฒ•($O(n^3)$)์ด ํฌ๋ž˜๋จธ ๋ฒ•์น™($O(n \cdot n!)$)๋ณด๋‹ค ํ›จ์”ฌ ๋น ๋ฆ…๋‹ˆ๋‹ค.

def cramer(A, b):
    """ํฌ๋ž˜๋จธ ๋ฒ•์น™์œผ๋กœ Ax = b๋ฅผ ํ’‰๋‹ˆ๋‹ค."""
    n = len(b)
    d = det(A)
    if abs(d) < 1e-12:
        raise ValueError("ํ–‰๋ ฌ์‹์ด 0: ์œ ์ผํ•œ ํ•ด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Œ")

    x = np.zeros(n)
    for i in range(n):
        A_i = A.copy()
        A_i[:, i] = b
        x[i] = det(A_i) / d
    return x

# ์˜ˆ์ œ
A = np.array([[2, 1, -1],
              [-3, -1, 2],
              [-2, 1, 2]])
b = np.array([8, -11, -3])

x = cramer(A, b)
print(f"ํฌ๋ž˜๋จธ ๋ฒ•์น™ ํ•ด: {x}")

3.4 ํ–‰๋ ฌ์˜ ๊ณ„์ˆ˜ (Rank)

ํ–‰๋ ฌ์˜ ๊ณ„์ˆ˜(rank)๋Š” ์„ ํ˜• ๋…๋ฆฝ์ธ ํ–‰(๋˜๋Š” ์—ด)์˜ ์ตœ๋Œ€ ๊ฐœ์ˆ˜์ž…๋‹ˆ๋‹ค.

$$ \text{rank}(A) = \text{dim}(\text{Col}(A)) = \text{dim}(\text{Row}(A)) $$

์—ฐ๋ฆฝ๋ฐฉ์ •์‹์˜ ํ•ด์˜ ์กด์žฌ์„ฑ: - $\text{rank}(A) = \text{rank}(A|b) = n$: ์œ ์ผํ•œ ํ•ด - $\text{rank}(A) = \text{rank}(A|b) < n$: ๋ฌดํ•œํžˆ ๋งŽ์€ ํ•ด - $\text{rank}(A) < \text{rank}(A|b)$: ํ•ด ์—†์Œ (๋ถˆ๋Šฅ)

# ๊ณ„์ˆ˜ ์˜ˆ์ œ
A_full = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 10]])  # rank 3
A_deficient = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])  # rank 2 (3ํ–‰ = ํ–‰1 + 2*ํ–‰2 ์•„๋‹˜, ํ•˜์ง€๋งŒ 1+3=2*2)

print(f"rank(A_full) = {np.linalg.matrix_rank(A_full)}")
print(f"rank(A_deficient) = {np.linalg.matrix_rank(A_deficient)}")
print(f"det(A_full) = {det(A_full):.4f}")
print(f"det(A_deficient) = {det(A_deficient):.4f}")

4. ๊ณ ์œ ๊ฐ’๊ณผ ๊ณ ์œ ๋ฒกํ„ฐ (Eigenvalues and Eigenvectors)

4.1 ์ •์˜์™€ ํŠน์„ฑ ๋ฐฉ์ •์‹

์ •๋ฐฉํ–‰๋ ฌ $A$์— ๋Œ€ํ•ด, ๋‹ค์Œ์„ ๋งŒ์กฑํ•˜๋Š” 0์ด ์•„๋‹Œ ๋ฒกํ„ฐ $\mathbf{v}$์™€ ์Šค์นผ๋ผ $\lambda$๋ฅผ ์ฐพ๋Š” ๋ฌธ์ œ:

$$ A\mathbf{v} = \lambda\mathbf{v} $$

  • $\lambda$: ๊ณ ์œ ๊ฐ’(eigenvalue)
  • $\mathbf{v}$: ๊ณ ์œ ๋ฒกํ„ฐ(eigenvector)

๊ธฐํ•˜ํ•™์  ์˜๋ฏธ: $A$์— ์˜ํ•œ ์„ ํ˜• ๋ณ€ํ™˜์—์„œ, ๊ณ ์œ ๋ฒกํ„ฐ๋Š” ๋ฐฉํ–ฅ์ด ๋ณ€ํ•˜์ง€ ์•Š๋Š” ํŠน๋ณ„ํ•œ ๋ฒกํ„ฐ์ž…๋‹ˆ๋‹ค. ๊ณ ์œ ๊ฐ’์€ ๊ทธ ๋ฐฉํ–ฅ์œผ๋กœ์˜ ๋Š˜๋ฆผ/์ค„์ž„ ๋น„์œจ์ž…๋‹ˆ๋‹ค.

ํŠน์„ฑ ๋ฐฉ์ •์‹(characteristic equation):

$$ \det(A - \lambda I) = 0 $$

์ด๊ฒƒ์€ $\lambda$์— ๋Œ€ํ•œ $n$์ฐจ ๋‹คํ•ญ์‹์œผ๋กœ, ํŠน์„ฑ ๋‹คํ•ญ์‹(characteristic polynomial)์ด๋ผ ํ•ฉ๋‹ˆ๋‹ค.

import numpy as np
from numpy.linalg import eig

# 2x2 ํ–‰๋ ฌ์˜ ๊ณ ์œ ๊ฐ’/๊ณ ์œ ๋ฒกํ„ฐ
A = np.array([[4, 2], [1, 3]])

eigenvalues, eigenvectors = eig(A)
print("๊ณ ์œ ๊ฐ’:", eigenvalues)
print("๊ณ ์œ ๋ฒกํ„ฐ (์—ด๋ฒกํ„ฐ):\n", eigenvectors)

# ๊ฒ€์ฆ: Av = ฮปv
for i in range(len(eigenvalues)):
    lam = eigenvalues[i]
    v = eigenvectors[:, i]
    Av = A @ v
    lam_v = lam * v
    print(f"\nฮป_{i+1} = {lam:.4f}")
    print(f"v_{i+1} = {v}")
    print(f"Av = {Av}")
    print(f"ฮปv = {lam_v}")
    print(f"Av โ‰ˆ ฮปv: {np.allclose(Av, lam_v)}")

4.2 ์ˆ˜๋™ ๊ณ„์‚ฐ ์˜ˆ์ œ

$A = \begin{pmatrix} 3 & 1 \\ 0 & 2 \end{pmatrix}$์˜ ๊ณ ์œ ๊ฐ’/๊ณ ์œ ๋ฒกํ„ฐ:

ํŠน์„ฑ ๋ฐฉ์ •์‹: $$ \det(A - \lambda I) = \det\begin{pmatrix} 3-\lambda & 1 \\ 0 & 2-\lambda \end{pmatrix} = (3-\lambda)(2-\lambda) = 0 $$

$\lambda_1 = 3$, $\lambda_2 = 2$

๊ณ ์œ ๋ฒกํ„ฐ ($\lambda_1 = 3$): $$ (A - 3I)\mathbf{v} = \begin{pmatrix} 0 & 1 \\ 0 & -1 \end{pmatrix}\mathbf{v} = 0 \implies v_2 = 0 \implies \mathbf{v}_1 = \begin{pmatrix} 1 \\ 0 \end{pmatrix} $$

๊ณ ์œ ๋ฒกํ„ฐ ($\lambda_2 = 2$): $$ (A - 2I)\mathbf{v} = \begin{pmatrix} 1 & 1 \\ 0 & 0 \end{pmatrix}\mathbf{v} = 0 \implies v_1 + v_2 = 0 \implies \mathbf{v}_2 = \begin{pmatrix} -1 \\ 1 \end{pmatrix} $$

import sympy as sp

# SymPy๋ฅผ ์ด์šฉํ•œ ํ•ด์„์  ๊ณ„์‚ฐ
A_sym = sp.Matrix([[3, 1], [0, 2]])
print("ํŠน์„ฑ ๋‹คํ•ญ์‹:", A_sym.charpoly().as_expr())
print("๊ณ ์œ ๊ฐ’:", A_sym.eigenvals())  # {3: 1, 2: 1} (๊ณ ์œ ๊ฐ’: ์ค‘๋ณต๋„)
print("๊ณ ์œ ๋ฒกํ„ฐ:", A_sym.eigenvects())

4.3 ํ–‰๋ ฌ์˜ ๋Œ€๊ฐํ™” (Diagonalization)

$n \times n$ ํ–‰๋ ฌ $A$๊ฐ€ $n$๊ฐœ์˜ ์„ ํ˜• ๋…๋ฆฝ์ธ ๊ณ ์œ ๋ฒกํ„ฐ๋ฅผ ๊ฐ€์ง€๋ฉด ๋Œ€๊ฐํ™” ๊ฐ€๋Šฅ(diagonalizable)ํ•ฉ๋‹ˆ๋‹ค.

๊ณ ์œ ๋ฒกํ„ฐ๋ฅผ ์—ด๋กœ ๋‚˜์—ดํ•œ ํ–‰๋ ฌ $P = [\mathbf{v}_1 | \mathbf{v}_2 | \cdots | \mathbf{v}_n]$์„ ๊ตฌ์„ฑํ•˜๋ฉด:

$$ P^{-1}AP = D = \text{diag}(\lambda_1, \lambda_2, \ldots, \lambda_n) $$

๋Œ€๊ฐํ™”์˜ ์œ ์šฉ์„ฑ:

  • ๊ฑฐ๋“ญ์ œ๊ณฑ: $A^k = P D^k P^{-1}$์ด๋ฏ€๋กœ $D^k$๋Š” ๋Œ€๊ฐ ์›์†Œ๋ฅผ $k$์ œ๊ณฑํ•˜๋ฉด ๋จ
  • ์ง€์ˆ˜ํ•จ์ˆ˜: $e^{At} = P \, e^{Dt} \, P^{-1}$, ์—ฌ๊ธฐ์„œ $e^{Dt} = \text{diag}(e^{\lambda_1 t}, \ldots, e^{\lambda_n t})$
  • ์—ฐ๋ฆฝ ODE: $\dot{\mathbf{x}} = A\mathbf{x}$๋ฅผ ๋…๋ฆฝ์ ์ธ ์Šค์นผ๋ผ ODE๋กœ ๋ถ„๋ฆฌ
# ๋Œ€๊ฐํ™” ์˜ˆ์ œ
A = np.array([[4, 2], [1, 3]])
eigenvalues, P = eig(A)
D = np.diag(eigenvalues)

print("P (๊ณ ์œ ๋ฒกํ„ฐ ํ–‰๋ ฌ):\n", P)
print("D (๋Œ€๊ฐ ํ–‰๋ ฌ):\n", D)

# ๊ฒ€์ฆ: A = P D P^{-1}
P_inv = np.linalg.inv(P)
A_reconstructed = P @ D @ P_inv
print("\nP D P^{-1} =\n", np.round(A_reconstructed, 10))
print("A์™€ ์ผ์น˜:", np.allclose(A, A_reconstructed))

# ์‘์šฉ: A^10 ๊ณ„์‚ฐ
A_power_10 = P @ np.diag(eigenvalues**10) @ P_inv
print(f"\nA^10 =\n{np.round(A_power_10.real, 2)}")
print(f"์ง์ ‘ ๊ณ„์‚ฐ:\n{np.round(np.linalg.matrix_power(A, 10).astype(float), 2)}")

4.4 ๋Œ€์นญ ํ–‰๋ ฌ๊ณผ ์—๋ฅด๋ฏธํŠธ ํ–‰๋ ฌ์˜ ์„ฑ์งˆ

์ŠคํŽ™ํŠธ๋Ÿผ ์ •๋ฆฌ(Spectral Theorem):

  1. ์‹ค๋Œ€์นญ ํ–‰๋ ฌ ($A^T = A$):
  2. ๋ชจ๋“  ๊ณ ์œ ๊ฐ’์ด ์‹ค์ˆ˜
  3. ์„œ๋กœ ๋‹ค๋ฅธ ๊ณ ์œ ๊ฐ’์— ๋Œ€์‘ํ•˜๋Š” ๊ณ ์œ ๋ฒกํ„ฐ๋Š” ์ง๊ต
  4. ์ง๊ต ํ–‰๋ ฌ $Q$๋กœ ๋Œ€๊ฐํ™” ๊ฐ€๋Šฅ: $Q^T A Q = D$, $Q^T = Q^{-1}$

  5. ์—๋ฅด๋ฏธํŠธ ํ–‰๋ ฌ ($A^\dagger = A$):

  6. ๋ชจ๋“  ๊ณ ์œ ๊ฐ’์ด ์‹ค์ˆ˜
  7. ์„œ๋กœ ๋‹ค๋ฅธ ๊ณ ์œ ๊ฐ’์— ๋Œ€์‘ํ•˜๋Š” ๊ณ ์œ ๋ฒกํ„ฐ๋Š” ์ง๊ต
  8. ์œ ๋‹ˆํ„ฐ๋ฆฌ ํ–‰๋ ฌ $U$๋กœ ๋Œ€๊ฐํ™” ๊ฐ€๋Šฅ: $U^\dagger A U = D$, $U^\dagger = U^{-1}$
# ์‹ค๋Œ€์นญ ํ–‰๋ ฌ์˜ ์„ฑ์งˆ
A_sym = np.array([[4, 1, 2],
                   [1, 3, 1],
                   [2, 1, 5]])

eigenvalues, eigenvectors = eig(A_sym)
print("๋Œ€์นญ ํ–‰๋ ฌ์˜ ๊ณ ์œ ๊ฐ’:", eigenvalues)
print("๋ชจ๋‘ ์‹ค์ˆ˜:", np.allclose(eigenvalues.imag, 0))

# ๊ณ ์œ ๋ฒกํ„ฐ์˜ ์ง๊ต์„ฑ ํ™•์ธ
print("\n๊ณ ์œ ๋ฒกํ„ฐ ๋‚ด์ :")
for i in range(3):
    for j in range(i+1, 3):
        dot = eigenvectors[:, i] @ eigenvectors[:, j]
        print(f"  v{i+1} ยท v{j+1} = {dot:.6e}")

# ์ง๊ต ํ–‰๋ ฌ๋กœ ๋Œ€๊ฐํ™”
Q = eigenvectors
print(f"\nQ^T Q =\n{np.round(Q.T @ Q, 10)}")
print("Q๋Š” ์ง๊ต ํ–‰๋ ฌ:", np.allclose(Q.T @ Q, np.eye(3)))

4.5 ์ฃผ์š” ํ–‰๋ ฌ ๋ถ„ํ•ด๋ฒ• ์š”์•ฝ

๋ถ„ํ•ด๋ฒ• ํ˜•ํƒœ ์กฐ๊ฑด ๋ฌผ๋ฆฌ์  ์‘์šฉ
๊ณ ์œ ๊ฐ’ ๋ถ„ํ•ด $A = PDP^{-1}$ $n$๊ฐœ ๋…๋ฆฝ ๊ณ ์œ ๋ฒกํ„ฐ ์ง„๋™ ๋ชจ๋“œ, ์•ˆ์ •์„ฑ
์ง๊ต ๋Œ€๊ฐํ™” $A = QDQ^T$ ๋Œ€์นญ ํ–‰๋ ฌ ์ฃผ์ถ• ์ •๋ฆฌ, ๊ด€์„ฑ ํ…์„œ
SVD $A = U\Sigma V^T$ ์ž„์˜์˜ $m \times n$ ๋ฐ์ดํ„ฐ ์ถ•์†Œ, ์ตœ์†Œ์ž์Šน
LU ๋ถ„ํ•ด $A = LU$ ์ •๋ฐฉํ–‰๋ ฌ ์—ฐ๋ฆฝ๋ฐฉ์ •์‹ ํšจ์œจ ํ’€์ด
์ด๋ ˆ์Šคํ‚ค $A = LL^T$ ์–‘์ •์น˜ ๋Œ€์นญ ํ†ต๊ณ„, ์ตœ์ ํ™”

5. ์ด์ฐจํ˜•์‹๊ณผ ์–‘์ •์น˜์„ฑ (Quadratic Forms)

5.1 ์ด์ฐจํ˜•์‹์˜ ์ •์˜

๋ฒกํ„ฐ $\mathbf{x} \in \mathbb{R}^n$์— ๋Œ€ํ•œ ์ด์ฐจํ˜•์‹(quadratic form):

$$ Q(\mathbf{x}) = \mathbf{x}^T A \mathbf{x} = \sum_{i,j} a_{ij} x_i x_j $$

์—ฌ๊ธฐ์„œ $A$๋Š” ํ•ญ์ƒ ๋Œ€์นญ ํ–‰๋ ฌ๋กœ ์ทจ๊ธ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (๋น„๋Œ€์นญ ๋ถ€๋ถ„์€ ์ด์ฐจํ˜•์‹์— ๊ธฐ์—ฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ $A \to (A + A^T)/2$).

2๋ณ€์ˆ˜ ์˜ˆ:

$$ Q(x, y) = \begin{pmatrix} x & y \end{pmatrix} \begin{pmatrix} a & b \\ b & c \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} = ax^2 + 2bxy + cy^2 $$

5.2 ์–‘์ •์น˜์„ฑ ํŒ๋ณ„

๋Œ€์นญ ํ–‰๋ ฌ $A$์˜ ์ •์น˜์„ฑ(definiteness):

๋ถ„๋ฅ˜ ์กฐ๊ฑด ๊ณ ์œ ๊ฐ’ ์กฐ๊ฑด
์–‘์ •์น˜ (positive definite) $\mathbf{x}^T A \mathbf{x} > 0$ (๋ชจ๋“  $\mathbf{x} \neq 0$) ๋ชจ๋“  $\lambda_i > 0$
์–‘๋ฐ˜์ •์น˜ (positive semidefinite) $\mathbf{x}^T A \mathbf{x} \geq 0$ ๋ชจ๋“  $\lambda_i \geq 0$
์Œ์ •์น˜ (negative definite) $\mathbf{x}^T A \mathbf{x} < 0$ (๋ชจ๋“  $\mathbf{x} \neq 0$) ๋ชจ๋“  $\lambda_i < 0$
๋ถ€์ •์น˜ (indefinite) ์–‘์ˆ˜์™€ ์Œ์ˆ˜ ๋ชจ๋‘ ๊ฐ€๋Šฅ ์–‘์ˆ˜/์Œ์ˆ˜ ๊ณ ์œ ๊ฐ’ ํ˜ผ์žฌ

์‹ค๋ฒก์Šคํ„ฐ ๊ธฐ์ค€(Sylvester's criterion): ๋Œ€์นญ ํ–‰๋ ฌ์ด ์–‘์ •์น˜์ผ ํ•„์š”์ถฉ๋ถ„์กฐ๊ฑด์€ ๋ชจ๋“  ์„ ํ–‰ ์ฃผ ์†Œํ–‰๋ ฌ์‹(leading principal minors)์ด ์–‘์ˆ˜:

$$ a_{11} > 0, \quad \det\begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{pmatrix} > 0, \quad \det\begin{pmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \end{pmatrix} > 0, \quad \ldots $$

def check_definiteness(A):
    """๋Œ€์นญ ํ–‰๋ ฌ์˜ ์ •์น˜์„ฑ์„ ํŒ๋ณ„ํ•ฉ๋‹ˆ๋‹ค."""
    eigenvalues = np.linalg.eigvalsh(A)  # ๋Œ€์นญ ํ–‰๋ ฌ ์ „์šฉ
    print(f"๊ณ ์œ ๊ฐ’: {eigenvalues}")

    if all(eigenvalues > 0):
        return "์–‘์ •์น˜ (positive definite)"
    elif all(eigenvalues >= 0):
        return "์–‘๋ฐ˜์ •์น˜ (positive semidefinite)"
    elif all(eigenvalues < 0):
        return "์Œ์ •์น˜ (negative definite)"
    elif all(eigenvalues <= 0):
        return "์Œ๋ฐ˜์ •์น˜ (negative semidefinite)"
    else:
        return "๋ถ€์ •์น˜ (indefinite)"

# ์˜ˆ์ œ
matrices = {
    "์–‘์ •์น˜": np.array([[2, -1], [-1, 2]]),
    "๋ถ€์ •์น˜": np.array([[1, 3], [3, 1]]),
    "์–‘๋ฐ˜์ •์น˜": np.array([[1, 1], [1, 1]]),
}

for name, M in matrices.items():
    result = check_definiteness(M)
    print(f"{name} ํ–‰๋ ฌ: {result}\n")

5.3 ์ฃผ์ถ• ์ •๋ฆฌ (Principal Axis Theorem)

์ด์ฐจํ˜•์‹์„ ์ฃผ์ถ• ์ขŒํ‘œ๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด ๊ต์ฐจํ•ญ์ด ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

๋Œ€์นญ ํ–‰๋ ฌ $A = Q D Q^T$์ด๋ฉด:

$$ Q(\mathbf{x}) = \mathbf{x}^T A \mathbf{x} = \mathbf{y}^T D \mathbf{y} = \lambda_1 y_1^2 + \lambda_2 y_2^2 + \cdots + \lambda_n y_n^2 $$

์—ฌ๊ธฐ์„œ $\mathbf{y} = Q^T \mathbf{x}$ (์ฃผ์ถ• ์ขŒํ‘œ).

์ด๊ฒƒ์€ ๋ฌผ๋ฆฌํ•™์—์„œ ๊ด€์„ฑ ํ…์„œ์˜ ์ฃผ์ถ• ๋ณ€ํ™˜, ์‘๋ ฅ ํ…์„œ์˜ ์ฃผ์‘๋ ฅ ๋ฐฉํ–ฅ ๋“ฑ์— ์ง์ ‘ ์‘์šฉ๋ฉ๋‹ˆ๋‹ค.

import matplotlib.pyplot as plt

# ์ด์ฐจ๊ณก๋ฉด๊ณผ ์ฃผ์ถ• ๋ณ€ํ™˜ ์‹œ๊ฐํ™”
A = np.array([[5, 2], [2, 2]])
eigenvalues, Q = np.linalg.eigh(A)

print(f"์›๋ž˜ ์ด์ฐจํ˜•์‹: 5xยฒ + 4xy + 2yยฒ")
print(f"๊ณ ์œ ๊ฐ’: ฮปโ‚={eigenvalues[0]:.2f}, ฮปโ‚‚={eigenvalues[1]:.2f}")
print(f"์ฃผ์ถ• ์ขŒํ‘œ: {eigenvalues[0]:.2f}yโ‚ยฒ + {eigenvalues[1]:.2f}yโ‚‚ยฒ")

# ํƒ€์› ์‹œ๊ฐํ™”
theta = np.linspace(0, 2*np.pi, 200)
fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# ์›๋ž˜ ์ขŒํ‘œ๊ณ„์—์„œ์˜ ํƒ€์› (5xยฒ + 4xy + 2yยฒ = 1)
# ๋งค๊ฐœ๋ณ€์ˆ˜ ํ‘œํ˜„ ์ด์šฉ
t = np.linspace(0, 2*np.pi, 200)
# ์ฃผ์ถ• ์ขŒํ‘œ์—์„œ ํƒ€์›: ฮปโ‚yโ‚ยฒ + ฮปโ‚‚yโ‚‚ยฒ = 1
y1 = np.cos(t) / np.sqrt(eigenvalues[0])
y2 = np.sin(t) / np.sqrt(eigenvalues[1])
# ์›๋ž˜ ์ขŒํ‘œ๋กœ ๋ณ€ํ™˜: x = Q y
xy = Q @ np.array([y1, y2])

axes[0].plot(xy[0], xy[1], 'b-', linewidth=2)
# ์ฃผ์ถ• ๋ฐฉํ–ฅ
for i in range(2):
    v = Q[:, i] / np.sqrt(eigenvalues[i])
    axes[0].arrow(0, 0, v[0], v[1], head_width=0.03, color=['red', 'green'][i],
                  linewidth=2, label=f'์ฃผ์ถ• {i+1} (ฮป={eigenvalues[i]:.2f})')
axes[0].set_aspect('equal')
axes[0].grid(True, alpha=0.3)
axes[0].legend()
axes[0].set_title('์›๋ž˜ ์ขŒํ‘œ๊ณ„: 5xยฒ + 4xy + 2yยฒ = 1')

# ์ฃผ์ถ• ์ขŒํ‘œ์—์„œ์˜ ํƒ€์› (์ถ• ์ •๋ ฌ)
y1 = np.cos(t) / np.sqrt(eigenvalues[0])
y2 = np.sin(t) / np.sqrt(eigenvalues[1])
axes[1].plot(y1, y2, 'b-', linewidth=2)
axes[1].axhline(y=0, color='green', linewidth=1.5, label=f'yโ‚‚์ถ• (ฮป={eigenvalues[1]:.2f})')
axes[1].axvline(x=0, color='red', linewidth=1.5, label=f'yโ‚์ถ• (ฮป={eigenvalues[0]:.2f})')
axes[1].set_aspect('equal')
axes[1].grid(True, alpha=0.3)
axes[1].legend()
axes[1].set_title(f'์ฃผ์ถ• ์ขŒํ‘œ: {eigenvalues[0]:.2f}yโ‚ยฒ + {eigenvalues[1]:.2f}yโ‚‚ยฒ = 1')

plt.tight_layout()
plt.savefig('principal_axes.png', dpi=100, bbox_inches='tight')
plt.close()

6. ๋ฌผ๋ฆฌํ•™ ์‘์šฉ

6.1 ๊ด€์„ฑ ํ…์„œ์™€ ์ฃผ์ถ• (Moment of Inertia Tensor)

๊ฐ•์ฒด์˜ ๊ด€์„ฑ ํ…์„œ(moment of inertia tensor)๋Š” $3 \times 3$ ๋Œ€์นญ ํ–‰๋ ฌ์ž…๋‹ˆ๋‹ค:

$$ I = \begin{pmatrix} I_{xx} & -I_{xy} & -I_{xz} \\ -I_{yx} & I_{yy} & -I_{yz} \\ -I_{zx} & -I_{zy} & I_{zz} \end{pmatrix} $$

์—ฌ๊ธฐ์„œ: - $I_{xx} = \sum m_i (y_i^2 + z_i^2)$ (๊ด€์„ฑ ๋ชจ๋ฉ˜ํŠธ) - $I_{xy} = \sum m_i x_i y_i$ (๊ด€์„ฑ๊ณฑ)

์ฃผ์ถ• ๋ณ€ํ™˜: $I$๋ฅผ ๋Œ€๊ฐํ™”ํ•˜๋ฉด ์ฃผ๊ด€์„ฑ ๋ชจ๋ฉ˜ํŠธ $I_1, I_2, I_3$์™€ ์ฃผ์ถ•(principal axes)์„ ์–ป์Šต๋‹ˆ๋‹ค.

$$ Q^T I Q = \text{diag}(I_1, I_2, I_3) $$

์ฃผ์ถ• ์ขŒํ‘œ๊ณ„์—์„œ ๊ฐ์šด๋™๋Ÿ‰์€ $L_i = I_i \omega_i$๋กœ ๋‹จ์ˆœํ™”๋ฉ๋‹ˆ๋‹ค.

# ๊ด€์„ฑ ํ…์„œ ์˜ˆ์ œ: ์ •์œก๋ฉด์ฒด ๊ผญ์ง“์ ์— ์งˆ๋Ÿ‰์ด ์žˆ๋Š” ๊ฒฝ์šฐ
# ์ •์œก๋ฉด์ฒด ๊ผญ์ง“์  ์ขŒํ‘œ (๋ณ€์˜ ๊ธธ์ด 2, ์ค‘์‹ฌ ์›์ )
vertices = np.array([
    [ 1,  1,  1], [ 1,  1, -1], [ 1, -1,  1], [ 1, -1, -1],
    [-1,  1,  1], [-1,  1, -1], [-1, -1,  1], [-1, -1, -1]
], dtype=float)

m = 1.0  # ๊ฐ ๊ผญ์ง“์ ์˜ ์งˆ๋Ÿ‰

# ๊ด€์„ฑ ํ…์„œ ๊ณ„์‚ฐ
I_tensor = np.zeros((3, 3))
for r in vertices:
    I_tensor += m * (np.dot(r, r) * np.eye(3) - np.outer(r, r))

print("๊ด€์„ฑ ํ…์„œ:\n", I_tensor)

# ๋Œ€๊ฐํ™” โ†’ ์ฃผ๊ด€์„ฑ ๋ชจ๋ฉ˜ํŠธ
eigenvalues, eigenvectors = np.linalg.eigh(I_tensor)
print(f"\n์ฃผ๊ด€์„ฑ ๋ชจ๋ฉ˜ํŠธ: Iโ‚={eigenvalues[0]:.2f}, Iโ‚‚={eigenvalues[1]:.2f}, Iโ‚ƒ={eigenvalues[2]:.2f}")
print("์ฃผ์ถ• ๋ฐฉํ–ฅ:\n", eigenvectors)

6.2 ์—ฐ์„ฑ ์ง„๋™ (Coupled Oscillations)

๋‘ ๊ฐœ์˜ ์งˆ๋Ÿ‰์ด ์Šคํ”„๋ง์œผ๋กœ ์—ฐ๊ฒฐ๋œ ์‹œ์Šคํ…œ:

$$ M\ddot{\mathbf{x}} = -K\mathbf{x} $$

์—ฌ๊ธฐ์„œ $M$์€ ์งˆ๋Ÿ‰ ํ–‰๋ ฌ, $K$๋Š” ๊ฐ•์„ฑ ํ–‰๋ ฌ(stiffness matrix).

๊ณ ์œ ์ง„๋™์ˆ˜(normal frequencies)์™€ ๊ณ ์œ ๋ชจ๋“œ(normal modes)๋Š” ์ผ๋ฐ˜ํ™” ๊ณ ์œ ๊ฐ’ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค:

$$ K\mathbf{v} = \omega^2 M\mathbf{v} $$

# ์—ฐ์„ฑ ์ง„๋™ ์˜ˆ์ œ: ๋‘ ์งˆ๋Ÿ‰-์Šคํ”„๋ง ๊ณ„
# mโ‚ = mโ‚‚ = m, ์Šคํ”„๋ง ์ƒ์ˆ˜ kโ‚ = kโ‚‚ = kโ‚ƒ = k
# ์šด๋™๋ฐฉ์ •์‹: m*xโ‚'' = -k*xโ‚ + k*(xโ‚‚-xโ‚) = -2k*xโ‚ + k*xโ‚‚
#             m*xโ‚‚'' = -k*(xโ‚‚-xโ‚) - k*xโ‚‚ = k*xโ‚ - 2k*xโ‚‚

m, k = 1.0, 1.0

M_mat = m * np.eye(2)
K_mat = np.array([[2*k, -k],
                   [-k, 2*k]])

# ์ผ๋ฐ˜ํ™” ๊ณ ์œ ๊ฐ’ ๋ฌธ์ œ: K v = ฯ‰ยฒ M v
# M = mI์ด๋ฏ€๋กœ (1/m)K v = ฯ‰ยฒ v
eigenvalues, eigenvectors = np.linalg.eigh(K_mat / m)
omega = np.sqrt(eigenvalues)

print("๊ฐ•์„ฑ ํ–‰๋ ฌ K:\n", K_mat)
print(f"\n๊ณ ์œ ์ง„๋™์ˆ˜: ฯ‰โ‚ = {omega[0]:.4f}, ฯ‰โ‚‚ = {omega[1]:.4f}")
print(f"์ฃผ๊ธฐ: Tโ‚ = {2*np.pi/omega[0]:.4f}, Tโ‚‚ = {2*np.pi/omega[1]:.4f}")
print(f"\n๊ณ ์œ ๋ชจ๋“œ 1 (๋™์ƒ): {eigenvectors[:, 0]}")
print(f"๊ณ ์œ ๋ชจ๋“œ 2 (์—ญ์ƒ): {eigenvectors[:, 1]}")

# ์‹œ๊ฐ„ ๋ฐœ์ „ ์‹œ๊ฐํ™”
t = np.linspace(0, 20, 500)
# ์ดˆ๊ธฐ ์กฐ๊ฑด: xโ‚(0) = 1, xโ‚‚(0) = 0, ์†๋„ 0
# ๋ชจ๋“œ ์ขŒํ‘œ๋กœ ๋ถ„ํ•ด
eta = eigenvectors.T @ np.array([1, 0])
x = np.zeros((2, len(t)))
for i in range(2):
    x += np.outer(eigenvectors[:, i], eta[i] * np.cos(omega[i] * t))

fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(t, x[0], label='xโ‚(t)', linewidth=1.5)
ax.plot(t, x[1], label='xโ‚‚(t)', linewidth=1.5)
ax.set_xlabel('์‹œ๊ฐ„ t')
ax.set_ylabel('๋ณ€์œ„')
ax.set_title('์—ฐ์„ฑ ์ง„๋™: ๋งฅ๋†€์ด(beat) ํ˜„์ƒ')
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('coupled_oscillations.png', dpi=100, bbox_inches='tight')
plt.close()

6.3 ์–‘์ž์—ญํ•™์—์„œ์˜ ํ–‰๋ ฌ (Matrices in Quantum Mechanics)

์–‘์ž์—ญํ•™์—์„œ ๊ด€์ธก ๊ฐ€๋Šฅ๋Ÿ‰(observable)์€ ์—๋ฅด๋ฏธํŠธ ์—ฐ์‚ฐ์ž๋กœ ํ‘œํ˜„๋˜๋ฉฐ, ์œ ํ•œ ์ฐจ์›์—์„œ๋Š” ์—๋ฅด๋ฏธํŠธ ํ–‰๋ ฌ์ž…๋‹ˆ๋‹ค.

์Šคํ•€-1/2 ์ž…์ž์˜ ํŒŒ์šธ๋ฆฌ ํ–‰๋ ฌ:

$$ \sigma_x = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}, \quad \sigma_y = \begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix}, \quad \sigma_z = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix} $$

์ด๋“ค์€ ์—๋ฅด๋ฏธํŠธ($\sigma_i^\dagger = \sigma_i$)์ด๊ณ , ๊ฐ๊ฐ์˜ ๊ณ ์œ ๊ฐ’์€ $\pm 1$์ž…๋‹ˆ๋‹ค.

# ํŒŒ์šธ๋ฆฌ ํ–‰๋ ฌ
sigma_x = np.array([[0, 1], [1, 0]], dtype=complex)
sigma_y = np.array([[0, -1j], [1j, 0]])
sigma_z = np.array([[1, 0], [0, -1]], dtype=complex)

for name, sigma in [('ฯƒ_x', sigma_x), ('ฯƒ_y', sigma_y), ('ฯƒ_z', sigma_z)]:
    vals, vecs = np.linalg.eigh(sigma)
    print(f"{name}:")
    print(f"  ์—๋ฅด๋ฏธํŠธ: {np.allclose(sigma, sigma.conj().T)}")
    print(f"  ๊ณ ์œ ๊ฐ’: {vals}")
    print(f"  tr(ฯƒ) = {np.trace(sigma):.0f}, det(ฯƒ) = {np.linalg.det(sigma):.0f}")
    print()

# ๊ตํ™˜ ๊ด€๊ณ„: [ฯƒ_i, ฯƒ_j] = 2i ฮต_ijk ฯƒ_k
comm_xy = sigma_x @ sigma_y - sigma_y @ sigma_x
print("[ฯƒ_x, ฯƒ_y] = 2i ฯƒ_z:")
print(np.round(comm_xy, 10))
print("2i ฯƒ_z:")
print(2j * sigma_z)
print("์ผ์น˜:", np.allclose(comm_xy, 2j * sigma_z))

7. Python์œผ๋กœ ํ•˜๋Š” ์„ ํ˜•๋Œ€์ˆ˜

7.1 NumPy์™€ SciPy ํ™œ์šฉ

import numpy as np
from scipy import linalg

# ===== ๊ธฐ๋ณธ ์—ฐ์‚ฐ =====
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 10]])

# ํ–‰๋ ฌ์‹, ์—ญํ–‰๋ ฌ
print(f"det(A) = {np.linalg.det(A):.4f}")
print(f"A^(-1) =\n{np.linalg.inv(A)}")

# ๊ณ ์œ ๊ฐ’ ๋ถ„ํ•ด
vals, vecs = np.linalg.eig(A)
print(f"\n๊ณ ์œ ๊ฐ’: {vals}")

# ===== ๋‹ค์–‘ํ•œ ํ–‰๋ ฌ ๋ถ„ํ•ด =====

# LU ๋ถ„ํ•ด
P, L, U = linalg.lu(A)
print(f"\nLU ๋ถ„ํ•ด:")
print(f"P =\n{P}")
print(f"L =\n{np.round(L, 4)}")
print(f"U =\n{np.round(U, 4)}")
print(f"PLU = A: {np.allclose(P @ L @ U, A)}")

# SVD (Singular Value Decomposition)
U_svd, s, Vt = np.linalg.svd(A)
print(f"\nํŠน์ด๊ฐ’: {s}")

# QR ๋ถ„ํ•ด
Q, R = np.linalg.qr(A)
print(f"\nQR ๋ถ„ํ•ด: Q ์ง๊ต์„ฑ {np.allclose(Q.T @ Q, np.eye(3))}")

# ์—ฐ๋ฆฝ๋ฐฉ์ •์‹ ํ’€๊ธฐ
b = np.array([1, 2, 3])
x = np.linalg.solve(A, b)
print(f"\nAx = b์˜ ํ•ด: {x}")
print(f"๊ฒ€์ฆ: Ax = {A @ x}")

7.2 SymPy๋ฅผ ์ด์šฉํ•œ ํ•ด์„์  ๊ณ„์‚ฐ

import sympy as sp

# ๊ธฐํ˜ธ ํ–‰๋ ฌ
a, b, c, d = sp.symbols('a b c d')
M = sp.Matrix([[a, b], [c, d]])

print("์ผ๋ฐ˜ 2x2 ํ–‰๋ ฌ:")
print(f"  det = {M.det()}")
print(f"  trace = {M.trace()}")
print(f"  ํŠน์„ฑ ๋‹คํ•ญ์‹: {M.charpoly().as_expr()}")

# ์ผ€์ผ๋ฆฌ-ํ•ด๋ฐ€ํ„ด ์ •๋ฆฌ: ๋ชจ๋“  ํ–‰๋ ฌ์€ ์ž์‹ ์˜ ํŠน์„ฑ ๋‹คํ•ญ์‹์„ ๋งŒ์กฑ
# Aยฒ - (a+d)A + (ad-bc)I = 0
lam = sp.Symbol('lambda')
char_poly = M.charpoly(lam)
print(f"\nํŠน์„ฑ ๋‹คํ•ญ์‹ p(ฮป) = {char_poly.as_expr()}")
print("์ผ€์ผ๋ฆฌ-ํ•ด๋ฐ€ํ„ด: p(M) = 0 ํ™•์ธ")
result = M**2 - (a+d)*M + (a*d - b*c)*sp.eye(2)
print(f"  p(M) = {sp.simplify(result)}")

์—ฐ์Šต๋ฌธ์ œ

๊ธฐ๋ณธ ๋ฌธ์ œ

1. ๋‹ค์Œ ํ–‰๋ ฌ์˜ ํ–‰๋ ฌ์‹๊ณผ ์—ญํ–‰๋ ฌ์„ ๊ตฌํ•˜์‹œ์˜ค: $$ A = \begin{pmatrix} 1 & 2 & 1 \\ 3 & 1 & -1 \\ 2 & 0 & 3 \end{pmatrix} $$

2. ๋‹ค์Œ ์—ฐ๋ฆฝ๋ฐฉ์ •์‹์„ ๊ฐ€์šฐ์Šค ์†Œ๊ฑฐ๋ฒ•์œผ๋กœ ํ‘ธ์‹œ์˜ค: $$ x + 2y + z = 4, \quad 3x + y - z = 2, \quad 2x + 3z = 7 $$

3. ๋‹ค์Œ ํ–‰๋ ฌ์˜ ๊ณ ์œ ๊ฐ’๊ณผ ๊ณ ์œ ๋ฒกํ„ฐ๋ฅผ ๊ตฌํ•˜์‹œ์˜ค: $$ B = \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix} $$

์‘์šฉ ๋ฌธ์ œ

4. ์ด์ฐจํ˜•์‹ $Q(x,y) = 3x^2 + 2xy + 3y^2$์˜ ์–‘์ •์น˜/์Œ์ •์น˜/๋ถ€์ •์น˜ ์—ฌ๋ถ€๋ฅผ ํŒ๋ณ„ํ•˜๊ณ , ์ฃผ์ถ• ๋ณ€ํ™˜ํ•˜์‹œ์˜ค.

5. ์งˆ๋Ÿ‰ $m_1 = 1$, $m_2 = 2$์ธ ๋‘ ๋ฌผ์ฒด๊ฐ€ ์Šคํ”„๋ง ์ƒ์ˆ˜ $k_1 = 3$, $k_2 = 4$, $k_3 = 2$์ธ ์„ธ ์Šคํ”„๋ง์œผ๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค (๋ฒฝโ€“kโ‚โ€“mโ‚โ€“kโ‚‚โ€“mโ‚‚โ€“kโ‚ƒโ€“๋ฒฝ). ๊ณ ์œ ์ง„๋™์ˆ˜์™€ ๊ณ ์œ ๋ชจ๋“œ๋ฅผ ๊ตฌํ•˜์‹œ์˜ค.

6. ์ž๊ธฐ์žฅ ๋ฐฉํ–ฅ $\hat{n} = (\sin\theta\cos\phi, \sin\theta\sin\phi, \cos\theta)$์— ๋Œ€ํ•œ ์Šคํ•€-1/2 ์ธก์ • ์—ฐ์‚ฐ์ž $\hat{S}_n = \frac{\hbar}{2}(\sigma_x \sin\theta\cos\phi + \sigma_y \sin\theta\sin\phi + \sigma_z \cos\theta)$์˜ ๊ณ ์œ ๊ฐ’๊ณผ ๊ณ ์œ ๋ฒกํ„ฐ๋ฅผ ๊ตฌํ•˜์‹œ์˜ค.


์ฐธ๊ณ  ์ž๋ฃŒ

  • Boas, Mathematical Methods in the Physical Sciences, Chapter 3
  • Strang, Introduction to Linear Algebra
  • Arfken & Weber, Mathematical Methods for Physicists, Chapters 3-4
  • ์ด ๋ ˆ์Šจ์˜ ์ฝ”๋“œ: examples/Math_for_AI/01_vector_matrix_ops.py, 02_svd_pca.py ์ฐธ์กฐ

๋‹ค์Œ ๋ ˆ์Šจ

04. ํŽธ๋ฏธ๋ถ„ (Partial Differentiation)์—์„œ ๋‹ค๋ณ€์ˆ˜ ํ•จ์ˆ˜์˜ ๋ฏธ์ ๋ถ„์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

to navigate between lessons