전치 행렬

전치 행렬(transpose of a matrix)은 원래 행렬의 행과 열을 뒤바꾼 행렬을 말한다. 이는 수학적으로 다음과 같이 정의된다. 행렬 \mathbf{A}m \times n 행렬일 때, 그 전치 행렬 \mathbf{A}^Tn \times m 행렬로, 아래 조건을 만족한다:

\mathbf{A}^T_{ij} = \mathbf{A}_{ji} \quad \forall i, j

즉, 행렬의 i-번째 행과 j-번째 열의 원소가 전치 행렬에서는 j-번째 행과 i-번째 열의 원소로 변환된다.

전치 연산의 몇 가지 중요한 성질은 다음과 같다:

  1. 이중 전치의 항등성:
(\mathbf{A}^T)^T = \mathbf{A}

이는 행렬을 두 번 전치하면 원래의 행렬로 돌아온다는 것을 의미한다.

  1. 덧셈에 대한 전치 연산의 분배성:
(\mathbf{A} + \mathbf{B})^T = \mathbf{A}^T + \mathbf{B}^T

두 행렬 \mathbf{A}\mathbf{B}의 합을 전치하는 것은 각각의 행렬을 전치한 후 더하는 것과 같다.

  1. 스칼라 곱에 대한 전치 연산의 분배성:
(c \mathbf{A})^T = c \mathbf{A}^T

스칼라 c에 대해, 행렬의 스칼라 곱을 전치하는 것은 그 스칼라를 유지한 채 행렬을 전치하는 것과 동일하다.

  1. 행렬 곱에 대한 전치 연산:
(\mathbf{A} \mathbf{B})^T = \mathbf{B}^T \mathbf{A}^T

두 행렬의 곱을 전치하는 것은 행렬의 순서를 바꿔 각각을 전치한 후 곱하는 것과 동일하다.

Eigen 라이브러리에서 전치 연산은 간단하게 .transpose() 메서드를 사용하여 수행할 수 있다. 예를 들어, 다음과 같은 코드가 있다고 하자:

#include <Eigen/Dense>
using namespace Eigen;

Matrix3d A;
A << 1, 2, 3,
     4, 5, 6,
     7, 8, 9;

Matrix3d A_transpose = A.transpose();

위 코드에서 A.transpose()는 행렬 \mathbf{A}의 전치 행렬을 반환한다.

수반 행렬

수반 행렬(adjoint matrix)은 복소수 행렬의 경우에 정의되며, 전치 행렬의 복소수 켤레(complex conjugate)를 취한 행렬이다. 행렬 \mathbf{A}가 복소수 행렬일 때, 그 수반 행렬 \mathbf{A}^*는 다음과 같이 정의된다:

\mathbf{A}^* = \overline{\mathbf{A}}^T

여기서 \overline{\mathbf{A}}는 행렬 \mathbf{A}의 각 원소에 대해 복소수 켤레를 취한 행렬이다. 즉, \mathbf{A}의 원소가 a_{ij}라면, 수반 행렬 \mathbf{A}^*의 원소는 \overline{a_{ji}}가 된다.

수반 행렬의 주요 성질 중 몇 가지는 다음과 같다:

  1. 수반 행렬의 이중 수반성:
(\mathbf{A}^*)^* = \mathbf{A}

이는 실수 행렬에서 이중 전치와 같은 역할을 하며, 복소수 행렬에서 수반 연산을 두 번 하면 원래의 행렬로 돌아온다는 것을 의미한다.

  1. 덧셈에 대한 수반 연산의 분배성:
(\mathbf{A} + \mathbf{B})^* = \mathbf{A}^* + \mathbf{B}^*

이는 전치 연산과 마찬가지로, 두 행렬의 합을 수반하는 것은 각각을 수반한 후 더하는 것과 동일하다.

  1. 행렬 곱에 대한 수반 연산:
(\mathbf{A} \mathbf{B})^* = \mathbf{B}^* \mathbf{A}^*

두 행렬의 곱을 수반하는 것은 전치 연산과 마찬가지로 순서를 바꾼 후 각각을 수반한 결과와 같다.

Eigen 라이브러리에서 수반 행렬은 .adjoint() 메서드를 사용하여 구할 수 있다. 다음 예시를 보자:

#include <Eigen/Dense>
using namespace Eigen;

MatrixXcd A(2,2);
A(0,0) = std::complex<double>(1, 2); // 1 + 2i
A(1,0) = std::complex<double>(3, 4); // 3 + 4i
A(0,1) = std::complex<double>(5, 6); // 5 + 6i
A(1,1) = std::complex<double>(7, 8); // 7 + 8i

