1. 덧셈과 뺄셈
행렬과 벡터의 덧셈과 뺄셈은 동일한 차원을 가진 경우에만 가능하다. 이를 수학적으로 표현하면, 두 행렬 \mathbf{A}, \mathbf{B}가 같은 차원 \mathbb{R}^{m \times n}에 속해 있을 때 덧셈은 아래와 같이 이루어진다:
위 수식에서 \mathbf{A}(i,j)와 \mathbf{B}(i,j)는 각각 \mathbf{A}와 \mathbf{B}의 (i,j) 성분을 의미하며, \mathbf{C}의 성분 \mathbf{C}(i,j)는 두 행렬 성분의 합으로 정의된다. 벡터의 덧셈도 유사하며, 두 벡터 \mathbf{u}, \mathbf{v} \in \mathbb{R}^n에 대해 성분별로 계산된다:
벡터와 행렬의 뺄셈 역시 덧셈과 동일한 방식으로 성분별로 계산된다:
Eigen 라이브러리에서 행렬과 벡터의 덧셈 및 뺄셈은 간단하게 +
및 -
연산자를 사용하여 구현할 수 있다. 예시 코드는 다음과 같다:
Eigen::Matrix3d A, B, C;
C = A + B;
2. 스칼라 곱셈
행렬 또는 벡터에 스칼라 값을 곱하는 연산은 각 성분에 동일한 스칼라 값을 곱하는 방식으로 이루어진다. 행렬 \mathbf{A} \in \mathbb{R}^{m \times n}과 스칼라 c \in \mathbb{R}에 대해 다음과 같이 정의된다:
벡터 \mathbf{u} \in \mathbb{R}^n에 스칼라 c를 곱하는 경우도 마찬가지로 성분별로 계산된다:
이 연산은 행렬과 벡터의 크기를 조정하거나 방향성을 유지한 채 크기를 변경할 때 자주 사용된다. Eigen 라이브러리에서 스칼라 곱셈은 다음과 같이 구현된다:
Eigen::Vector3d u, v;
double c = 2.0;
v = c * u;
3. 행렬 곱셈
두 행렬 \mathbf{A} \in \mathbb{R}^{m \times n}, \mathbf{B} \in \mathbb{R}^{n \times p}의 곱은 일반적으로 아래와 같이 정의된다:
행렬 곱셈은 행렬의 행과 열을 서로 곱하여 합을 구하는 방식으로 계산되며, \mathbf{A}의 열의 개수는 반드시 \mathbf{B}의 행의 개수와 일치해야 한다. 행렬 곱셈은 선형 변환을 표현하는 중요한 연산 중 하나이다.
벡터에 행렬을 곱하는 경우, 행렬 \mathbf{A} \in \mathbb{R}^{m \times n}과 벡터 \mathbf{v} \in \mathbb{R}^n이 주어졌을 때, 결과 벡터 \mathbf{w} \in \mathbb{R}^m는 아래와 같이 정의된다:
Eigen 라이브러리에서 행렬 곱셈은 *
연산자를 통해 쉽게 구현할 수 있다:
Eigen::Matrix3d A, B, C;
C = A * B;
Eigen::Vector3d u, w;
w = A * u;
4. 전치 행렬
행렬의 전치(transpose)는 행과 열을 서로 바꾼 행렬을 의미한다. 주어진 행렬 \mathbf{A} \in \mathbb{R}^{m \times n}에 대해 전치 행렬 \mathbf{A}^T \in \mathbb{R}^{n \times m}는 다음과 같이 정의된다:
즉, \mathbf{A}의 (i,j) 성분이 전치 행렬에서는 (j,i) 성분으로 이동하는 것이다. 전치 행렬은 주로 내적이나 역행렬 계산 등에 활용되며, Eigen 라이브러리에서는 .transpose()
함수를 사용하여 전치를 구할 수 있다:
Eigen::Matrix3d A, B;
B = A.transpose();
5. 내적 (Dot Product)
두 벡터의 내적은 벡터 공간에서 중요한 연산 중 하나로, 두 벡터 사이의 각도를 계산하거나 벡터의 투영을 구하는 데 활용된다. 두 벡터 \mathbf{u}, \mathbf{v} \in \mathbb{R}^n의 내적은 아래와 같이 정의된다:
내적의 결과는 스칼라 값이며, 이는 벡터 간의 평행성이나 직교성을 평가하는 데 유용하다. Eigen 라이브러리에서는 .dot()
함수를 사용하여 내적을 계산할 수 있다:
Eigen::Vector3d u, v;
double dot_product = u.dot(v);
6. 외적 (Cross Product)
외적은 3차원 공간에서 두 벡터 사이의 직교하는 벡터를 구하는 연산이다. 주어진 두 벡터 \mathbf{u}, \mathbf{v} \in \mathbb{R}^3의 외적은 다음과 같이 정의된다:
외적의 결과는 두 벡터와 직교하는 벡터 \mathbf{w}이며, 그 성분은 아래와 같다:
이 식에서 \mathbf{i}, \mathbf{j}, \mathbf{k}는 각각 x, y, z 방향의 단위 벡터이다.
외적은 벡터의 평면에서 수직인 벡터를 구하거나, 두 벡터가 이루는 평행사변형의 넓이를 구할 때 사용된다. Eigen 라이브러리에서 외적은 .cross()
함수를 사용하여 구할 수 있다:
Eigen::Vector3d u, v, w;
w = u.cross(v);
7. 역행렬
역행렬은 주어진 정방행렬 \mathbf{A} \in \mathbb{R}^{n \times n}에 대해, \mathbf{A}와 곱했을 때 단위 행렬이 되는 행렬 \mathbf{A}^{-1}을 의미한다. 즉, 아래의 관계를 만족하는 \mathbf{A}^{-1}을 찾는 것이다:
여기서 \mathbf{I}는 단위 행렬(identity matrix)이다. 역행렬은 행렬이 정칙(invertible)일 때만 존재하며, 정칙 행렬은 행렬식(determinant)이 0이 아닌 행렬을 의미한다.
역행렬은 선형 방정식의 해를 구하거나, 시스템의 역을 구할 때 사용된다. Eigen 라이브러리에서는 .inverse()
함수를 사용하여 역행렬을 구할 수 있다:
Eigen::Matrix3d A, A_inv;
A_inv = A.inverse();
역행렬이 존재하는지 여부는 행렬식의 값에 따라 결정된다. 행렬식이 0일 경우 역행렬은 존재하지 않는다.
8. 행렬식
행렬 \mathbf{A} \in \mathbb{R}^{n \times n}의 행렬식(determinant)은 그 행렬의 고유한 스칼라 값을 의미하며, \mathbf{A}가 역행렬을 가질 수 있는지 여부를 결정하는 중요한 지표이다. \mathbf{A}의 행렬식은 \det(\mathbf{A})로 나타내며, 예를 들어 2 \times 2 행렬의 경우 다음과 같이 계산된다:
더 높은 차원의 행렬식은 보다 복잡한 방식으로 계산되며, 다중 행과 열에 걸친 소행렬식(cofactor)을 활용한다. 행렬식이 0인 경우, 행렬은 역행렬을 갖지 않으며 "특이(singular)"하다고 한다.
Eigen 라이브러리에서는 .determinant()
함수를 사용하여 행렬식을 계산할 수 있다:
Eigen::Matrix3d A;
double det_A = A.determinant();
9. 대각합 (Trace)
대각합(trace)은 정방행렬의 대각 성분의 합을 의미하며, 이는 행렬의 고유값의 합과 같다는 특징을 가진다. 주어진 행렬 \mathbf{A} \in \mathbb{R}^{n \times n}에 대해 대각합은 아래와 같이 정의된다:
대각합은 주로 행렬의 특성을 요약하는 데 사용되며, 고유값 문제에서 중요한 역할을 한다. Eigen 라이브러리에서는 .trace()
함수를 사용하여 대각합을 구할 수 있다:
Eigen::Matrix3d A;
double trace_A = A.trace();
10. 단위 행렬
단위 행렬(identity matrix)은 주어진 차원의 정방 행렬에서 모든 대각 성분이 1이고, 그 외의 성분이 모두 0인 행렬이다. 단위 행렬 \mathbf{I} \in \mathbb{R}^{n \times n}은 아래와 같이 정의된다:
단위 행렬은 행렬 곱셈에서 항등원 역할을 한다. 즉, 임의의 행렬 \mathbf{A} \in \mathbb{R}^{n \times n}에 대해 다음이 성립한다:
단위 행렬은 주로 행렬 계산에서 기준점이 되는 행렬로 사용되며, 역행렬 계산, 선형 시스템 분석 등 다양한 곳에서 활용된다.
Eigen 라이브러리에서는 Eigen::MatrixXd::Identity()
함수를 통해 단위 행렬을 생성할 수 있다:
Eigen::Matrix3d I = Eigen::Matrix3d::Identity();
11. 대칭 행렬
대칭 행렬(symmetric matrix)은 주어진 행렬의 전치 행렬이 원래 행렬과 동일한 행렬을 의미한다. 즉, 행렬 \mathbf{A} \in \mathbb{R}^{n \times n}에 대해 다음 조건을 만족하면 대칭 행렬이라고 한다:
이 의미는 \mathbf{A}의 (i,j) 성분과 (j,i) 성분이 동일하다는 것을 나타낸다. 즉, 아래가 성립한다:
대칭 행렬은 선형 대수학에서 중요한 특성을 가지고 있으며, 특히 고유값이 실수(real number)라는 성질을 가진다. 물리학, 통계학, 제어 시스템에서 자주 등장하며, 예를 들어 공분산 행렬이 대칭 행렬의 대표적인 예이다.
Eigen 라이브러리에서 대칭 행렬을 생성하려면 행렬의 특정 성분을 직접 설정할 수 있다:
Eigen::Matrix3d A;
A(0, 1) = A(1, 0) = value; // 대칭 관계 설정
12. 대각 행렬
대각 행렬(diagonal matrix)은 모든 비대각 성분이 0인 정방 행렬을 말한다. 행렬 \mathbf{A} \in \mathbb{R}^{n \times n}이 대각 행렬이라면 다음과 같은 구조를 갖는다:
즉, \mathbf{A}의 비대각 성분은 모두 0이고, 대각 성분은 0이 아닐 수 있다. 대각 행렬은 행렬 곱셈에서 계산이 간단하며, 고유값 문제나 선형 시스템 해석에서 중요한 역할을 한다.
대각 행렬은 Eigen 라이브러리에서 Eigen::DiagonalMatrix
클래스를 사용하여 생성할 수 있다:
Eigen::Vector3d diag_values;
Eigen::DiagonalMatrix<double, 3> D(diag_values);
또한 일반 행렬에서 대각 성분만 추출하려면 .diagonal()
함수를 사용할 수 있다:
Eigen::Matrix3d A;
Eigen::Vector3d diag = A.diagonal();
13. 고유값과 고유벡터
행렬 \mathbf{A} \in \mathbb{R}^{n \times n}의 고유값(eigenvalue)과 고유벡터(eigenvector)는 다음 조건을 만족하는 \lambda \in \mathbb{R} (고유값)과 \mathbf{v} \in \mathbb{R}^n (고유벡터)를 의미한다:
이때 \mathbf{A}는 고유벡터 \mathbf{v}의 방향을 변화시키지 않고 크기만 \lambda로 조정하는 역할을 한다. 고유값과 고유벡터는 선형 변환의 특성을 분석하는 데 중요한 개념으로, 특히 시스템의 안정성 분석, 진동 모드, 데이터 축소(예: PCA) 등에 활용된다.
Eigen 라이브러리에서는 고유값과 고유벡터를 구하기 위해 Eigen::EigenSolver
클래스를 사용할 수 있다. 예시는 다음과 같다:
Eigen::Matrix3d A;
Eigen::EigenSolver<Eigen::Matrix3d> solver(A);
Eigen::Vector3cd eigenvalues = solver.eigenvalues();
Eigen::Matrix3cd eigenvectors = solver.eigenvectors();
14. 직교 행렬
직교 행렬(orthogonal matrix)은 그 행렬의 전치 행렬이 역행렬과 동일한 행렬을 의미한다. 즉, 행렬 \mathbf{Q} \in \mathbb{R}^{n \times n}이 직교 행렬이라면 다음 조건을 만족한다:
여기서 \mathbf{I}는 단위 행렬(identity matrix)이다. 직교 행렬의 중요한 특성 중 하나는 그 열 벡터가 서로 직교하고, 모든 벡터의 크기가 1로 정규화(normalized)되어 있다는 점이다. 즉, 직교 행렬의 열 또는 행 벡터는 모두 단위 벡터(orthonormal)이다.
직교 행렬은 회전 변환과 반사 변환에서 중요한 역할을 하며, 수치 해석에서 정규 직교 기저를 사용하여 계산을 간단하게 할 수 있다.
Eigen 라이브러리에서는 직교 행렬을 생성하거나 검증하기 위해 다양한 방법을 사용할 수 있으며, QR 분해 등의 알고리즘을 활용해 직교 행렬을 얻을 수 있다:
Eigen::Matrix3d A;
Eigen::HouseholderQR<Eigen::Matrix3d> qr(A);
Eigen::Matrix3d Q = qr.householderQ();
15. QR 분해
QR 분해는 임의의 행렬을 직교 행렬과 상삼각 행렬로 분해하는 방법이다. 주어진 행렬 \mathbf{A} \in \mathbb{R}^{m \times n}을 다음과 같이 두 행렬의 곱으로 표현한다:
여기서 \mathbf{Q} \in \mathbb{R}^{m \times m}는 직교 행렬이고, \mathbf{R} \in \mathbb{R}^{m \times n}은 상삼각 행렬이다. QR 분해는 주로 선형 시스템 해석, 최소자승 문제, 그리고 고유값 계산 등에 사용된다.
Eigen 라이브러리에서는 QR 분해를 다음과 같이 수행할 수 있다:
Eigen::MatrixXd A;
Eigen::HouseholderQR<Eigen::MatrixXd> qr(A);
Eigen::MatrixXd Q = qr.householderQ();
Eigen::MatrixXd R = qr.matrixQR().triangularView<Eigen::Upper>();
16. LU 분해
LU 분해는 행렬을 하삼각 행렬과 상삼각 행렬로 분해하는 방법이다. 주어진 정방행렬 \mathbf{A} \in \mathbb{R}^{n \times n}을 아래와 같이 두 행렬의 곱으로 나타낸다:
여기서 \mathbf{L}은 하삼각 행렬(lower triangular matrix), \mathbf{U}는 상삼각 행렬(upper triangular matrix)이다. LU 분해는 선형 시스템 해석, 역행렬 계산, 행렬식 계산 등에 사용된다.
Eigen 라이브러리에서는 LU 분해를 아래와 같이 구현할 수 있다:
Eigen::MatrixXd A;
Eigen::FullPivLU<Eigen::MatrixXd> lu(A);
Eigen::MatrixXd L = lu.matrixLU().triangularView<Eigen::Lower>();
Eigen::MatrixXd U = lu.matrixLU().triangularView<Eigen::Upper>();
17. SVD (특이값 분해)
특이값 분해(SVD, Singular Value Decomposition)는 임의의 행렬을 세 개의 행렬 곱으로 분해하는 방법이다. 주어진 행렬 \mathbf{A} \in \mathbb{R}^{m \times n}에 대해 다음과 같은 분해를 한다:
여기서 \mathbf{U} \in \mathbb{R}^{m \times m}와 \mathbf{V} \in \mathbb{R}^{n \times n}는 직교 행렬이며, \mathbf{\Sigma} \in \mathbb{R}^{m \times n}는 대각 행렬로 특이값을 포함한다. SVD는 선형 변환의 특성을 분석하고, 데이터 압축이나 차원 축소(PCA) 등의 응용에서 중요한 역할을 한다.
Eigen 라이브러리에서 SVD는 JacobiSVD
클래스를 사용하여 계산할 수 있다:
Eigen::MatrixXd A;
Eigen::JacobiSVD<Eigen::MatrixXd> svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
Eigen::MatrixXd U = svd.matrixU();
Eigen::MatrixXd V = svd.matrixV();
Eigen::VectorXd S = svd.singularValues();
SVD는 임의의 행렬에 대해 매우 안정적인 분해 방법으로, 특히 고유값이 존재하지 않는 경우에도 유용하게 사용된다.
18. 행렬의 노름 (Matrix Norm)
행렬의 노름(matrix norm)은 행렬의 크기를 측정하는 수치이다. 노름은 여러 가지 방식으로 정의될 수 있으며, 각 정의는 행렬의 특정 성질을 강조한다. 일반적으로 사용되는 몇 가지 행렬 노름은 다음과 같다.
1. Frobenius 노름
Frobenius 노름은 행렬의 모든 성분의 제곱합에 루트를 취한 값으로 정의된다. 행렬 \mathbf{A} \in \mathbb{R}^{m \times n}에 대해 Frobenius 노름은 아래와 같이 계산된다:
Frobenius 노름은 유클리드 거리와 비슷한 방식으로 행렬의 크기를 측정하며, 행렬의 전 성분에 대해 고르게 기여하는 특징이 있다.
Eigen 라이브러리에서는 Frobenius 노름을 norm()
함수로 구할 수 있다:
Eigen::MatrixXd A;
double frobenius_norm = A.norm();
2. 1-노름
1-노름은 행렬의 각 열에서 절대값의 합 중 가장 큰 값을 나타낸다. 수학적으로는 다음과 같이 정의된다:
1-노름은 행렬의 각 열의 크기 중 가장 큰 값을 강조하는 방식으로 크기를 측정한다.
3. 무한 노름 (Infinity Norm)
무한 노름은 행렬의 각 행에서 절대값의 합 중 가장 큰 값을 나타낸다. 이는 다음과 같이 계산된다:
무한 노름은 행렬의 각 행에 집중하여, 가장 큰 합을 가지는 행의 크기를 측정하는 방식이다.
Eigen 라이브러리에서는 1-노름과 무한 노름을 직접 계산하려면 행렬의 성분을 순차적으로 합산하고, 그 최대값을 찾는 방식으로 구현할 수 있다.
19. 아다마르 곱 (Hadamard Product)
아다마르 곱(Hadamard Product)은 두 행렬의 성분별 곱으로 정의된다. 주어진 행렬 \mathbf{A}, \mathbf{B} \in \mathbb{R}^{m \times n}에 대해 슈어 보곱은 다음과 같이 계산된다:
아다마르 곱은 성분별로 행렬을 곱하는 연산으로, 행렬의 크기가 동일할 때에만 정의된다. 이 연산은 주로 통계 및 신호 처리 분야에서 자주 사용된다.
Eigen 라이브러리에서는 아다마르 곱을 cwiseProduct()
함수를 사용하여 계산할 수 있다:
Eigen::MatrixXd A, B, C;
C = A.cwiseProduct(B);
20. 블록 행렬 (Block Matrix)
블록 행렬(block matrix)은 행렬을 더 작은 행렬로 나누어 다루는 방법이다. 이를 통해 행렬의 특정 부분을 효율적으로 처리하거나, 복잡한 행렬 연산을 간단하게 구현할 수 있다. 예를 들어, 행렬 \mathbf{A} \in \mathbb{R}^{m \times n}을 두 개의 작은 행렬로 나눈다면 다음과 같이 표현할 수 있다:
각각의 블록 \mathbf{A}_{ij}는 더 작은 행렬로, 블록 행렬을 활용하여 행렬의 연산을 효율적으로 처리할 수 있다.
Eigen 라이브러리에서는 block()
함수를 통해 행렬의 특정 블록을 추출하거나 설정할 수 있다:
Eigen::MatrixXd A(4, 4);
Eigen::MatrixXd B = A.block(0, 0, 2, 2); // A의 (0,0) 위치에서 2x2 블록 추출
21. 행렬 분해 (Matrix Decomposition)
행렬 분해(matrix decomposition)은 주어진 행렬을 더 작은 행렬로 분해하여 처리하는 방법이다. 앞서 소개한 LU 분해, QR 분해, SVD 분해 등 다양한 분해 방법을 포함하여, 행렬의 특성에 맞게 최적의 분해 방법을 선택할 수 있다. 분해 방법은 선형 시스템 해석, 고유값 문제, 최적화 등에 널리 사용된다.
대표적인 행렬 분해 방법
-
LU 분해: 행렬을 하삼각 행렬 \mathbf{L}과 상삼각 행렬 \mathbf{U}로 분해하는 방법. 이 방법은 주로 선형 방정식 해법에서 사용된다.
-
QR 분해: 행렬을 직교 행렬 \mathbf{Q}와 상삼각 행렬 \mathbf{R}로 분해하는 방법. QR 분해는 고유값 문제를 다루거나 최소자승법(Least Squares)에 유용하다.
-
SVD (Singular Value Decomposition): 임의의 행렬을 직교 행렬 \mathbf{U}, \mathbf{V}와 대각 행렬 \mathbf{\Sigma}로 분해하는 방법. SVD는 행렬의 차원 축소 및 데이터 압축에 사용된다.
-
Cholesky 분해: 대칭이고 양의 정부호인 행렬을 하삼각 행렬 \mathbf{L}과 그 전치 \mathbf{L}^T로 분해하는 방법. Cholesky 분해는 수치적으로 매우 안정적이며, 주로 선형 방정식 해법에서 사용된다.
Eigen 라이브러리에서는 다양한 행렬 분해 알고리즘을 쉽게 구현할 수 있다. 예를 들어, Cholesky 분해는 다음과 같이 구현할 수 있다:
Eigen::MatrixXd A;
Eigen::LLT<Eigen::MatrixXd> llt(A);
Eigen::MatrixXd L = llt.matrixL(); // 하삼각 행렬 L
각 행렬 분해 방법은 주어진 문제의 특성에 맞춰 선택되며, 연산의 효율성과 안정성을 크게 개선할 수 있다.