Skip to content

Commit

Permalink
computation of cartan matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
slashbade committed May 1, 2024
1 parent f5b4554 commit 463f549
Show file tree
Hide file tree
Showing 12 changed files with 1,086 additions and 860 deletions.
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"python.testing.pytestArgs": [
"."
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
28 changes: 14 additions & 14 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Lie Group Machine Learning

## Introduction

This is an auxilliary lib for my final year project, which aims to create a working high performance tensor-based implementation of Lie structure theory. The goal of the whole project is to design an learning algorithm based on structure theory of Lie algebra.

## Basic

Contains basic definition and operation for Lie algebra.

## Reference

- Computing Cartan subalgebras of Lie algebras, De Graaf et al., 1996
- Handbook of Computatational Group Theory, O’Brien, 2005
# Lie Group Machine Learning

## Introduction

This is an auxilliary lib for my final year project, which aims to create a working high performance tensor-based implementation of Lie structure theory. The goal of the whole project is to design an learning algorithm based on structure theory of Lie algebra.

## Basic

Contains basic definition and operation for Lie algebra.

## Reference

- Computing Cartan subalgebras of Lie algebras, De Graaf et al., 1996
- Handbook of Computatational Group Theory, O’Brien, 2005
Binary file modified __pycache__/basic.cpython-311.pyc
Binary file not shown.
Binary file added __pycache__/basic.cpython-312.pyc
Binary file not shown.
Binary file added __pycache__/cartan_subalgebra.cpython-312.pyc
Binary file not shown.
Binary file added __pycache__/general_linear.cpython-312.pyc
Binary file not shown.
270 changes: 128 additions & 142 deletions basic.py
Original file line number Diff line number Diff line change
@@ -1,142 +1,128 @@
import numpy as np


class LieAlgebra:
def __init__(self, structure_constant: np.ndarray, basis: np.ndarray = None) -> None:
"""Initialize Lie algebra with structure constant
Args:
structure_constant (np.ndarray): structure constant in the shape (basis_num, basis_num, basis_num)
"""
self.structure_constant = structure_constant
self.dimension = structure_constant.shape[0]
self.basis = np.eye(self.dimension)
if basis is not None:
self.basis = basis

class SubLieAlgebra(LieAlgebra):
def __init__(self, L: LieAlgebra, subspace_basis: np.ndarray) -> None:
"""Initialize Lie algebra with structure constant
Args:
L (LieAlgebra): Lie algebra
subspace_basis (np.ndarray): orthogonal basis of subspace, each line is a basis
"""
self.structure_constant = np.zeros((subspace_basis.shape[0], subspace_basis.shape[0], subspace_basis.shape[0]))
for i in range(subspace_basis.shape[0]):
for j in range(subspace_basis.shape[0]):
self.structure_constant[i, j, :] = subspace_basis @ bracket(L, subspace_basis[i], subspace_basis[j])
self.dimension = subspace_basis.shape[0]
self.basis = subspace_basis

def presentation(L: LieAlgebra, x: np.ndarray) -> np.ndarray:
"""Change of basis
Args:
B (np.ndarray): new basis
x (np.ndarray): vector in the old basis
Returns:
np.ndarray: vector in the new basis
"""
assert L.basis.shape[1] == x.shape[0]
return L.basis @ x

def adjoint(L: LieAlgebra, x: np.ndarray) -> np.ndarray:
"""Obtain adjoint representation in the matrix form
Args:
x (np.ndarray): matrix in GLn
Returns:
np.ndarray: adjoint representation of shape (basis_num, basis_num)
"""

adjoint_mat = np.zeros((L.dimension, L.dimension))
for i in range(L.dimension):
adjoint_mat[i, :] = np.dot(np.transpose(L.structure_constant[:, :, i]), presentation(L, x))
return adjoint_mat

def bracket(L: LieAlgebra, x: np.ndarray, y: np.ndarray) -> np.ndarray:
"""Computes the bracket of two vectors
Args:
x (np.ndarray): vector in L
y (np.ndarray): vector in L
Returns:
np.ndarray: bracket of x and y
"""
bracket_prod = np.zeros(L.dimension)
for i in range(L.dimension):
bracket_prod[i] = L.structure_constant[:, :, i] @ y @ x

return bracket_prod

def is_ad_nilpotent(L: LieAlgebra, x: np.ndarray) -> bool:
"""Justify if a matrix is nilpotent
Args:
x (np.ndarray): matrix in GLn
Returns:
bool: nilpotency of end
"""
tol = 1e-8
adx = adjoint(L, x)
# print("testadx", adx.shape)
eigvals = np.linalg.eigvals(adx)
if all(np.abs(eigvals) <= tol):
return True
else:
return False

def is_in_subspace(L: LieAlgebra, subspace_basis: np.ndarray, new_coord: np.ndarray) -> bool:
"""Justify if a vector is in the subspace spanned by basis
Args:
subspace_basis (np.ndarray): basis of subspace, each line is a basis
new_coord (np.ndarray): new vectot
Returns:
bool: if vector in the subspace
"""
subspace_basis = subspace_basis.transpose()
matrix_rank = np.linalg.matrix_rank(subspace_basis)
ext_matrix = np.concatenate([subspace_basis, new_coord.reshape((-1, 1))], axis=1)
ext_matrix_rank = np.linalg.matrix_rank(ext_matrix)
if matrix_rank >= ext_matrix_rank:
return True
return False

def is_sub_Lie_algebra(L: LieAlgebra, subspace_basis: np.ndarray) -> bool:
"""Justify if a subspace is a sub Lie algebra
Args:
subspace_basis (np.ndarray): orthogonal basis of subspace, each line is a basis
Returns:
bool: if subspace is a sub Lie algebra
"""
basis_num = subspace_basis.shape[0]
for i in range(basis_num):
for j in range(i, basis_num):
if not is_in_subspace(L, subspace_basis, bracket(L, subspace_basis[i], subspace_basis[j])):
return False
return True


def Killing_form(L: LieAlgebra, x: np.ndarray, y: np.ndarray) -> np.float32:
return np.trace(adjoint(L, x) @ adjoint(L, y))

def Killing_form_basis_matrix(L: LieAlgebra) -> np.ndarray:
kf_m = np.zeros((L.dimension, L.dimension))
for i in range(L.dimension):
for j in range(L.dimension):
kf_m[i, j] = Killing_form(L, L.basis[i], L.basis[j])
return kf_m

def is_semisimple(L: LieAlgebra) -> bool:
kf_m = Killing_form_basis_matrix(L)
return np.linalg.matrix_rank(kf_m) == L.dimension

import numpy as np


class LieAlgebra:
def __init__(self, structure_constant: np.ndarray, basis: np.ndarray = None) -> None:
"""Initialize Lie algebra with structure constant
Args:
structure_constant (np.ndarray): structure constant in the shape (basis_num, basis_num, basis_num)
"""
self.structure_constant = structure_constant
self.dimension = structure_constant.shape[0]
self.basis = np.eye(self.dimension)
if basis is not None:
self.basis = basis

class LieSubalgebra(LieAlgebra):
def __init__(self, L: LieAlgebra, subspace_basis: np.ndarray) -> None:
"""Initialize Lie algebra with structure constant
Args:
L (LieAlgebra): Lie algebra
subspace_basis (np.ndarray): orthogonal basis of subspace, each line is a basis
"""
self.structure_constant = np.zeros((subspace_basis.shape[0], subspace_basis.shape[0], subspace_basis.shape[0]))
for i in range(subspace_basis.shape[0]):
for j in range(subspace_basis.shape[0]):
self.structure_constant[i, j, :] = subspace_basis @ bracket(L, subspace_basis[i], subspace_basis[j])
self.dimension = subspace_basis.shape[0]
self.basis = subspace_basis


def adjoint(L: LieAlgebra, x: np.ndarray) -> np.ndarray:
"""Obtain adjoint representation in the matrix form
Args:
x (np.ndarray): matrix in GLn
Returns:
np.ndarray: adjoint representation of shape (basis_num, basis_num)
"""

adjoint_mat = np.zeros((L.dimension, L.dimension))
for i in range(L.dimension):
adjoint_mat[i, :] = np.transpose(L.structure_constant[:, :, i]) @ (L.basis @ x)
return adjoint_mat

def bracket(L: LieAlgebra, x: np.ndarray, y: np.ndarray) -> np.ndarray:
"""Computes the bracket of two vectors
Args:
x (np.ndarray): vector in L
y (np.ndarray): vector in L
Returns:
np.ndarray: bracket of x and y
"""
bracket_prod = np.zeros(L.dimension)
for i in range(L.dimension):
bracket_prod[i] = L.structure_constant[:, :, i] @ y @ x

return bracket_prod

def is_ad_nilpotent(L: LieAlgebra, x: np.ndarray) -> bool:
"""Justify if a matrix is nilpotent
Args:
x (np.ndarray): matrix in GLn
Returns:
bool: nilpotency of end
"""
tol = 1e-8
adx = adjoint(L, x)
# print("testadx", adx.shape)
eigvals = np.linalg.eigvals(adx)
return all(np.abs(eigvals) <= tol)

def is_in_subspace(L: LieAlgebra, new_coord: np.ndarray) -> bool:
"""Justify if a vector is in the subspace spanned by basis
Args:
subspace_basis (np.ndarray): basis of subspace, each line is a basis
new_coord (np.ndarray): new vectot
Returns:
bool: if vector in the subspace
"""
subspace_basis = L.basis.transpose()
matrix_rank = np.linalg.matrix_rank(subspace_basis)
ext_matrix = np.concatenate([subspace_basis, new_coord.reshape((-1, 1))], axis=1)
ext_matrix_rank = np.linalg.matrix_rank(ext_matrix)
if matrix_rank >= ext_matrix_rank:
return True
return False

def is_sub_Lie_algebra(L: LieAlgebra, subspace_basis: np.ndarray) -> bool:
"""Justify if a subspace is a sub Lie algebra
Args:
subspace_basis (np.ndarray): orthogonal basis of subspace, each line is a basis
Returns:
bool: if subspace is a sub Lie algebra
"""
basis_num = subspace_basis.shape[0]
for i in range(basis_num):
for j in range(i, basis_num):
if not is_in_subspace(L, subspace_basis, bracket(L, subspace_basis[i], subspace_basis[j])):
return False
return True


def Killing_form(L: LieAlgebra, x: np.ndarray, y: np.ndarray) -> np.float32:
return np.trace(adjoint(L, x) @ adjoint(L, y))

def Killing_form_basis_matrix(L: LieAlgebra) -> np.ndarray:
kf_m = np.zeros((L.dimension, L.dimension))
for i in range(L.dimension):
for j in range(L.dimension):
kf_m[i, j] = Killing_form(L, L.basis[i], L.basis[j])
return kf_m

def is_semisimple(L: LieAlgebra) -> bool:
kf_m = Killing_form_basis_matrix(L)
return np.linalg.matrix_rank(kf_m) == L.dimension


Loading

0 comments on commit 463f549

Please sign in to comment.