"""Functionality for dealing with bases."""
import copy
import numpy as np
[docs]def cartesian_basis(dimension=3):
r"""
Get the standard Cartesian basis in the specified dimension.
:param int dimension: Dimension of Euclidean space.
:return: The identity matrix in :math:`\mathbb{R}^n`, where n is the desired dimension.
:rtype: :class:`Numpy array <numpy.ndarray>`
.. rubric:: Examples
>>> cartesian_basis(2)
array([[1., 0.],
[0., 1.]])
"""
return np.identity(dimension)
[docs]def cartesian_basis_vector(i, dimension=3):
"""
Get the i:th standard Cartesian basis vector in the specified dimension (3 by default).
:param int i: Index of the basis vector (in [0, 1, ..., dimension - 1]).
:param int dimension: Dimension of Euclidean space.
:return: The i:th Cartesian basis vector.
:rtype: :class:`Numpy array <numpy.ndarray>`
.. rubric:: Examples
>>> cartesian_basis_vector(1)
array([0., 1., 0.])
"""
return cartesian_basis(dimension=dimension)[i]
[docs]def basis_matrix(basis_vectors_array):
"""
Construct the matrix representation of a basis from a list of basis vectors.
:param basis_vectors_array: List of basis vectors.
:return: Matrix representation of basis (square matrix with basis vectors as columns).
"""
dim = len(basis_vectors_array)
basis = np.empty((dim, dim))
for i in range(dim):
basis[:, i] = basis_vectors_array[i]
return basis
[docs]def basis_vectors(basis):
"""
Get a list of basis vectors from the matrix representation of a basis.
:param basis: Matrix representation of basis (square matrix with basis vectors as columns).
:return: List of basis vectors.
"""
return basis.T
[docs]def metric_tensor(basis):
"""
Compute the metric tensor for a basis.
:param basis: Basis (square matrix with basis vectors as columns).
:return: Metric tensor.
"""
if isinstance(basis, np.ndarray):
return np.dot(basis.T, basis)
b = np.array(basis)
return np.dot(b.T, b)
[docs]def inverse_metric_tensor(basis):
"""
Compute the inverse metric tensor for a basis.
:param basis: Basis (square matrix with basis vectors as columns).
:return: Inverse metric tensor.
"""
g = metric_tensor(basis)
if not isinstance(g, np.ndarray):
# Assume scalar
return 1 / g
return np.linalg.inv(g)
[docs]def dual_basis(basis):
r"""
Compute the dual basis of a given basis, i.e., the basis :math:`e^i` such that
:math:`\langle e_i, e^j \rangle = \delta_i^j`.
:param basis: Basis (square matrix with basis vectors as columns).
:return: Dual basis (square matrix with dual basis vectors as columns).
"""
if not isinstance(basis, np.ndarray):
# Assume scalar
return 1 / basis
# B^T * B_d = I => B_d = (B^T)^-1 = (B^-1)^T = B^-T
return np.linalg.inv(basis).T
[docs]def gram_schmidt_orthonormalization_rn(basis):
r"""
Create an orthonormal basis from a general basis of :math:`\mathbb{R}^n` or an n dimensional subspace of
:math:`\mathbb{R}^m` using the Gram-Schmidt process.
:param basis: Input basis (m by n matrix with the basis vectors as columns).
:type basis: :class:`Numpy array <numpy.ndarray>`
:return: Orthonormal basis (m by n matrix with the basis vectors as columns), where the basis vectors is
obtained by Gram-Schmidt orthonormalization of the input basis vectors.
:rtype: :class:`Numpy array <numpy.ndarray>`
"""
q, r = np.linalg.qr(basis)
for i in range(basis.shape[1]):
if np.dot(q[:, i], basis[:, i]) < 0:
q[:, i] *= -1
return q
[docs]def gram_schmidt_orthonormalization(basis, inner_product=np.dot):
r"""
Create an orthonormal basis for an inner product space V from a general basis using the Gram-Schmidt process.
:param basis: Input array of basis vectors.
:param inner_product: Inner product for the inner product space (a map :math:`V \times V \to \mathbb{R}` satisfying
the inner product properties).
:return: Orthonormal basis (matrix with the basis vectors as columns), where the basis vectors is
obtained by Gram-Schmidt orthonormalization of the input basis vectors.
"""
assert len(basis) > 0
on_basis = copy.deepcopy(basis)
for i in range(len(on_basis)):
for j in range(i):
on_basis[i] -= inner_product(on_basis[i], on_basis[j]) * on_basis[j]
on_basis[i] /= np.sqrt(inner_product(on_basis[i], on_basis[i]))
return on_basis
if __name__ == "__main__":
import doctest
doctest.testmod()