MatrixXcd A_adjoint = A.adjoint();

위 코드는 복소수 행렬 \mathbf{A}의 수반 행렬을 계산하는 예시이다.

수반 행렬의 실수 행렬에 대한 적용

수반 행렬은 주로 복소수 행렬에 대해 정의되지만, 실수 행렬에도 적용할 수 있다. 실수 행렬의 경우, 각 원소의 복소수 켤레는 원래 값과 동일하므로, 실수 행렬에서 수반 행렬은 전치 행렬과 동일하다. 즉, 실수 행렬 \mathbf{A}에 대해:

\mathbf{A}^* = \mathbf{A}^T

따라서, 실수 행렬에서는 굳이 수반 행렬을 구하는 연산을 따로 고려할 필요는 없다. 복소수 행렬에서 수반 행렬이 더 의미 있는 역할을 하며, 주로 양자역학이나 신호 처리 분야에서 사용된다.

수반 연산과 에르미트 행렬

수반 행렬과 밀접하게 관련된 개념은 에르미트 행렬(Hermitian matrix)이다. 에르미트 행렬은 그 수반 행렬이 원래의 행렬과 동일한 행렬을 말한다. 즉, 행렬 \mathbf{A}가 에르미트 행렬일 조건은:

\mathbf{A}^* = \mathbf{A}

이 조건은 실수 행렬에서는 대칭 행렬의 정의와 동일하다. 다시 말해, 실수 행렬의 경우 에르미트 행렬은 곧 대칭 행렬이다. 복소수 행렬의 경우, 에르미트 행렬은 모든 대각 성분이 실수이고, 비대각 성분이 서로 복소수 켤레인 구조를 가진다.

Eigen 라이브러리에서는 에르미트 행렬인지 여부를 직접 확인하는 메서드를 제공하지 않으므로, 개발자가 직접 확인해야 한다. 예를 들어, 수반 행렬을 계산한 후 원래 행렬과 비교하여 에르미트 성질을 확인할 수 있다:

#include <Eigen/Dense>
using namespace Eigen;

MatrixXcd A(2,2);
A(0,0) = std::complex<double>(1, 0); // 실수
A(1,0) = std::complex<double>(3, 4); // 복소수
A(0,1) = std::complex<double>(3, -4); // 켤레 복소수
A(1,1) = std::complex<double>(5, 0); // 실수

bool isHermitian = A.isApprox(A.adjoint());

위 코드에서 isHermitian 변수는 행렬 \mathbf{A}가 에르미트 행렬인지 여부를 반환한다.

전치 및 수반 연산의 활용 예시

전치 행렬과 수반 행렬은 다양한 응용에서 사용된다. 특히, 선형대수학에서 전치 연산은 직교성, 내적, 외적 등의 개념과 깊이 연결된다. 수반 행렬은 복소수 공간에서 에너지 보존, 양자 상태의 전환 등 물리학에서 자주 사용된다.

직교 행렬

직교 행렬은 전치 행렬이 역행렬과 같은 행렬을 말한다. 즉, 행렬 \mathbf{Q}가 직교 행렬일 조건은 다음과 같다:

\mathbf{Q}^T \mathbf{Q} = \mathbf{I}

여기서 \mathbf{I}는 항등 행렬이다. 직교 행렬은 벡터 공간에서 벡터를 회전하거나 반사할 때 사용된다. 직교 행렬의 가장 중요한 성질 중 하나는 그 행렬의 열벡터가 서로 직교하고, 각각의 벡터의 크기가 1이라는 점이다.

유니터리 행렬

유니터리 행렬은 복소수 공간에서 직교 행렬에 해당하는 개념이다. 즉, 복소수 행렬 \mathbf{U}가 유니터리 행렬일 조건은 다음과 같다:

\mathbf{U}^* \mathbf{U} = \mathbf{I}

유니터리 행렬은 양자 역학에서 중요한 역할을 하며, 양자 상태의 변환에서 에너지 보존을 보장하는 연산자로 사용된다. 이 조건은 복소수 벡터의 길이를 보존하고, 복소수 벡터 사이의 내적도 보존함을 의미한다.

Eigen 라이브러리에서 유니터리 행렬을 쉽게 다룰 수 있으며, 예를 들어 QR 분해(QR decomposition)를 수행할 때 유니터리 행렬을 생성할 수 있다.

