Source code for tenpy.linalg.random_matrix

r"""Provide some random matrix ensembles for numpy.

The implemented ensembles are:

=========== ======================== ======================= ================== ===========
ensemble    matrix class drawn from  measure                 invariant under    beta
=========== ======================== ======================= ================== ===========
GOE         real, symmetric          ``~ exp(-n/4 tr(H^2))`` orthogonal O       1
----------- ------------------------ ----------------------- ------------------ -----------
GUE         hermitian                ``~ exp(-n/2 tr(H^2))`` unitary U          2
----------- ------------------------ ----------------------- ------------------ -----------
CRE         O(n)                     Haar                    orthogonal O       /
----------- ------------------------ ----------------------- ------------------ -----------
COE         U in U(n) with U = U^T   Haar                    orthogonal O       1
----------- ------------------------ ----------------------- ------------------ -----------
CUE         U(n)                     Haar                    unitary U          2
----------- ------------------------ ----------------------- ------------------ -----------
O_close_1   O(n)                     ?                       /                  /
----------- ------------------------ ----------------------- ------------------ -----------
U_close_1   U(n)                     ?                       /                  /
=========== ======================== ======================= ================== ===========


All functions in this module take a tuple ``(n, n)`` as first argument, such that
we can use the function :meth:`~tenpy.linalg.np_conserved.Array.from_func`
to generate a block diagonal :class:`~tenpy.linalg.np_conserved.Array` with the block from the
corresponding ensemble, for example::

    npc.Array.from_func_square(GOE, [leg, leg.conj()])

"""
# Copyright 2018-2019 TeNPy Developers, GNU GPLv3

import numpy as np

__all__ = [
    'box', 'standard_normal_complex', 'GOE', 'GUE', 'CRE', 'COE', 'CUE', 'O_close_1', 'U_close_1'
]


[docs]def box(size, W=1.): """return random number uniform in (-W, W].""" return (0.5 - np.random.random(size)) * (2. * W)
[docs]def standard_normal_complex(size): """return ``(R + 1.j*I)`` for independent `R` and `I` from np.random.standard_normal.""" return np.random.standard_normal(size) + 1.j * np.random.standard_normal(size)
[docs]def GOE(size): r"""Gaussian orthogonal ensemble (GOE). Parameters ---------- size : tuple ``(n, n)``, where `n` is the dimension of the output matrix. Returns ------- H : ndarray Real, symmetric numpy matrix drawn from the GOE, i.e. :math:`p(H) = 1/Z exp(-n/4 tr(H^2))` """ A = np.random.standard_normal(size) return (A + A.T) * 0.5
[docs]def GUE(size): r"""Gaussian unitary ensemble (GUE). Parameters ---------- size : tuple ``(n, n)``, where `n` is the dimension of the output matrix. Returns ------- H : ndarray Hermitian (complex) numpy matrix drawn from the GUE, i.e. :math:`p(H) = 1/Z exp(-n/4 tr(H^2))`. """ A = standard_normal_complex(size) return (A + A.T.conj()) * 0.5
[docs]def CRE(size): r"""Circular real ensemble (CRE). Parameters ---------- size : tuple ``(n, n)``, where `n` is the dimension of the output matrix. Returns ------- U : ndarray Orthogonal matrix drawn from the CRE (=Haar measure on O(n)). """ # almost same code as for CUE n, m = size assert n == m # ensure that `mode` in qr doesn't matter. A = np.random.standard_normal(size) Q, R = np.linalg.qr(A) # Q-R is not unique; to make it unique ensure that the diagonal of R is positive # Q' = Q*L; R' = L^{-1} *R, where L = diag(phase(diagonal(R))) L = np.diagonal(R) Q *= np.sign(L) return Q
[docs]def COE(size): r"""Circular orthogonal ensemble (COE). Parameters ---------- size : tuple ``(n, n)``, where `n` is the dimension of the output matrix. Returns ------- U : ndarray Unitary, symmetric (complex) matrix drawn from the COE (=Haar measure on this space). """ U = CUE(size) return np.dot(U.T, U)
[docs]def CUE(size): r"""Circular unitary ensemble (CUE). Parameters ---------- size : tuple ``(n, n)``, where `n` is the dimension of the output matrix. Returns ------- U : ndarray Unitary matrix drawn from the CUE (=Haar measure on U(n)). """ # almost same code as for CRE n, m = size assert n == m # ensure that `mode` in qr doesn't matter. A = standard_normal_complex(size) Q, R = np.linalg.qr(A) # Q-R is not unique; to make it unique ensure that the diagonal of R is positive # Q' = Q*L; R' = L^{-1} *R, where L = diag(phase(diagonal(R))) L = np.diagonal(R).copy() L[np.abs(L) < 1.e-15] = 1. Q *= L / np.abs(L) return Q
[docs]def O_close_1(size, a=0.01): r"""return an random orthogonal matrix 'close' to the Identity. Parameters ---------- size : tuple ``(n, n)``, where `n` is the dimension of the output matrix. a : float Parameter determining how close the result is on `O`; :math:`\lim_{a \rightarrow 0} <|O-E|>_a = 0`` (where `E` is the identity). Returns ------- O : ndarray Orthogonal matrix close to the identiy (for small `a`). """ n, m = size assert n == m A = GOE(size) / (2. * n)**0.5 # scale such that eigenvalues are in [-1, 1] E = np.eye(size[0]) Q, R = np.linalg.qr(E + a * A) L = np.diagonal(R) # make QR decomposition unique & ensure Q is close to one for small `a` Q *= np.sign(L) return Q
[docs]def U_close_1(size, a=0.01): r"""return an random orthogonal matrix 'close' to the identity. Parameters ---------- size : tuple ``(n, n)``, where `n` is the dimension of the output matrix. a : float Parameter determining how close the result is to the identity. :math:`\lim_{a \rightarrow 0} <|O-E|>_a = 0`` (where `E` is the identity). Returns ------- U : ndarray Unitary matrix close to the identiy (for small `a`). Eigenvalues are chosen i.i.d. as ``exp(1.j*a*x)`` with `x` uniform in [-1, 1]. """ n, m = size assert n == m U = CUE(size) # random unitary E = np.exp(1.j * a * (np.random.rand(n) * 2. - 1.)) return np.dot(U * E, U.T.conj())