test_decomp_cholesky.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. from numpy.testing import assert_array_almost_equal, assert_array_equal
  2. from pytest import raises as assert_raises
  3. from numpy import array, transpose, dot, conjugate, zeros_like, empty
  4. from numpy.random import random
  5. from scipy.linalg import cholesky, cholesky_banded, cho_solve_banded, \
  6. cho_factor, cho_solve
  7. from scipy.linalg._testutils import assert_no_overwrite
  8. class TestCholesky:
  9. def test_simple(self):
  10. a = [[8, 2, 3], [2, 9, 3], [3, 3, 6]]
  11. c = cholesky(a)
  12. assert_array_almost_equal(dot(transpose(c), c), a)
  13. c = transpose(c)
  14. a = dot(c, transpose(c))
  15. assert_array_almost_equal(cholesky(a, lower=1), c)
  16. def test_check_finite(self):
  17. a = [[8, 2, 3], [2, 9, 3], [3, 3, 6]]
  18. c = cholesky(a, check_finite=False)
  19. assert_array_almost_equal(dot(transpose(c), c), a)
  20. c = transpose(c)
  21. a = dot(c, transpose(c))
  22. assert_array_almost_equal(cholesky(a, lower=1, check_finite=False), c)
  23. def test_simple_complex(self):
  24. m = array([[3+1j, 3+4j, 5], [0, 2+2j, 2+7j], [0, 0, 7+4j]])
  25. a = dot(transpose(conjugate(m)), m)
  26. c = cholesky(a)
  27. a1 = dot(transpose(conjugate(c)), c)
  28. assert_array_almost_equal(a, a1)
  29. c = transpose(c)
  30. a = dot(c, transpose(conjugate(c)))
  31. assert_array_almost_equal(cholesky(a, lower=1), c)
  32. def test_random(self):
  33. n = 20
  34. for k in range(2):
  35. m = random([n, n])
  36. for i in range(n):
  37. m[i, i] = 20*(.1+m[i, i])
  38. a = dot(transpose(m), m)
  39. c = cholesky(a)
  40. a1 = dot(transpose(c), c)
  41. assert_array_almost_equal(a, a1)
  42. c = transpose(c)
  43. a = dot(c, transpose(c))
  44. assert_array_almost_equal(cholesky(a, lower=1), c)
  45. def test_random_complex(self):
  46. n = 20
  47. for k in range(2):
  48. m = random([n, n])+1j*random([n, n])
  49. for i in range(n):
  50. m[i, i] = 20*(.1+abs(m[i, i]))
  51. a = dot(transpose(conjugate(m)), m)
  52. c = cholesky(a)
  53. a1 = dot(transpose(conjugate(c)), c)
  54. assert_array_almost_equal(a, a1)
  55. c = transpose(c)
  56. a = dot(c, transpose(conjugate(c)))
  57. assert_array_almost_equal(cholesky(a, lower=1), c)
  58. class TestCholeskyBanded:
  59. """Tests for cholesky_banded() and cho_solve_banded."""
  60. def test_check_finite(self):
  61. # Symmetric positive definite banded matrix `a`
  62. a = array([[4.0, 1.0, 0.0, 0.0],
  63. [1.0, 4.0, 0.5, 0.0],
  64. [0.0, 0.5, 4.0, 0.2],
  65. [0.0, 0.0, 0.2, 4.0]])
  66. # Banded storage form of `a`.
  67. ab = array([[-1.0, 1.0, 0.5, 0.2],
  68. [4.0, 4.0, 4.0, 4.0]])
  69. c = cholesky_banded(ab, lower=False, check_finite=False)
  70. ufac = zeros_like(a)
  71. ufac[list(range(4)), list(range(4))] = c[-1]
  72. ufac[(0, 1, 2), (1, 2, 3)] = c[0, 1:]
  73. assert_array_almost_equal(a, dot(ufac.T, ufac))
  74. b = array([0.0, 0.5, 4.2, 4.2])
  75. x = cho_solve_banded((c, False), b, check_finite=False)
  76. assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
  77. def test_upper_real(self):
  78. # Symmetric positive definite banded matrix `a`
  79. a = array([[4.0, 1.0, 0.0, 0.0],
  80. [1.0, 4.0, 0.5, 0.0],
  81. [0.0, 0.5, 4.0, 0.2],
  82. [0.0, 0.0, 0.2, 4.0]])
  83. # Banded storage form of `a`.
  84. ab = array([[-1.0, 1.0, 0.5, 0.2],
  85. [4.0, 4.0, 4.0, 4.0]])
  86. c = cholesky_banded(ab, lower=False)
  87. ufac = zeros_like(a)
  88. ufac[list(range(4)), list(range(4))] = c[-1]
  89. ufac[(0, 1, 2), (1, 2, 3)] = c[0, 1:]
  90. assert_array_almost_equal(a, dot(ufac.T, ufac))
  91. b = array([0.0, 0.5, 4.2, 4.2])
  92. x = cho_solve_banded((c, False), b)
  93. assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
  94. def test_upper_complex(self):
  95. # Hermitian positive definite banded matrix `a`
  96. a = array([[4.0, 1.0, 0.0, 0.0],
  97. [1.0, 4.0, 0.5, 0.0],
  98. [0.0, 0.5, 4.0, -0.2j],
  99. [0.0, 0.0, 0.2j, 4.0]])
  100. # Banded storage form of `a`.
  101. ab = array([[-1.0, 1.0, 0.5, -0.2j],
  102. [4.0, 4.0, 4.0, 4.0]])
  103. c = cholesky_banded(ab, lower=False)
  104. ufac = zeros_like(a)
  105. ufac[list(range(4)), list(range(4))] = c[-1]
  106. ufac[(0, 1, 2), (1, 2, 3)] = c[0, 1:]
  107. assert_array_almost_equal(a, dot(ufac.conj().T, ufac))
  108. b = array([0.0, 0.5, 4.0-0.2j, 0.2j + 4.0])
  109. x = cho_solve_banded((c, False), b)
  110. assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
  111. def test_lower_real(self):
  112. # Symmetric positive definite banded matrix `a`
  113. a = array([[4.0, 1.0, 0.0, 0.0],
  114. [1.0, 4.0, 0.5, 0.0],
  115. [0.0, 0.5, 4.0, 0.2],
  116. [0.0, 0.0, 0.2, 4.0]])
  117. # Banded storage form of `a`.
  118. ab = array([[4.0, 4.0, 4.0, 4.0],
  119. [1.0, 0.5, 0.2, -1.0]])
  120. c = cholesky_banded(ab, lower=True)
  121. lfac = zeros_like(a)
  122. lfac[list(range(4)), list(range(4))] = c[0]
  123. lfac[(1, 2, 3), (0, 1, 2)] = c[1, :3]
  124. assert_array_almost_equal(a, dot(lfac, lfac.T))
  125. b = array([0.0, 0.5, 4.2, 4.2])
  126. x = cho_solve_banded((c, True), b)
  127. assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
  128. def test_lower_complex(self):
  129. # Hermitian positive definite banded matrix `a`
  130. a = array([[4.0, 1.0, 0.0, 0.0],
  131. [1.0, 4.0, 0.5, 0.0],
  132. [0.0, 0.5, 4.0, -0.2j],
  133. [0.0, 0.0, 0.2j, 4.0]])
  134. # Banded storage form of `a`.
  135. ab = array([[4.0, 4.0, 4.0, 4.0],
  136. [1.0, 0.5, 0.2j, -1.0]])
  137. c = cholesky_banded(ab, lower=True)
  138. lfac = zeros_like(a)
  139. lfac[list(range(4)), list(range(4))] = c[0]
  140. lfac[(1, 2, 3), (0, 1, 2)] = c[1, :3]
  141. assert_array_almost_equal(a, dot(lfac, lfac.conj().T))
  142. b = array([0.0, 0.5j, 3.8j, 3.8])
  143. x = cho_solve_banded((c, True), b)
  144. assert_array_almost_equal(x, [0.0, 0.0, 1.0j, 1.0])
  145. class TestOverwrite:
  146. def test_cholesky(self):
  147. assert_no_overwrite(cholesky, [(3, 3)])
  148. def test_cho_factor(self):
  149. assert_no_overwrite(cho_factor, [(3, 3)])
  150. def test_cho_solve(self):
  151. x = array([[2, -1, 0], [-1, 2, -1], [0, -1, 2]])
  152. xcho = cho_factor(x)
  153. assert_no_overwrite(lambda b: cho_solve(xcho, b), [(3,)])
  154. def test_cholesky_banded(self):
  155. assert_no_overwrite(cholesky_banded, [(2, 3)])
  156. def test_cho_solve_banded(self):
  157. x = array([[0, -1, -1], [2, 2, 2]])
  158. xcho = cholesky_banded(x)
  159. assert_no_overwrite(lambda b: cho_solve_banded((xcho, False), b),
  160. [(3,)])
  161. class TestEmptyArray:
  162. def test_cho_factor_empty_square(self):
  163. a = empty((0, 0))
  164. b = array([])
  165. c = array([[]])
  166. d = []
  167. e = [[]]
  168. x, _ = cho_factor(a)
  169. assert_array_equal(x, a)
  170. for x in ([b, c, d, e]):
  171. assert_raises(ValueError, cho_factor, x)