def test_poorly_conditioned(self): """ Testing against a single poorly-conditioned matrix. Generated as a random 6x6 array, and then divided the first row and column by 1e6 """ mat = np.array([[ 6.6683264e-07, 6.3376014e-07, 4.5754601e-07, 7.1252750e-07, 7.5942456e-07, 5.9028134e-07 ], [ 5.7484930e-07, 6.5606222e-01, 6.5073522e-01, 2.4251825e-01, 1.0735555e-01, 2.6956707e-01 ], [ 6.1098206e-07, 4.0445840e-01, 5.6152644e-01, 5.8278476e-01, 8.0418942e-01, 7.7306821e-01 ], [ 8.5656473e-07, 4.3833014e-01, 5.7838875e-01, 2.4317287e-01, 1.6641302e-01, 3.9590950e-01 ], [ 4.4858020e-07, 1.1731434e-01, 7.3598305e-01, 4.5670520e-01, 5.8185932e-01, 9.4438709e-01 ], [ 4.1073805e-07, 9.6286350e-02, 7.7365790e-01, 1.3120009e-01, 9.3908360e-01, 1.4665616e-01 ]]) phi = expm(mat) out_scipy = expm_scipy(mat) assert_arrays_equal(out_scipy, phi, decimal=8)
def expm(A, use_exact_onenorm="auto", verbose=False): from scipy.linalg import expm as expm_scipy return expm_scipy(A) # Core of expm, separated to allow testing exact and approximate # algorithms. # Hardcode a matrix order threshold for exact vs. estimated one-norms. use_exact_onenorm = A.shape[0] < 200 h = _ExpmPadeHelper(A, use_exact_onenorm=use_exact_onenorm) # Use Pade order 13. eta_3 = max(h.d6_tight, h.d8_loose) eta_4 = max(h.d8_loose, h.d10_loose) eta_5 = min(eta_3, eta_4) theta_13 = 4.25 # Choose smallest s>=0 such that 2**(-s) eta_5 <= theta_13 if eta_5 == 0: # Nilpotent special case s = 0 else: s = max(int(np.ceil(np.log2(eta_5 / theta_13))), 0) s = s + _ell(2**-s * h.A, 13) U, V = h.pade13_scaled(s) X = _solve_P_Q(U, V) # X = r_13(A)^(2^s) by repeated squaring. for i in range(s): X = X.dot(X) return X
def test_expm_nearly_identity(self): """ nearly the identity matrix """ a = np.array( [[1.0012, 0, 0.0003], [0.0075, 0.9876543, 0.0011], [0, 0, 0.9873]], dtype=np.float64) phi = expm(a) out_scipy = expm_scipy(a) assert_arrays_equal(out_scipy, phi, decimal=12)
def test_expm_one_huge_element(self): """ one value swamping the rest """ a = np.array( [[999.875, 0.2, 0.3], [0.1, 0.002, 0.001], [0.01, 0, -0.003]], dtype=np.float64) phi = expm(a) out_scipy = expm_scipy(a) assert_arrays_equal(out_scipy, phi, decimal=12)
def test_expm_one_large_element(self): """ one value slightly swamping the rest """ a = np.array( [[0.1, 0.02, 0.003], [1.875, 0.12, 0.11], [0.1234567, 0, 0.3]], dtype=np.float64) phi = expm(a) out_scipy = expm_scipy(a) assert_arrays_equal(out_scipy, phi, decimal=12)
def test_expm_random_non_zero_floats(self): """ arbitrarily large values, and some negatives """ a = np.array([[99.23452, 2.0000234523, 0.0003, 378.2362], [1.00001, 8754.236, 1.1007, 33.333333], [111, 0.00034, 3922.323, -999.333], [-1234.5678, -0.00034, 333.65, 13]], dtype=np.float64) phi = expm(a) out_scipy = expm_scipy(a) assert_arrays_equal(out_scipy, phi, decimal=12)
def test_expm_random_sparse(self): """ Testing against a large set of random 2D matricies with defined sparsity """ np.random.seed(7) for size in range(5, 40): for d in [x / 100 for x in range(10, 90)]: mat = sparse.random(size, size, density=d).toarray() phi = expm(mat) out_scipy = expm_scipy(mat) assert_arrays_equal(out_scipy, phi, decimal=7)
def expm(M): """ Computes the matrix exponential of M. Args: M (torch.tensor): Square matrix (N, N) Returns: M (torch.tensor): Matrix exponential (N, N) """ device = M.device dtype = M.dtype M = M.detach().cpu().numpy() M = expm_scipy(M) M = torch.from_numpy(M).type(dtype).to(device) return M
def test_expm_random_integers(self): """ a simple, arbitrary matrix """ a = np.array([[1, 2, 3], [1, 2, 1.1], [1, 0, 3]], dtype=np.float64) phi = expm(a) out_scipy = expm_scipy(a) assert_arrays_equal(out_scipy, phi, decimal=12)
def test_expm_all_ones(self): """ Test against a matrix of all ones """ a = np.ones((33, 33), dtype='float64') phi = expm(a) out_scipy = expm_scipy(a) assert_arrays_equal(out_scipy, phi, decimal=12)
def test_expm_all_zeros(self): """ Test against a matrix of all zeros """ a = np.zeros((20, 20), dtype='float32') phi = expm(a) out_scipy = expm_scipy(a) assert_arrays_equal(out_scipy, phi, decimal=12)
def test_expm_smallish_floats(self): """ This is just some arbitrary set of small-ish floats """ a = np.arange(1, 17, dtype='float64').reshape(4, 4) / 1e3 phi = expm(a) out_scipy = expm_scipy(a) assert_arrays_equal(out_scipy, phi, decimal=12)