Source code for multipie.util.util_gram_schmidt

"""
For Gram-Schmidt orthonormalization.
"""

import numpy as np
import sympy as sp


# ==================================================
[docs] def gram_schmidt(vec, n_max=None): """ Gram-Schmidt orthogonalization (sympy). Args: vec (array-like): list of vectors to be orthogonalized, [[sympy]]. n_max (int, optional): max. of nonzero basis. Returns: - (ndarray) -- list of nonzero orthogonalized vectors, [[sympy]]. - (ndarray) -- indices of nonzero vectors, [int]. """ ip = lambda x, y: np.vectorize(sp.expand)(np.vdot(x, y)) norm = lambda x: sp.sqrt(ip(x, x)) vec = np.asarray(vec, dtype=object) vec = np.vectorize(sp.expand)(vec) if vec.ndim < 2: nv = norm(vec) if nv != 0: vec /= nv vec = np.vectorize(sp.radsimp)(vec) return vec, np.array([0]) if n_max is None: n_max = len(vec) ortho_vec = [] nonzero = [] for no, v in enumerate(vec): for u in ortho_vec: v -= sp.expand(sp.radsimp(ip(v, u) / ip(u, u))) * u v = np.vectorize(sp.simplify)(v) if not (v == 0).all(): ortho_vec.append(v) nonzero.append(no) if len(ortho_vec) == n_max: break nonzero = np.asarray(nonzero) ret = [] for v in ortho_vec: nv = norm(v) if nv != 0: v /= nv v = np.vectorize(sp.radsimp)(v) ret.append(v) ortho_vec = np.asarray(ret, dtype=object) return ortho_vec, nonzero
# ==================================================
[docs] def gram_schmidt_float(vec, n_max=None, TOL=1e-8): """ Gram-Schmidt orthogonalization for real vectors by converting to float. Args: vec (array-like): list of vectors to be orthogonalized, [[sympy]]. n_max (int, optional): max. of nonzero basis. TOL (float, optional): absolute tolerance. Returns: - (ndarray) -- list of nonzero orthogonalized vectors, [[float]]. - (ndarray) -- indices of nonzero vectors, [int]. """ norm = lambda x: np.sqrt(np.dot(x, x)) vec = np.asarray(vec, dtype=float) if vec.ndim < 2: nv = norm(vec) if nv > TOL: vec /= nv return vec, np.array([0]) if n_max is None: n_max = len(vec) ortho_vec = [] nonzero = [] for no, v in enumerate(vec): for u in ortho_vec: v -= np.dot(v, u) / np.dot(u, u) * u nv = norm(v) if nv > TOL: ortho_vec.append(v / nv) nonzero.append(no) if len(ortho_vec) == n_max: break ortho_vec = np.asarray(ortho_vec) nonzero = np.asarray(nonzero) return ortho_vec, nonzero
# ==================================================
[docs] def gram_schmidt_complex(vec, n_max=None, TOL=1e-8): """ Gram-Schmidt orthogonalization for complex vectors by converting to complex. Args: vec (array-like): list of vectors to be orthogonalized, [[sympy]]. n_max (int, optional): max. of nonzero basis. TOL (float, optional): absolute tolerance. Returns: - (ndarray) -- list of nonzero orthogonalized vectors, [[complex]]. - (ndarray) -- indices of nonzero vectors, [int]. """ norm = lambda x: np.sqrt(np.vdot(x, x)) vec = np.asarray(vec, dtype=complex) if vec.ndim < 2: nv = norm(vec) if nv > TOL: vec /= nv return vec, np.array([0]) if n_max is None: n_max = len(vec) ortho_vec = [] nonzero = [] for no, v in enumerate(vec): for u in ortho_vec: v -= np.vdot(v, u) / np.vdot(u, u) * u nv = norm(v) if nv > TOL: ortho_vec.append(v / nv) nonzero.append(no) if len(ortho_vec) == n_max: break ortho_vec = np.asarray(ortho_vec) nonzero = np.asarray(nonzero) return ortho_vec, nonzero