#include <Eigen/Dense>
using namespace Eigen;

MatrixXcd A = MatrixXcd::Random(4,4); // 4x4 복소수 행렬
HouseholderQR<MatrixXcd> qr(A);
MatrixXcd Q = qr.householderQ();

bool isUnitary = Q.adjoint() * Q == MatrixXcd::Identity(4,4);

위 코드에서 Q는 행렬 \mathbf{A}의 QR 분해에서 얻은 유니터리 행렬을 나타낸다.

전치 연산과 대각화

행렬의 전치 연산은 대각화(diagonalization) 과정에서도 중요한 역할을 한다. 대각화는 행렬을 대각 성분만을 가지는 행렬로 변환하는 작업으로, 이를 통해 복잡한 행렬 연산을 단순하게 처리할 수 있다. 행렬 \mathbf{A}가 대각화 가능할 조건은 다음과 같다:

\mathbf{A} = \mathbf{P} \mathbf{D} \mathbf{P}^{-1}

여기서 \mathbf{P}는 행렬의 고유벡터(eigenvector)로 이루어진 행렬, \mathbf{D}는 행렬의 고유값(eigenvalue)이 대각 성분으로 나열된 대각 행렬이다. 전치 행렬의 경우, 대각화 가능하면 다음과 같은 성질을 가진다:

\mathbf{A}^T = \mathbf{P}^T \mathbf{D} \mathbf{P}^{-T}

즉, 전치 행렬 역시 대각화가 가능하고, 그 대각화 결과는 원래 행렬의 대각화와 유사한 구조를 가진다. 대각화의 중요한 용도 중 하나는 행렬의 멱(power)을 쉽게 계산할 수 있다는 것이다. 예를 들어, 행렬의 n-제곱을 계산하는 문제는 다음과 같이 단순화된다:

\mathbf{A}^n = \mathbf{P} \mathbf{D}^n \mathbf{P}^{-1}

여기서 \mathbf{D}^n은 대각 행렬이므로, 각 대각 성분을 n-제곱하는 것만으로 간단하게 계산된다.

직교 대각화

직교 행렬은 특별한 경우의 대각화 가능 행렬로, 직교 행렬의 경우 \mathbf{P}가 역행렬이 아닌 전치 행렬과 동일하다. 즉, 직교 대각화는 다음과 같은 형태로 표현된다:

\mathbf{A} = \mathbf{Q} \mathbf{D} \mathbf{Q}^T

직교 대각화는 주로 대칭 행렬의 대각화를 수행할 때 사용된다. 모든 실수 대칭 행렬은 직교 대각화가 가능하며, 이는 실수 대칭 행렬의 고유벡터가 서로 직교한다는 성질을 반영한다.

수반 행렬과 양자역학

수반 행렬은 양자역학에서 중요한 역할을 하며, 양자 상태의 변환과 관련된 연산에서 자주 사용된다. 양자역학에서 상태는 복소수 벡터로 표현되며, 유니터리 연산자를 사용하여 상태 변환을 수행한다. 유니터리 행렬의 수반 행렬은 그 행렬의 역행렬과 동일하기 때문에, 수반 연산은 양자 상태의 보존과 관련된 성질을 유지하게 한다.

예를 들어, 양자 상태 |\psi\rangle에 대해, 그 에너지를 측정하는 연산자는 에르미트 연산자로 나타낸다. 에르미트 연산자 \mathbf{H}에 대해 다음 조건이 성립한다:

\mathbf{H} = \mathbf{H}^*

이는 양자역학에서 물리적 관측값이 항상 실수라는 것을 보장하는 중요한 성질이다. 수반 행렬과 에르미트 행렬의 이러한 관계는 양자역학뿐만 아니라 신호 처리, 정보 이론에서도 중요한 의미를 가진다.

수반 행렬과 미분방정식

