import numpy as np
try:
import numqi
except ImportError:
%pip install numqi
import numqi
np_rng = np.random.default_rng()
d=3¶
Usually, they denotes the following $8$ matrices with $3$ columns and $3$ rows. wiki/Gell-Mann-matrices One can retrieve these matrices matrices via numqi.gellmann
module as follows. The order of the matrices is different from the one in the wiki page and numqi
chose this one for easier manipulation when $d$ is not $3$.
gm3 = numqi.gellmann.all_gellmann_matrix(3, with_I=False)
for x in gm3:
print(x.real if (x.imag.max() < 1e-4) else x)
[[0. 1. 0.] [1. 0. 0.] [0. 0. 0.]] [[0. 0. 1.] [0. 0. 0.] [1. 0. 0.]] [[0. 0. 0.] [0. 0. 1.] [0. 1. 0.]] [[ 0.+0.j -0.-1.j 0.+0.j] [ 0.+1.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j]] [[ 0.+0.j 0.+0.j -0.-1.j] [ 0.+0.j 0.+0.j 0.+0.j] [ 0.+1.j 0.+0.j 0.+0.j]] [[ 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j -0.-1.j] [ 0.+0.j 0.+1.j 0.+0.j]] [[ 1. 0. 0.] [ 0. -1. 0.] [ 0. 0. 0.]] [[ 0.57735027 0. 0. ] [ 0. 0.57735027 0. ] [ 0. 0. -1.15470054]]
d=2 Pauli¶
Generalized Gell-Mann matrices are also introduced when $d$ is not $3$ wiki/generalization-pauli. And specifically, when $d=2$, the generalized Gell-Mann matrices are the Pauli matrices. For brief, we will call the generalized Gell-Mann matrices as Gell-Mann matrices.
gm2 = numqi.gellmann.all_gellmann_matrix(2, with_I=False)
for x in gm2:
print(x.real if (x.imag.max() < 1e-4) else x)
[[0. 1.] [1. 0.]] [[ 0.+0.j -0.-1.j] [ 0.+1.j 0.+0.j]] [[ 1. 0.] [ 0. -1.]]
d=4¶
For $d$-dimensional Gell-Mann matrices, there is $d^2-1$ matrices. The first $d(d-1)/2$ matrices are real symmetric matrices (Pauli-X like), the following $d(d-1)/2$ matrics are pure imaginary anti-symmetric matrices (Pauli-Y like), and the last $d-1$ matrices are real diagonal matrices (Pauli-Z like). They are orthogonal to each other with respect to the Hilbert-Schmidt inner product and they make up a basis for the space of tracelss Hermitian matrices.
d = 4
gmd = numqi.gellmann.all_gellmann_matrix(d, with_I=False)
print('Pauli-X like Gell-Mann matric, real, symmetric, off-diagonal')
ind0 = np_rng.integers(0, d*(d-1)//2)
print(f'$M_{ind0}$=\n', gmd[ind0].real)
print('Pauli-Y like Gell-Mann matric, pure imaginary, anti-symmetric, off-diagonal')
ind1 = np_rng.integers(d*(d-1)//2, d*(d-1))
print(f'$M_{ind1}$=\n', gmd[ind1])
print('Pauli-Z like Gell-Mann matric, real, diagonal')
ind2 = np_rng.integers(d*(d-1), d*d-1)
print(f'$M_{ind2}$=\n', gmd[ind2].real)
Pauli-X like Gell-Mann matric, real, symmetric, off-diagonal $M_0$= [[0. 1. 0. 0.] [1. 0. 0. 0.] [0. 0. 0. 0.] [0. 0. 0. 0.]] Pauli-Y like Gell-Mann matric, pure imaginary, anti-symmetric, off-diagonal $M_10$= [[ 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j -0.-1.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+1.j 0.+0.j 0.+0.j]] Pauli-Z like Gell-Mann matric, real, diagonal $M_14$= [[ 0.40824829 0. 0. 0. ] [ 0. 0.40824829 0. 0. ] [ 0. 0. 0.40824829 0. ] [ 0. 0. 0. -1.22474487]]
Identity matrix¶
Sometimes, the identity matrix is also included in the Gell-Mann matrices to make a complete, orthogonal basis for Hermitian basis. In this case, the number of Gell-Mann matrices is $d^2$. numqi.gellmann
module append this identity matrix $M_{d^2-1}=\sqrt{2/d}I$ to the Gell-Mann matrices as the last element.
"Orthogonal" means that the Hilbert-Schmidt inner product of any two matrices is zero. The Hilbert-Schmidt inner product of two matrices $A$ and $B$ is defined as $\langle A, B \rangle = \mathrm{Tr}(A^\dagger B)$. As for the Gell-Mann matrices, their Hilbert-Schmidt inner product
$$ \langle M_i,M_j\rangle=2\delta_{ij} $$
where $\delta_{ij}$ is the Kronecker delta and the factor $2$ is due to the normalization of the Gell-Mann matrices (so that when $d=2$, it will recover the Pauli matrices).
gmd = numqi.gellmann.all_gellmann_matrix(d) #with_I=True (default)
print(f'identity: \n{gmd[-1].real}')
mat0,mat1 = gmd[np_rng.permutation(d*d)[:2]] # randomly pick two matrix
print(f'mat0=\n{mat0}\nmat1=\n{mat1}')
print('<mat0,mat0>=', np.trace(mat0.conj().T @ mat0))
print('<mat1,mat1>=', np.trace(mat1.conj().T @ mat1))
print('<mat0,mat1>=', np.trace(mat0.conj().T @ mat1))
identity: [[0.70710678 0. 0. 0. ] [0. 0.70710678 0. 0. ] [0. 0. 0.70710678 0. ] [0. 0. 0. 0.70710678]] mat0= [[0.+0.j 1.+0.j 0.+0.j 0.+0.j] [1.+0.j 0.+0.j 0.+0.j 0.+0.j] [0.+0.j 0.+0.j 0.+0.j 0.+0.j] [0.+0.j 0.+0.j 0.+0.j 0.+0.j]] mat1= [[ 0.40824829+0.j 0. +0.j 0. +0.j 0. +0.j] [ 0. +0.j 0.40824829+0.j 0. +0.j 0. +0.j] [ 0. +0.j 0. +0.j 0.40824829+0.j 0. +0.j] [ 0. +0.j 0. +0.j 0. +0.j -1.22474487+0.j]] <mat0,mat0>= (2+0j) <mat1,mat1>= (1.9999999999999998+0j) <mat0,mat1>= 0j
"Complete" basis means any Hermitian matrix can be expressed as a linear combination of the Gell-Mann matrices with real coefficients, and any matrix (Hermitian or non-Hermitian) can be expressed as a linear combination of the Gell-Mann matrices with complex coefficients.
$$ A=\sum_i a_i M_i,a_i=\langle M_i,A \rangle/2. $$
When the matrix $A$ is Hermitian, the coefficients $a_i$ are real. When the matrix $A$ is non-Hermitian, the coefficients $a_i$ are complex.
d = 3
print('non-Hermitian matrix')
matA = np.around(np_rng.uniform(-1,1,size=(d,d)) + 1j*np_rng.uniform(-1,1,size=(d,d)), 3)
coeff = numqi.gellmann.matrix_to_gellmann_basis(matA)
print(f'matA=\n{matA}')
print(f'coeff=\n{coeff}')
print('\nHermitian matrix')
matA = matA + matA.T.conj()
coeff = numqi.gellmann.matrix_to_gellmann_basis(matA)
print(f'matA=\n{matA}')
print(f'coeff.real=\n{coeff.real}')
print(f'coeff.imag=\n{coeff.imag}')
matA_restored = numqi.gellmann.gellmann_basis_to_matrix(coeff)
print(f'matA_restored=\n{matA_restored}')
non-Hermitian matrix matA= [[ 0.941-0.448j -0.727-0.76j 0.405+0.172j] [ 0.664-0.716j -0.127-0.868j 0.897+0.961j] [ 0.512+0.009j -0.195-0.05j -0.565+0.479j]] coeff= [-0.0315 -0.738j 0.4585 +0.0905j 0.351 +0.4555j 0.022 -0.6955j -0.0815 -0.0535j -0.5055 +0.546j 0.534 +0.21j 0.56118446-0.65644726j 0.10165382-0.34170382j] Hermitian matrix matA= [[ 1.882+0.j -0.063-0.044j 0.917+0.163j] [-0.063+0.044j -0.254+0.j 0.702+1.011j] [ 0.917-0.163j 0.702-1.011j -1.13 +0.j ]] coeff.real= [-0.063 0.917 0.702 0.044 -0.163 -1.011 1.068 1.12236892 0.20330765] coeff.imag= [0. 0. 0. 0. 0. 0. 0. 0. 0.] matA_restored= [[ 1.882+0.j -0.063-0.044j 0.917+0.163j] [-0.063+0.044j -0.254+0.j 0.702+1.011j] [ 0.917-0.163j 0.702-1.011j -1.13 +0.j ]]
Connection with Frobenius inner product¶
Given two matrix $A,B\in\mathbb{C}^{m\times n}$, their Frobenius inner product wiki is defined
$$ \langle A,B\rangle_{fro}=\sum_{ij} A_{ij}^* B_{ij}=\mathrm{Tr}[A^\dagger B] $$
If we choose the Gell-Mann matrices as the basis for the space of $n\times n$ matrices, then the Frobenius inner product of two matrices is related to the inner product of two coefficient vectors.
$$ A=\sum_i a_i M_i,a_i=\langle M_i,A \rangle/2. $$
$$ B=\sum_i b_i M_i,b_i=\langle M_i,B \rangle/2. $$
$$ \langle A,B\rangle_{fro} = 2\langle \vec{a},\vec{b}\rangle=2\sum_i{a_i^*b_i} $$
d = 4
matA = np.around(np_rng.uniform(-1,1,size=(d,d)) + 1j*np_rng.uniform(-1,1,size=(d,d)), 3)
coeffA = numqi.gellmann.matrix_to_gellmann_basis(matA)
matB = np.around(np_rng.uniform(-1,1,size=(d,d)) + 1j*np_rng.uniform(-1,1,size=(d,d)), 3)
coeffB = numqi.gellmann.matrix_to_gellmann_basis(matB)
print('<A,B>=', np.trace(matA.T.conj() @ matB))
print('<coeffA,coeffB>=', 2*np.vdot(coeffA, coeffB))
<A,B>= (-0.9631699999999999-0.05298599999999998j) <coeffA,coeffB>= (-0.9631700000000003-0.05298599999999992j)