수반 행렬은 또한 미분방정식에서도 자주 등장한다. 선형 미분방정식의 풀이에서 그린 함수(Green's function)를 구할 때 수반 연산이 사용되며, 이는 경계 조건을 만족시키는 해를 찾는 데 중요한 역할을 한다.

선형 연산자 \mathcal{L}이 주어졌을 때, 그 수반 연산자는 \mathcal{L}^*로 표현되며, 미분방정식의 해 공간에서의 대칭성을 반영한다. 수반 연산자는 본질적으로 전치 연산과 켤레 복소수를 결합하여 미분 연산자에 적용한 형태로 이해할 수 있다.

수반 연산자와 에너지 보존

물리학에서 수반 연산자는 에너지 보존 법칙과도 관련이 있다. 특히, 수반 연산자가 에르미트 연산자일 때, 이는 시스템이 에너지를 보존한다는 것을 의미한다. 예를 들어, 해밀토니안 \mathbf{H}가 에르미트 행렬일 경우, 양자 시스템에서 에너지가 보존된다는 중요한 물리적 의미를 가진다.

수반 행렬과 신호 처리

수반 행렬은 신호 처리에서 중요한 역할을 하며, 주로 푸리에 변환(Fourier Transform)과 같은 변환 과정에서 사용된다. 복소수 행렬로 나타낼 수 있는 신호 처리 시스템에서는 수반 연산을 통해 신호의 주파수 성분을 분석하고, 역변환을 수행하는 데 활용된다.

푸리에 변환과 수반 행렬

신호 처리에서 자주 사용되는 푸리에 변환은, 복소수 행렬로 표현되는 신호의 주파수 성분을 추출하는 과정이다. 푸리에 변환을 행렬 형식으로 나타내면, 변환 행렬 \mathbf{F}와 신호 벡터 \mathbf{x}에 대해 다음과 같이 표현된다:

\mathbf{X} = \mathbf{F} \mathbf{x}

여기서 \mathbf{X}는 주파수 영역에서의 신호 벡터를 의미한다. 푸리에 변환의 역변환(inverse Fourier transform)은 수반 행렬을 사용하여 구할 수 있으며, 다음과 같이 표현된다:

\mathbf{x} = \mathbf{F}^* \mathbf{X}

이 과정에서 수반 행렬 \mathbf{F}^*는 전치 연산과 복소수 켤레를 결합한 형태로, 원래 신호로 되돌리는 역할을 한다. 이는 신호 처리 시스템에서 신호의 변환과 복원을 모두 처리하는 데 중요한 수학적 도구로 활용된다.

유니터리 행렬과 신호의 보존

유니터리 행렬은 신호의 변환 과정에서 중요한 역할을 하며, 신호의 에너지를 보존하는 연산으로 자주 사용된다. 유니터리 행렬 \mathbf{U}에 대해 다음 조건이 성립한다:

\mathbf{U}^* \mathbf{U} = \mathbf{I}

이 조건은 신호 처리에서 에너지를 보존하는 시스템을 설계할 때 유용하다. 예를 들어, 푸리에 변환과 같은 주파수 변환에서, 신호의 총 에너지가 변하지 않음을 보장하기 위해 유니터리 연산자를 사용한다. 이를 통해 변환된 신호는 원래 신호와 동일한 에너지를 가지게 된다.

Eigen 라이브러리에서는 유니터리 행렬을 생성하거나 다루는 것이 간단하다. 신호 처리 시스템에서 유니터리 행렬을 사용하는 예시는 다음과 같다:

#include <Eigen/Dense>
using namespace Eigen;

MatrixXcd signal = MatrixXcd::Random(4, 4);
MatrixXcd U = signal.householderQr().householderQ();

bool isUnitary = U.adjoint() * U == MatrixXcd::Identity(4, 4);

이 코드는 임의의 복소수 신호를 유니터리 변환하는 시스템을 생성하고, 유니터리 성질을 확인하는 방법을 보여준다. 이러한 유니터리 연산은 신호의 총 에너지를 보존하는지 확인하는 데 사용될 수 있다.

전치 행렬과 선형 회귀

선형 회귀(Linear Regression) 문제에서 전치 행렬은 매우 중요한 역할을 한다. 주어진 데이터 집합 \mathbf{X}와 목표 값 \mathbf{y}에 대해, 선형 회귀 문제는 회귀 계수 벡터 \mathbf{w}를 찾는 문제로, 다음과 같은 최소제곱 문제를 해결하는 과정이다:

\min_{\mathbf{w}} || \mathbf{X} \mathbf{w} - \mathbf{y} ||^2

이 문제를 풀기 위해 행렬의 전치 연산을 이용한 정규 방정식을 사용할 수 있다. 정규 방정식은 다음과 같다:

\mathbf{w} = (\mathbf{X}^T \mathbf{X})^{-1} \mathbf{X}^T \mathbf{y}

여기서 \mathbf{X}^T는 데이터 행렬 \mathbf{X}의 전치 행렬이다. 전치 연산을 통해 행렬을 변환하여 문제를 쉽게 해결할 수 있다.

Eigen 라이브러리에서는 선형 회귀를 간단하게 구현할 수 있으며, 다음과 같은 코드로 전치 연산을 포함한 회귀 분석을 수행할 수 있다:

#include <Eigen/Dense>
using namespace Eigen;

MatrixXd X(4, 3); // 4개의 샘플, 3개의 특징
VectorXd y(4);    // 목표값

// X와 y에 데이터 할당
X << 1, 2, 3,
     4, 5, 6,
     7, 8, 9,
     10, 11, 12;

y << 1, 2, 3, 4;

// 정규 방정식 계산
VectorXd w = (X.transpose() * X).inverse() * X.transpose() * y;

위 코드는 주어진 데이터에 대해 선형 회귀 분석을 수행하고, 회귀 계수 \mathbf{w}를 계산한다. 전치 연산 X.transpose()는 데이터 행렬의 변환을 포함하여 문제를 해결하는 데 필수적인 역할을 한다.

전치 행렬과 역행렬

전치 행렬은 역행렬 계산에서도 중요한 역할을 한다. 정방행렬(square matrix) \mathbf{A}에 대해, 그 역행렬 \mathbf{A}^{-1}는 다음과 같은 성질을 가진다:

(\mathbf{A}^T)^{-1} = (\mathbf{A}^{-1})^T

즉, 행렬의 전치 행렬의 역행렬은 원래 행렬의 역행렬을 전치한 것과 동일하다. 이 성질은 다양한 선형 시스템을 풀 때 유용하게 사용된다. 예를 들어, 역행렬을 구한 후 전치 연산을 추가로 수행하는 경우에 이 성질을 활용하면 연산 효율을 높일 수 있다.

Eigen 라이브러리에서는 전치 행렬의 역행렬을 쉽게 구할 수 있으며, 다음과 같은 코드를 사용할 수 있다:

#include <Eigen/Dense>
using namespace Eigen;

MatrixXd A(3, 3);
A << 1, 2, 3,
     0, 1, 4,
     5, 6, 0;

MatrixXd A_inv = A.inverse();
MatrixXd A_inv_transpose = A_inv.transpose();

위 코드는 행렬 \mathbf{A}의 역행렬과 그 전치 행렬을 계산하는 방법을 보여준다. 이와 같은 역행렬의 전치 연산은 다양한 선형 시스템에서 중요한 역할을 한다.

전치 행렬과 특이값 분해(SVD)

전치 행렬은 특이값 분해(Singular Value Decomposition, SVD)에서도 중요한 역할을 한다. 특이값 분해는 임의의 행렬을 세 개의 행렬로 분해하는 강력한 도구이며, 데이터 분석, 신호 처리, 머신러닝에서 자주 사용된다. 주어진 행렬 \mathbf{A}에 대해 SVD는 다음과 같이 표현된다:

\mathbf{A} = \mathbf{U} \mathbf{\Sigma} \mathbf{V}^T

여기서: - \mathbf{U}\mathbf{A}의 좌측 특이벡터(left singular vectors)로 이루어진 직교 행렬, - \mathbf{\Sigma}\mathbf{A}의 특이값(singular values)들이 대각 성분으로 나열된 대각 행렬, - \mathbf{V}^T\mathbf{A}의 우측 특이벡터(right singular vectors)로 이루어진 행렬의 전치이다.

전치 연산이 SVD에서 중요한 이유는 \mathbf{V}^T\mathbf{A}의 우측 특이벡터로 구성된 행렬의 전치 행렬이기 때문이다. 또한, 전치 연산은 SVD의 여러 성질을 활용하는 데 중요한 역할을 한다.

SVD의 성질

  1. 전치 행렬에 대한 SVD:
(\mathbf{A}^T) = \mathbf{V} \mathbf{\Sigma}^T \mathbf{U}^T

즉, 행렬 \mathbf{A}의 전치 행렬의 특이값 분해는 \mathbf{A}의 특이값 분해에서 좌측 특이벡터와 우측 특이벡터를 교환한 것과 같다.

  1. 특이값의 불변성: 전치 연산을 하더라도 특이값 \mathbf{\Sigma}는 변하지 않는다. 이는 전치 연산이 행렬의 크기와 형상에는 영향을 미치지만, 그 자체의 값에는 영향을 미치지 않는다는 것을 의미한다.

Eigen 라이브러리에서는 SVD를 간단하게 구현할 수 있다. 다음 예제는 특이값 분해와 전치 연산을 사용하는 방법을 보여준다:

#include <Eigen/Dense>
using namespace Eigen;

MatrixXd A(4, 2);
A << 1, 2,
     3, 4,
     5, 6,
     7, 8;

JacobiSVD<MatrixXd> svd(A, ComputeThinU | ComputeThinV);
MatrixXd U = svd.matrixU();
MatrixXd S = svd.singularValues().asDiagonal();
MatrixXd V = svd.matrixV();

MatrixXd A_transpose_svd = V * S.transpose() * U.transpose();

이 코드는 \mathbf{A}의 특이값 분해와 전치 행렬을 이용하여 원래 행렬의 특이값 분해를 계산하는 방법을 보여준다. 특이값 분해는 주로 차원 축소(dimensionality reduction), 노이즈 제거, 데이터 압축 등의 문제를 해결하는 데 사용된다.

전치 행렬과 그라디언트 계산

전치 행렬은 벡터 미적분학과 그라디언트 계산에서도 중요한 역할을 한다. 벡터함수 \mathbf{f}(\mathbf{x})의 그라디언트는 다음과 같이 정의된다:

\nabla \mathbf{f}(\mathbf{x}) = \frac{\partial \mathbf{f}}{\partial \mathbf{x}}

행렬 함수의 그라디언트를 계산할 때, 전치 연산은 다음과 같이 등장한다. 함수 f(\mathbf{x}) = \mathbf{x}^T \mathbf{A} \mathbf{x}에 대해 그라디언트는 다음과 같이 계산된다:

\nabla f(\mathbf{x}) = 2 \mathbf{A} \mathbf{x}

여기서 \mathbf{A}는 대칭 행렬일 필요가 있다. 만약 \mathbf{A}가 비대칭 행렬이라면, 그라디언트는 다음과 같은 형태로 나타난다:

\nabla f(\mathbf{x}) = (\mathbf{A} + \mathbf{A}^T) \mathbf{x}

전치 연산은 이와 같이 그라디언트 계산 과정에서 필수적인 역할을 한다. 특히, 최적화 문제에서 함수의 기울기를 계산하여 경로를 찾을 때 전치 연산이 활용된다.

전치 연산과 직교화

직교화(Orthogonalization)는 벡터 집합을 서로 직교하는 집합으로 변환하는 과정이다. 전치 연산은 직교화 알고리즘, 특히 그램-슈미트 직교화(Gram-Schmidt orthogonalization)에서 중요한 역할을 한다. 이 알고리즘은 벡터 집합을 직교화하고, 직교 벡터를 생성하는 과정에서 전치 연산을 사용하여 계산한다.

그램-슈미트 알고리즘을 간단히 설명하면, 주어진 벡터 집합 \mathbf{v}_1, \mathbf{v}_2, \dots, \mathbf{v}_n에 대해 직교 벡터 집합 \mathbf{u}_1, \mathbf{u}_2, \dots, \mathbf{u}_n을 구하는 과정이다. 이 과정은 다음과 같이 진행된다:

\mathbf{u}_1 = \mathbf{v}_1
\mathbf{u}_2 = \mathbf{v}_2 - \frac{\mathbf{v}_2^T \mathbf{u}_1}{\mathbf{u}_1^T \mathbf{u}_1} \mathbf{u}_1
\mathbf{u}_3 = \mathbf{v}_3 - \frac{\mathbf{v}_3^T \mathbf{u}_1}{\mathbf{u}_1^T \mathbf{u}_1} \mathbf{u}_1 - \frac{\mathbf{v}_3^T \mathbf{u}_2}{\mathbf{u}_2^T \mathbf{u}_2} \mathbf{u}_2

이 알고리즘에서 전치 연산은 벡터 간 내적을 계산하는 데 사용된다. 이를 통해 직교 벡터를 계산하며, 결과적으로 선형 독립인 벡터 집합을 얻을 수 있다.

Eigen 라이브러리에서 그램-슈미트 직교화를 쉽게 구현할 수 있다:

#include <Eigen/Dense>
using namespace Eigen;

MatrixXd A(3, 3);
A << 1, 2, 3,
     4, 5, 6,
     7, 8, 9;

HouseholderQR<MatrixXd> qr(A);
MatrixXd Q = qr.householderQ();

이 코드는 그램-슈미트 알고리즘을 사용하여 행렬 \mathbf{A}의 직교화를 수행하고, 직교 행렬 \mathbf{Q}를 생성한다. 전치 연산은 벡터 간의 내적을 계산하고, 직교화된 벡터를 구하는 데 핵심적인 역할을 한다.