Fixed database typo and removed unnecessary class identifier.
This commit is contained in:
parent
00ad49a143
commit
45fb349a7d
5098 changed files with 952558 additions and 85 deletions
0
venv/Lib/site-packages/scipy/linalg/tests/__init__.py
Normal file
0
venv/Lib/site-packages/scipy/linalg/tests/__init__.py
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_15_data.npz
Normal file
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_15_data.npz
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_18_data.npz
Normal file
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_18_data.npz
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_19_data.npz
Normal file
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_19_data.npz
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_20_data.npz
Normal file
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_20_data.npz
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_6_data.npz
Normal file
BIN
venv/Lib/site-packages/scipy/linalg/tests/data/carex_6_data.npz
Normal file
Binary file not shown.
Binary file not shown.
1597
venv/Lib/site-packages/scipy/linalg/tests/test_basic.py
Normal file
1597
venv/Lib/site-packages/scipy/linalg/tests/test_basic.py
Normal file
File diff suppressed because it is too large
Load diff
1096
venv/Lib/site-packages/scipy/linalg/tests/test_blas.py
Normal file
1096
venv/Lib/site-packages/scipy/linalg/tests/test_blas.py
Normal file
File diff suppressed because it is too large
Load diff
55
venv/Lib/site-packages/scipy/linalg/tests/test_build.py
Normal file
55
venv/Lib/site-packages/scipy/linalg/tests/test_build.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
from subprocess import call, PIPE, Popen
|
||||
import sys
|
||||
import re
|
||||
|
||||
import pytest
|
||||
from numpy.testing import assert_
|
||||
from numpy.compat import asbytes
|
||||
|
||||
from scipy.linalg import _flapack as flapack
|
||||
|
||||
# XXX: this is copied from numpy trunk. Can be removed when we will depend on
|
||||
# numpy 1.3
|
||||
|
||||
|
||||
class FindDependenciesLdd:
|
||||
def __init__(self):
|
||||
self.cmd = ['ldd']
|
||||
|
||||
try:
|
||||
call(self.cmd, stdout=PIPE, stderr=PIPE)
|
||||
except OSError:
|
||||
raise RuntimeError("command %s cannot be run" % self.cmd)
|
||||
|
||||
def get_dependencies(self, file):
|
||||
p = Popen(self.cmd + [file], stdout=PIPE, stderr=PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
if not (p.returncode == 0):
|
||||
raise RuntimeError("Failed to check dependencies for %s" % file)
|
||||
|
||||
return stdout
|
||||
|
||||
def grep_dependencies(self, file, deps):
|
||||
stdout = self.get_dependencies(file)
|
||||
|
||||
rdeps = dict([(asbytes(dep), re.compile(asbytes(dep))) for dep in deps])
|
||||
founds = []
|
||||
for l in stdout.splitlines():
|
||||
for k, v in rdeps.items():
|
||||
if v.search(l):
|
||||
founds.append(k)
|
||||
|
||||
return founds
|
||||
|
||||
|
||||
class TestF77Mismatch(object):
|
||||
@pytest.mark.skipif(not(sys.platform[:5] == 'linux'),
|
||||
reason="Skipping fortran compiler mismatch on non Linux platform")
|
||||
def test_lapack(self):
|
||||
f = FindDependenciesLdd()
|
||||
deps = f.grep_dependencies(flapack.__file__,
|
||||
['libg2c', 'libgfortran'])
|
||||
assert_(not (len(deps) > 1),
|
||||
"""Both g77 and gfortran runtimes linked in scipy.linalg.flapack ! This is
|
||||
likely to cause random crashes and wrong results. See numpy INSTALL.rst.txt for
|
||||
more information.""")
|
120
venv/Lib/site-packages/scipy/linalg/tests/test_cython_blas.py
Normal file
120
venv/Lib/site-packages/scipy/linalg/tests/test_cython_blas.py
Normal file
|
@ -0,0 +1,120 @@
|
|||
import numpy as np
|
||||
from numpy.testing import (assert_allclose,
|
||||
assert_equal)
|
||||
import scipy.linalg.cython_blas as blas
|
||||
|
||||
class TestDGEMM(object):
|
||||
|
||||
def test_transposes(self):
|
||||
|
||||
a = np.arange(12, dtype='d').reshape((3, 4))[:2,:2]
|
||||
b = np.arange(1, 13, dtype='d').reshape((4, 3))[:2,:2]
|
||||
c = np.empty((2, 4))[:2,:2]
|
||||
|
||||
blas._test_dgemm(1., a, b, 0., c)
|
||||
assert_allclose(c, a.dot(b))
|
||||
|
||||
blas._test_dgemm(1., a.T, b, 0., c)
|
||||
assert_allclose(c, a.T.dot(b))
|
||||
|
||||
blas._test_dgemm(1., a, b.T, 0., c)
|
||||
assert_allclose(c, a.dot(b.T))
|
||||
|
||||
blas._test_dgemm(1., a.T, b.T, 0., c)
|
||||
assert_allclose(c, a.T.dot(b.T))
|
||||
|
||||
blas._test_dgemm(1., a, b, 0., c.T)
|
||||
assert_allclose(c, a.dot(b).T)
|
||||
|
||||
blas._test_dgemm(1., a.T, b, 0., c.T)
|
||||
assert_allclose(c, a.T.dot(b).T)
|
||||
|
||||
blas._test_dgemm(1., a, b.T, 0., c.T)
|
||||
assert_allclose(c, a.dot(b.T).T)
|
||||
|
||||
blas._test_dgemm(1., a.T, b.T, 0., c.T)
|
||||
assert_allclose(c, a.T.dot(b.T).T)
|
||||
|
||||
def test_shapes(self):
|
||||
a = np.arange(6, dtype='d').reshape((3, 2))
|
||||
b = np.arange(-6, 2, dtype='d').reshape((2, 4))
|
||||
c = np.empty((3, 4))
|
||||
|
||||
blas._test_dgemm(1., a, b, 0., c)
|
||||
assert_allclose(c, a.dot(b))
|
||||
|
||||
blas._test_dgemm(1., b.T, a.T, 0., c.T)
|
||||
assert_allclose(c, b.T.dot(a.T).T)
|
||||
|
||||
class TestWfuncPointers(object):
|
||||
""" Test the function pointers that are expected to fail on
|
||||
Mac OS X without the additional entry statement in their definitions
|
||||
in fblas_l1.pyf.src. """
|
||||
|
||||
def test_complex_args(self):
|
||||
|
||||
cx = np.array([.5 + 1.j, .25 - .375j, 12.5 - 4.j], np.complex64)
|
||||
cy = np.array([.8 + 2.j, .875 - .625j, -1. + 2.j], np.complex64)
|
||||
|
||||
assert_allclose(blas._test_cdotc(cx, cy),
|
||||
-17.6468753815+21.3718757629j, 5)
|
||||
assert_allclose(blas._test_cdotu(cx, cy),
|
||||
-6.11562538147+30.3156242371j, 5)
|
||||
|
||||
assert_equal(blas._test_icamax(cx), 3)
|
||||
|
||||
assert_allclose(blas._test_scasum(cx), 18.625, 5)
|
||||
assert_allclose(blas._test_scnrm2(cx), 13.1796483994, 5)
|
||||
|
||||
assert_allclose(blas._test_cdotc(cx[::2], cy[::2]),
|
||||
-18.1000003815+21.2000007629j, 5)
|
||||
assert_allclose(blas._test_cdotu(cx[::2], cy[::2]),
|
||||
-6.10000038147+30.7999992371j, 5)
|
||||
assert_allclose(blas._test_scasum(cx[::2]), 18., 5)
|
||||
assert_allclose(blas._test_scnrm2(cx[::2]), 13.1719398499, 5)
|
||||
|
||||
def test_double_args(self):
|
||||
|
||||
x = np.array([5., -3, -.5], np.float64)
|
||||
y = np.array([2, 1, .5], np.float64)
|
||||
|
||||
assert_allclose(blas._test_dasum(x), 8.5, 10)
|
||||
assert_allclose(blas._test_ddot(x, y), 6.75, 10)
|
||||
assert_allclose(blas._test_dnrm2(x), 5.85234975815, 10)
|
||||
|
||||
assert_allclose(blas._test_dasum(x[::2]), 5.5, 10)
|
||||
assert_allclose(blas._test_ddot(x[::2], y[::2]), 9.75, 10)
|
||||
assert_allclose(blas._test_dnrm2(x[::2]), 5.0249376297, 10)
|
||||
|
||||
assert_equal(blas._test_idamax(x), 1)
|
||||
|
||||
def test_float_args(self):
|
||||
|
||||
x = np.array([5., -3, -.5], np.float32)
|
||||
y = np.array([2, 1, .5], np.float32)
|
||||
|
||||
assert_equal(blas._test_isamax(x), 1)
|
||||
|
||||
assert_allclose(blas._test_sasum(x), 8.5, 5)
|
||||
assert_allclose(blas._test_sdot(x, y), 6.75, 5)
|
||||
assert_allclose(blas._test_snrm2(x), 5.85234975815, 5)
|
||||
|
||||
assert_allclose(blas._test_sasum(x[::2]), 5.5, 5)
|
||||
assert_allclose(blas._test_sdot(x[::2], y[::2]), 9.75, 5)
|
||||
assert_allclose(blas._test_snrm2(x[::2]), 5.0249376297, 5)
|
||||
|
||||
def test_double_complex_args(self):
|
||||
|
||||
cx = np.array([.5 + 1.j, .25 - .375j, 13. - 4.j], np.complex128)
|
||||
cy = np.array([.875 + 2.j, .875 - .625j, -1. + 2.j], np.complex128)
|
||||
|
||||
assert_equal(blas._test_izamax(cx), 3)
|
||||
|
||||
assert_allclose(blas._test_zdotc(cx, cy), -18.109375+22.296875j, 10)
|
||||
assert_allclose(blas._test_zdotu(cx, cy), -6.578125+31.390625j, 10)
|
||||
|
||||
assert_allclose(blas._test_zdotc(cx[::2], cy[::2]),
|
||||
-18.5625+22.125j, 10)
|
||||
assert_allclose(blas._test_zdotu(cx[::2], cy[::2]),
|
||||
-6.5625+31.875j, 10)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from numpy.testing import assert_allclose
|
||||
from scipy.linalg import cython_lapack as cython_lapack
|
||||
from scipy.linalg import lapack
|
||||
|
||||
|
||||
class TestLamch(object):
|
||||
|
||||
def test_slamch(self):
|
||||
for c in [b'e', b's', b'b', b'p', b'n', b'r', b'm', b'u', b'l', b'o']:
|
||||
assert_allclose(cython_lapack._test_slamch(c),
|
||||
lapack.slamch(c))
|
||||
|
||||
def test_dlamch(self):
|
||||
for c in [b'e', b's', b'b', b'p', b'n', b'r', b'm', b'u', b'l', b'o']:
|
||||
assert_allclose(cython_lapack._test_dlamch(c),
|
||||
lapack.dlamch(c))
|
||||
|
2886
venv/Lib/site-packages/scipy/linalg/tests/test_decomp.py
Normal file
2886
venv/Lib/site-packages/scipy/linalg/tests/test_decomp.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,202 @@
|
|||
from numpy.testing import assert_array_almost_equal, assert_array_equal
|
||||
from pytest import raises as assert_raises
|
||||
|
||||
from numpy import array, transpose, dot, conjugate, zeros_like, empty
|
||||
from numpy.random import random
|
||||
from scipy.linalg import cholesky, cholesky_banded, cho_solve_banded, \
|
||||
cho_factor, cho_solve
|
||||
|
||||
from scipy.linalg._testutils import assert_no_overwrite
|
||||
|
||||
|
||||
class TestCholesky(object):
|
||||
|
||||
def test_simple(self):
|
||||
a = [[8, 2, 3], [2, 9, 3], [3, 3, 6]]
|
||||
c = cholesky(a)
|
||||
assert_array_almost_equal(dot(transpose(c), c), a)
|
||||
c = transpose(c)
|
||||
a = dot(c, transpose(c))
|
||||
assert_array_almost_equal(cholesky(a, lower=1), c)
|
||||
|
||||
def test_check_finite(self):
|
||||
a = [[8, 2, 3], [2, 9, 3], [3, 3, 6]]
|
||||
c = cholesky(a, check_finite=False)
|
||||
assert_array_almost_equal(dot(transpose(c), c), a)
|
||||
c = transpose(c)
|
||||
a = dot(c, transpose(c))
|
||||
assert_array_almost_equal(cholesky(a, lower=1, check_finite=False), c)
|
||||
|
||||
def test_simple_complex(self):
|
||||
m = array([[3+1j, 3+4j, 5], [0, 2+2j, 2+7j], [0, 0, 7+4j]])
|
||||
a = dot(transpose(conjugate(m)), m)
|
||||
c = cholesky(a)
|
||||
a1 = dot(transpose(conjugate(c)), c)
|
||||
assert_array_almost_equal(a, a1)
|
||||
c = transpose(c)
|
||||
a = dot(c, transpose(conjugate(c)))
|
||||
assert_array_almost_equal(cholesky(a, lower=1), c)
|
||||
|
||||
def test_random(self):
|
||||
n = 20
|
||||
for k in range(2):
|
||||
m = random([n, n])
|
||||
for i in range(n):
|
||||
m[i, i] = 20*(.1+m[i, i])
|
||||
a = dot(transpose(m), m)
|
||||
c = cholesky(a)
|
||||
a1 = dot(transpose(c), c)
|
||||
assert_array_almost_equal(a, a1)
|
||||
c = transpose(c)
|
||||
a = dot(c, transpose(c))
|
||||
assert_array_almost_equal(cholesky(a, lower=1), c)
|
||||
|
||||
def test_random_complex(self):
|
||||
n = 20
|
||||
for k in range(2):
|
||||
m = random([n, n])+1j*random([n, n])
|
||||
for i in range(n):
|
||||
m[i, i] = 20*(.1+abs(m[i, i]))
|
||||
a = dot(transpose(conjugate(m)), m)
|
||||
c = cholesky(a)
|
||||
a1 = dot(transpose(conjugate(c)), c)
|
||||
assert_array_almost_equal(a, a1)
|
||||
c = transpose(c)
|
||||
a = dot(c, transpose(conjugate(c)))
|
||||
assert_array_almost_equal(cholesky(a, lower=1), c)
|
||||
|
||||
|
||||
class TestCholeskyBanded(object):
|
||||
"""Tests for cholesky_banded() and cho_solve_banded."""
|
||||
|
||||
def test_check_finite(self):
|
||||
# Symmetric positive definite banded matrix `a`
|
||||
a = array([[4.0, 1.0, 0.0, 0.0],
|
||||
[1.0, 4.0, 0.5, 0.0],
|
||||
[0.0, 0.5, 4.0, 0.2],
|
||||
[0.0, 0.0, 0.2, 4.0]])
|
||||
# Banded storage form of `a`.
|
||||
ab = array([[-1.0, 1.0, 0.5, 0.2],
|
||||
[4.0, 4.0, 4.0, 4.0]])
|
||||
c = cholesky_banded(ab, lower=False, check_finite=False)
|
||||
ufac = zeros_like(a)
|
||||
ufac[list(range(4)), list(range(4))] = c[-1]
|
||||
ufac[(0, 1, 2), (1, 2, 3)] = c[0, 1:]
|
||||
assert_array_almost_equal(a, dot(ufac.T, ufac))
|
||||
|
||||
b = array([0.0, 0.5, 4.2, 4.2])
|
||||
x = cho_solve_banded((c, False), b, check_finite=False)
|
||||
assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
|
||||
|
||||
def test_upper_real(self):
|
||||
# Symmetric positive definite banded matrix `a`
|
||||
a = array([[4.0, 1.0, 0.0, 0.0],
|
||||
[1.0, 4.0, 0.5, 0.0],
|
||||
[0.0, 0.5, 4.0, 0.2],
|
||||
[0.0, 0.0, 0.2, 4.0]])
|
||||
# Banded storage form of `a`.
|
||||
ab = array([[-1.0, 1.0, 0.5, 0.2],
|
||||
[4.0, 4.0, 4.0, 4.0]])
|
||||
c = cholesky_banded(ab, lower=False)
|
||||
ufac = zeros_like(a)
|
||||
ufac[list(range(4)), list(range(4))] = c[-1]
|
||||
ufac[(0, 1, 2), (1, 2, 3)] = c[0, 1:]
|
||||
assert_array_almost_equal(a, dot(ufac.T, ufac))
|
||||
|
||||
b = array([0.0, 0.5, 4.2, 4.2])
|
||||
x = cho_solve_banded((c, False), b)
|
||||
assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
|
||||
|
||||
def test_upper_complex(self):
|
||||
# Hermitian positive definite banded matrix `a`
|
||||
a = array([[4.0, 1.0, 0.0, 0.0],
|
||||
[1.0, 4.0, 0.5, 0.0],
|
||||
[0.0, 0.5, 4.0, -0.2j],
|
||||
[0.0, 0.0, 0.2j, 4.0]])
|
||||
# Banded storage form of `a`.
|
||||
ab = array([[-1.0, 1.0, 0.5, -0.2j],
|
||||
[4.0, 4.0, 4.0, 4.0]])
|
||||
c = cholesky_banded(ab, lower=False)
|
||||
ufac = zeros_like(a)
|
||||
ufac[list(range(4)), list(range(4))] = c[-1]
|
||||
ufac[(0, 1, 2), (1, 2, 3)] = c[0, 1:]
|
||||
assert_array_almost_equal(a, dot(ufac.conj().T, ufac))
|
||||
|
||||
b = array([0.0, 0.5, 4.0-0.2j, 0.2j + 4.0])
|
||||
x = cho_solve_banded((c, False), b)
|
||||
assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
|
||||
|
||||
def test_lower_real(self):
|
||||
# Symmetric positive definite banded matrix `a`
|
||||
a = array([[4.0, 1.0, 0.0, 0.0],
|
||||
[1.0, 4.0, 0.5, 0.0],
|
||||
[0.0, 0.5, 4.0, 0.2],
|
||||
[0.0, 0.0, 0.2, 4.0]])
|
||||
# Banded storage form of `a`.
|
||||
ab = array([[4.0, 4.0, 4.0, 4.0],
|
||||
[1.0, 0.5, 0.2, -1.0]])
|
||||
c = cholesky_banded(ab, lower=True)
|
||||
lfac = zeros_like(a)
|
||||
lfac[list(range(4)), list(range(4))] = c[0]
|
||||
lfac[(1, 2, 3), (0, 1, 2)] = c[1, :3]
|
||||
assert_array_almost_equal(a, dot(lfac, lfac.T))
|
||||
|
||||
b = array([0.0, 0.5, 4.2, 4.2])
|
||||
x = cho_solve_banded((c, True), b)
|
||||
assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
|
||||
|
||||
def test_lower_complex(self):
|
||||
# Hermitian positive definite banded matrix `a`
|
||||
a = array([[4.0, 1.0, 0.0, 0.0],
|
||||
[1.0, 4.0, 0.5, 0.0],
|
||||
[0.0, 0.5, 4.0, -0.2j],
|
||||
[0.0, 0.0, 0.2j, 4.0]])
|
||||
# Banded storage form of `a`.
|
||||
ab = array([[4.0, 4.0, 4.0, 4.0],
|
||||
[1.0, 0.5, 0.2j, -1.0]])
|
||||
c = cholesky_banded(ab, lower=True)
|
||||
lfac = zeros_like(a)
|
||||
lfac[list(range(4)), list(range(4))] = c[0]
|
||||
lfac[(1, 2, 3), (0, 1, 2)] = c[1, :3]
|
||||
assert_array_almost_equal(a, dot(lfac, lfac.conj().T))
|
||||
|
||||
b = array([0.0, 0.5j, 3.8j, 3.8])
|
||||
x = cho_solve_banded((c, True), b)
|
||||
assert_array_almost_equal(x, [0.0, 0.0, 1.0j, 1.0])
|
||||
|
||||
|
||||
class TestOverwrite(object):
|
||||
def test_cholesky(self):
|
||||
assert_no_overwrite(cholesky, [(3, 3)])
|
||||
|
||||
def test_cho_factor(self):
|
||||
assert_no_overwrite(cho_factor, [(3, 3)])
|
||||
|
||||
def test_cho_solve(self):
|
||||
x = array([[2, -1, 0], [-1, 2, -1], [0, -1, 2]])
|
||||
xcho = cho_factor(x)
|
||||
assert_no_overwrite(lambda b: cho_solve(xcho, b), [(3,)])
|
||||
|
||||
def test_cholesky_banded(self):
|
||||
assert_no_overwrite(cholesky_banded, [(2, 3)])
|
||||
|
||||
def test_cho_solve_banded(self):
|
||||
x = array([[0, -1, -1], [2, 2, 2]])
|
||||
xcho = cholesky_banded(x)
|
||||
assert_no_overwrite(lambda b: cho_solve_banded((xcho, False), b),
|
||||
[(3,)])
|
||||
|
||||
|
||||
class TestEmptyArray(object):
|
||||
def test_cho_factor_empty_square(self):
|
||||
a = empty((0, 0))
|
||||
b = array([])
|
||||
c = array([[]])
|
||||
d = []
|
||||
e = [[]]
|
||||
|
||||
x, _ = cho_factor(a)
|
||||
assert_array_equal(x, a)
|
||||
|
||||
for x in ([b, c, d, e]):
|
||||
assert_raises(ValueError, cho_factor, x)
|
154
venv/Lib/site-packages/scipy/linalg/tests/test_decomp_cossin.py
Normal file
154
venv/Lib/site-packages/scipy/linalg/tests/test_decomp_cossin.py
Normal file
|
@ -0,0 +1,154 @@
|
|||
import pytest
|
||||
import numpy as np
|
||||
from numpy.random import seed
|
||||
from numpy.testing import assert_allclose
|
||||
|
||||
from scipy.linalg.lapack import _compute_lwork
|
||||
from scipy.stats import ortho_group, unitary_group
|
||||
from scipy.linalg import cossin, get_lapack_funcs
|
||||
|
||||
REAL_DTYPES = (np.float32, np.float64)
|
||||
COMPLEX_DTYPES = (np.complex64, np.complex128)
|
||||
DTYPES = REAL_DTYPES + COMPLEX_DTYPES
|
||||
|
||||
|
||||
@pytest.mark.parametrize('dtype_', DTYPES)
|
||||
@pytest.mark.parametrize('m, p, q',
|
||||
[
|
||||
(2, 1, 1),
|
||||
(3, 2, 1),
|
||||
(3, 1, 2),
|
||||
(4, 2, 2),
|
||||
(4, 1, 2),
|
||||
(40, 12, 20),
|
||||
(40, 30, 1),
|
||||
(40, 1, 30),
|
||||
(100, 50, 1),
|
||||
(100, 50, 50),
|
||||
])
|
||||
@pytest.mark.parametrize('swap_sign', [True, False])
|
||||
def test_cossin(dtype_, m, p, q, swap_sign):
|
||||
seed(1234)
|
||||
if dtype_ in COMPLEX_DTYPES:
|
||||
x = np.array(unitary_group.rvs(m), dtype=dtype_)
|
||||
else:
|
||||
x = np.array(ortho_group.rvs(m), dtype=dtype_)
|
||||
|
||||
u, cs, vh = cossin(x, p, q,
|
||||
swap_sign=swap_sign)
|
||||
assert_allclose(x, u @ cs @ vh, rtol=0., atol=m*1e3*np.finfo(dtype_).eps)
|
||||
assert u.dtype == dtype_
|
||||
# Test for float32 or float 64
|
||||
assert cs.dtype == np.real(u).dtype
|
||||
assert vh.dtype == dtype_
|
||||
|
||||
u, cs, vh = cossin([x[:p, :q], x[:p, q:], x[p:, :q], x[p:, q:]],
|
||||
swap_sign=swap_sign)
|
||||
assert_allclose(x, u @ cs @ vh, rtol=0., atol=m*1e3*np.finfo(dtype_).eps)
|
||||
assert u.dtype == dtype_
|
||||
assert cs.dtype == np.real(u).dtype
|
||||
assert vh.dtype == dtype_
|
||||
|
||||
_, cs2, vh2 = cossin(x, p, q,
|
||||
compute_u=False,
|
||||
swap_sign=swap_sign)
|
||||
assert_allclose(cs, cs2, rtol=0., atol=10*np.finfo(dtype_).eps)
|
||||
assert_allclose(vh, vh2, rtol=0., atol=10*np.finfo(dtype_).eps)
|
||||
|
||||
u2, cs2, _ = cossin(x, p, q,
|
||||
compute_vh=False,
|
||||
swap_sign=swap_sign)
|
||||
assert_allclose(u, u2, rtol=0., atol=10*np.finfo(dtype_).eps)
|
||||
assert_allclose(cs, cs2, rtol=0., atol=10*np.finfo(dtype_).eps)
|
||||
|
||||
_, cs2, _ = cossin(x, p, q,
|
||||
compute_u=False,
|
||||
compute_vh=False,
|
||||
swap_sign=swap_sign)
|
||||
assert_allclose(cs, cs2, rtol=0., atol=10*np.finfo(dtype_).eps)
|
||||
|
||||
|
||||
def test_cossin_mixed_types():
|
||||
seed(1234)
|
||||
x = np.array(ortho_group.rvs(4), dtype=np.float64)
|
||||
u, cs, vh = cossin([x[:2, :2],
|
||||
np.array(x[:2, 2:], dtype=np.complex128),
|
||||
x[2:, :2],
|
||||
x[2:, 2:]])
|
||||
|
||||
assert u.dtype == np.complex128
|
||||
assert cs.dtype == np.float64
|
||||
assert vh.dtype == np.complex128
|
||||
assert_allclose(x, u @ cs @ vh, rtol=0.,
|
||||
atol=1e4 * np.finfo(np.complex128).eps)
|
||||
|
||||
|
||||
def test_cossin_error_incorrect_subblocks():
|
||||
with pytest.raises(ValueError, match="be due to missing p, q arguments."):
|
||||
cossin(([1, 2], [3, 4, 5], [6, 7], [8, 9, 10]))
|
||||
|
||||
|
||||
def test_cossin_error_empty_subblocks():
|
||||
with pytest.raises(ValueError, match="x11.*empty"):
|
||||
cossin(([], [], [], []))
|
||||
with pytest.raises(ValueError, match="x12.*empty"):
|
||||
cossin(([1, 2], [], [6, 7], [8, 9, 10]))
|
||||
with pytest.raises(ValueError, match="x21.*empty"):
|
||||
cossin(([1, 2], [3, 4, 5], [], [8, 9, 10]))
|
||||
with pytest.raises(ValueError, match="x22.*empty"):
|
||||
cossin(([1, 2], [3, 4, 5], [2], []))
|
||||
|
||||
|
||||
def test_cossin_error_missing_partitioning():
|
||||
with pytest.raises(ValueError, match=".*exactly four arrays.* got 2"):
|
||||
cossin(unitary_group.rvs(2))
|
||||
|
||||
with pytest.raises(ValueError, match=".*might be due to missing p, q"):
|
||||
cossin(unitary_group.rvs(4))
|
||||
|
||||
|
||||
def test_cossin_error_non_iterable():
|
||||
with pytest.raises(ValueError, match="containing the subblocks of X"):
|
||||
cossin(12j)
|
||||
|
||||
|
||||
def test_cossin_error_non_square():
|
||||
with pytest.raises(ValueError, match="only supports square"):
|
||||
cossin(np.array([[1, 2]]), 1, 1)
|
||||
|
||||
def test_cossin_error_partitioning():
|
||||
x = np.array(ortho_group.rvs(4), dtype=np.float64)
|
||||
with pytest.raises(ValueError, match="invalid p=0.*0<p<4.*"):
|
||||
cossin(x, 0, 1)
|
||||
with pytest.raises(ValueError, match="invalid p=4.*0<p<4.*"):
|
||||
cossin(x, 4, 1)
|
||||
with pytest.raises(ValueError, match="invalid q=-2.*0<q<4.*"):
|
||||
cossin(x, 1, -2)
|
||||
with pytest.raises(ValueError, match="invalid q=5.*0<q<4.*"):
|
||||
cossin(x, 1, 5)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dtype_", DTYPES)
|
||||
def test_cossin_separate(dtype_):
|
||||
m, p, q = 250, 80, 170
|
||||
|
||||
pfx = 'or' if dtype_ in REAL_DTYPES else 'un'
|
||||
X = ortho_group.rvs(m) if pfx == 'or' else unitary_group.rvs(m)
|
||||
X = np.array(X, dtype=dtype_)
|
||||
|
||||
drv, dlw = get_lapack_funcs((pfx + 'csd', pfx + 'csd_lwork'),[X])
|
||||
lwval = _compute_lwork(dlw, m, p, q)
|
||||
lwvals = {'lwork': lwval} if pfx == 'or' else dict(zip(['lwork',
|
||||
'lrwork'],
|
||||
lwval))
|
||||
|
||||
*_, theta, u1, u2, v1t, v2t, _ = \
|
||||
drv(X[:p, :q], X[:p, q:], X[p:, :q], X[p:, q:], **lwvals)
|
||||
|
||||
(u1_2, u2_2), theta2, (v1t_2, v2t_2) = cossin(X, p, q, separate=True)
|
||||
|
||||
assert_allclose(u1_2, u1, rtol=0., atol=10*np.finfo(dtype_).eps)
|
||||
assert_allclose(u2_2, u2, rtol=0., atol=10*np.finfo(dtype_).eps)
|
||||
assert_allclose(v1t_2, v1t, rtol=0., atol=10*np.finfo(dtype_).eps)
|
||||
assert_allclose(v2t_2, v2t, rtol=0., atol=10*np.finfo(dtype_).eps)
|
||||
assert_allclose(theta2, theta, rtol=0., atol=10*np.finfo(dtype_).eps)
|
135
venv/Lib/site-packages/scipy/linalg/tests/test_decomp_ldl.py
Normal file
135
venv/Lib/site-packages/scipy/linalg/tests/test_decomp_ldl.py
Normal file
|
@ -0,0 +1,135 @@
|
|||
import itertools
|
||||
from numpy.testing import assert_array_almost_equal, assert_allclose, assert_
|
||||
from numpy import (array, eye, zeros, empty_like, empty, tril_indices_from,
|
||||
tril, triu_indices_from, spacing, float32, float64,
|
||||
complex64, complex128)
|
||||
from numpy.random import rand, randint, seed
|
||||
from scipy.linalg import ldl
|
||||
from pytest import raises as assert_raises, warns
|
||||
from numpy import ComplexWarning
|
||||
|
||||
|
||||
def test_args():
|
||||
A = eye(3)
|
||||
# Nonsquare array
|
||||
assert_raises(ValueError, ldl, A[:, :2])
|
||||
# Complex matrix with imaginary diagonal entries with "hermitian=True"
|
||||
with warns(ComplexWarning):
|
||||
ldl(A*1j)
|
||||
|
||||
|
||||
def test_empty_array():
|
||||
a = empty((0, 0), dtype=complex)
|
||||
l, d, p = ldl(empty((0, 0)))
|
||||
assert_array_almost_equal(l, empty_like(a))
|
||||
assert_array_almost_equal(d, empty_like(a))
|
||||
assert_array_almost_equal(p, array([], dtype=int))
|
||||
|
||||
|
||||
def test_simple():
|
||||
a = array([[-0.39-0.71j, 5.14-0.64j, -7.86-2.96j, 3.80+0.92j],
|
||||
[5.14-0.64j, 8.86+1.81j, -3.52+0.58j, 5.32-1.59j],
|
||||
[-7.86-2.96j, -3.52+0.58j, -2.83-0.03j, -1.54-2.86j],
|
||||
[3.80+0.92j, 5.32-1.59j, -1.54-2.86j, -0.56+0.12j]])
|
||||
b = array([[5., 10, 1, 18],
|
||||
[10., 2, 11, 1],
|
||||
[1., 11, 19, 9],
|
||||
[18., 1, 9, 0]])
|
||||
c = array([[52., 97, 112, 107, 50],
|
||||
[97., 114, 89, 98, 13],
|
||||
[112., 89, 64, 33, 6],
|
||||
[107., 98, 33, 60, 73],
|
||||
[50., 13, 6, 73, 77]])
|
||||
|
||||
d = array([[2., 2, -4, 0, 4],
|
||||
[2., -2, -2, 10, -8],
|
||||
[-4., -2, 6, -8, -4],
|
||||
[0., 10, -8, 6, -6],
|
||||
[4., -8, -4, -6, 10]])
|
||||
e = array([[-1.36+0.00j, 0+0j, 0+0j, 0+0j],
|
||||
[1.58-0.90j, -8.87+0j, 0+0j, 0+0j],
|
||||
[2.21+0.21j, -1.84+0.03j, -4.63+0j, 0+0j],
|
||||
[3.91-1.50j, -1.78-1.18j, 0.11-0.11j, -1.84+0.00j]])
|
||||
for x in (b, c, d):
|
||||
l, d, p = ldl(x)
|
||||
assert_allclose(l.dot(d).dot(l.T), x, atol=spacing(1000.), rtol=0)
|
||||
|
||||
u, d, p = ldl(x, lower=False)
|
||||
assert_allclose(u.dot(d).dot(u.T), x, atol=spacing(1000.), rtol=0)
|
||||
|
||||
l, d, p = ldl(a, hermitian=False)
|
||||
assert_allclose(l.dot(d).dot(l.T), a, atol=spacing(1000.), rtol=0)
|
||||
|
||||
u, d, p = ldl(a, lower=False, hermitian=False)
|
||||
assert_allclose(u.dot(d).dot(u.T), a, atol=spacing(1000.), rtol=0)
|
||||
|
||||
# Use upper part for the computation and use the lower part for comparison
|
||||
l, d, p = ldl(e.conj().T, lower=0)
|
||||
assert_allclose(tril(l.dot(d).dot(l.conj().T)-e), zeros((4, 4)),
|
||||
atol=spacing(1000.), rtol=0)
|
||||
|
||||
|
||||
def test_permutations():
|
||||
seed(1234)
|
||||
for _ in range(10):
|
||||
n = randint(1, 100)
|
||||
# Random real/complex array
|
||||
x = rand(n, n) if randint(2) else rand(n, n) + rand(n, n)*1j
|
||||
x = x + x.conj().T
|
||||
x += eye(n)*randint(5, 1e6)
|
||||
l_ind = tril_indices_from(x, k=-1)
|
||||
u_ind = triu_indices_from(x, k=1)
|
||||
|
||||
# Test whether permutations lead to a triangular array
|
||||
u, d, p = ldl(x, lower=0)
|
||||
# lower part should be zero
|
||||
assert_(not any(u[p, :][l_ind]), 'Spin {} failed'.format(_))
|
||||
|
||||
l, d, p = ldl(x, lower=1)
|
||||
# upper part should be zero
|
||||
assert_(not any(l[p, :][u_ind]), 'Spin {} failed'.format(_))
|
||||
|
||||
|
||||
def test_ldl_type_size_combinations():
|
||||
seed(1234)
|
||||
sizes = [30, 750]
|
||||
real_dtypes = [float32, float64]
|
||||
complex_dtypes = [complex64, complex128]
|
||||
|
||||
for n, dtype in itertools.product(sizes, real_dtypes):
|
||||
msg = ("Failed for size: {}, dtype: {}".format(n, dtype))
|
||||
|
||||
x = rand(n, n).astype(dtype)
|
||||
x = x + x.T
|
||||
x += eye(n, dtype=dtype)*dtype(randint(5, 1e6))
|
||||
|
||||
l, d1, p = ldl(x)
|
||||
u, d2, p = ldl(x, lower=0)
|
||||
rtol = 1e-4 if dtype is float32 else 1e-10
|
||||
assert_allclose(l.dot(d1).dot(l.T), x, rtol=rtol, err_msg=msg)
|
||||
assert_allclose(u.dot(d2).dot(u.T), x, rtol=rtol, err_msg=msg)
|
||||
|
||||
for n, dtype in itertools.product(sizes, complex_dtypes):
|
||||
msg1 = ("Her failed for size: {}, dtype: {}".format(n, dtype))
|
||||
msg2 = ("Sym failed for size: {}, dtype: {}".format(n, dtype))
|
||||
|
||||
# Complex hermitian upper/lower
|
||||
x = (rand(n, n)+1j*rand(n, n)).astype(dtype)
|
||||
x = x+x.conj().T
|
||||
x += eye(n, dtype=dtype)*dtype(randint(5, 1e6))
|
||||
|
||||
l, d1, p = ldl(x)
|
||||
u, d2, p = ldl(x, lower=0)
|
||||
rtol = 1e-4 if dtype is complex64 else 1e-10
|
||||
assert_allclose(l.dot(d1).dot(l.conj().T), x, rtol=rtol, err_msg=msg1)
|
||||
assert_allclose(u.dot(d2).dot(u.conj().T), x, rtol=rtol, err_msg=msg1)
|
||||
|
||||
# Complex symmetric upper/lower
|
||||
x = (rand(n, n)+1j*rand(n, n)).astype(dtype)
|
||||
x = x+x.T
|
||||
x += eye(n, dtype=dtype)*dtype(randint(5, 1e6))
|
||||
|
||||
l, d1, p = ldl(x, hermitian=0)
|
||||
u, d2, p = ldl(x, lower=0, hermitian=0)
|
||||
assert_allclose(l.dot(d1).dot(l.T), x, rtol=rtol, err_msg=msg2)
|
||||
assert_allclose(u.dot(d2).dot(u.T), x, rtol=rtol, err_msg=msg2)
|
|
@ -0,0 +1,90 @@
|
|||
import numpy as np
|
||||
from numpy.linalg import norm
|
||||
from numpy.testing import (assert_, assert_allclose, assert_equal)
|
||||
from scipy.linalg import polar, eigh
|
||||
|
||||
|
||||
diag2 = np.array([[2, 0], [0, 3]])
|
||||
a13 = np.array([[1, 2, 2]])
|
||||
|
||||
precomputed_cases = [
|
||||
[[[0]], 'right', [[1]], [[0]]],
|
||||
[[[0]], 'left', [[1]], [[0]]],
|
||||
[[[9]], 'right', [[1]], [[9]]],
|
||||
[[[9]], 'left', [[1]], [[9]]],
|
||||
[diag2, 'right', np.eye(2), diag2],
|
||||
[diag2, 'left', np.eye(2), diag2],
|
||||
[a13, 'right', a13/norm(a13[0]), a13.T.dot(a13)/norm(a13[0])],
|
||||
]
|
||||
|
||||
verify_cases = [
|
||||
[[1, 2], [3, 4]],
|
||||
[[1, 2, 3]],
|
||||
[[1], [2], [3]],
|
||||
[[1, 2, 3], [3, 4, 0]],
|
||||
[[1, 2], [3, 4], [5, 5]],
|
||||
[[1, 2], [3, 4+5j]],
|
||||
[[1, 2, 3j]],
|
||||
[[1], [2], [3j]],
|
||||
[[1, 2, 3+2j], [3, 4-1j, -4j]],
|
||||
[[1, 2], [3-2j, 4+0.5j], [5, 5]],
|
||||
[[10000, 10, 1], [-1, 2, 3j], [0, 1, 2]],
|
||||
]
|
||||
|
||||
|
||||
def check_precomputed_polar(a, side, expected_u, expected_p):
|
||||
# Compare the result of the polar decomposition to a
|
||||
# precomputed result.
|
||||
u, p = polar(a, side=side)
|
||||
assert_allclose(u, expected_u, atol=1e-15)
|
||||
assert_allclose(p, expected_p, atol=1e-15)
|
||||
|
||||
|
||||
def verify_polar(a):
|
||||
# Compute the polar decomposition, and then verify that
|
||||
# the result has all the expected properties.
|
||||
product_atol = np.sqrt(np.finfo(float).eps)
|
||||
|
||||
aa = np.asarray(a)
|
||||
m, n = aa.shape
|
||||
|
||||
u, p = polar(a, side='right')
|
||||
assert_equal(u.shape, (m, n))
|
||||
assert_equal(p.shape, (n, n))
|
||||
# a = up
|
||||
assert_allclose(u.dot(p), a, atol=product_atol)
|
||||
if m >= n:
|
||||
assert_allclose(u.conj().T.dot(u), np.eye(n), atol=1e-15)
|
||||
else:
|
||||
assert_allclose(u.dot(u.conj().T), np.eye(m), atol=1e-15)
|
||||
# p is Hermitian positive semidefinite.
|
||||
assert_allclose(p.conj().T, p)
|
||||
evals = eigh(p, eigvals_only=True)
|
||||
nonzero_evals = evals[abs(evals) > 1e-14]
|
||||
assert_((nonzero_evals >= 0).all())
|
||||
|
||||
u, p = polar(a, side='left')
|
||||
assert_equal(u.shape, (m, n))
|
||||
assert_equal(p.shape, (m, m))
|
||||
# a = pu
|
||||
assert_allclose(p.dot(u), a, atol=product_atol)
|
||||
if m >= n:
|
||||
assert_allclose(u.conj().T.dot(u), np.eye(n), atol=1e-15)
|
||||
else:
|
||||
assert_allclose(u.dot(u.conj().T), np.eye(m), atol=1e-15)
|
||||
# p is Hermitian positive semidefinite.
|
||||
assert_allclose(p.conj().T, p)
|
||||
evals = eigh(p, eigvals_only=True)
|
||||
nonzero_evals = evals[abs(evals) > 1e-14]
|
||||
assert_((nonzero_evals >= 0).all())
|
||||
|
||||
|
||||
def test_precomputed_cases():
|
||||
for a, side, expected_u, expected_p in precomputed_cases:
|
||||
check_precomputed_polar(a, side, expected_u, expected_p)
|
||||
|
||||
|
||||
def test_verify_cases():
|
||||
for a in verify_cases:
|
||||
verify_polar(a)
|
||||
|
1697
venv/Lib/site-packages/scipy/linalg/tests/test_decomp_update.py
Normal file
1697
venv/Lib/site-packages/scipy/linalg/tests/test_decomp_update.py
Normal file
File diff suppressed because it is too large
Load diff
607
venv/Lib/site-packages/scipy/linalg/tests/test_fblas.py
Normal file
607
venv/Lib/site-packages/scipy/linalg/tests/test_fblas.py
Normal file
|
@ -0,0 +1,607 @@
|
|||
# Test interfaces to fortran blas.
|
||||
#
|
||||
# The tests are more of interface than they are of the underlying blas.
|
||||
# Only very small matrices checked -- N=3 or so.
|
||||
#
|
||||
# !! Complex calculations really aren't checked that carefully.
|
||||
# !! Only real valued complex numbers are used in tests.
|
||||
|
||||
from numpy import float32, float64, complex64, complex128, arange, array, \
|
||||
zeros, shape, transpose, newaxis, common_type, conjugate
|
||||
|
||||
from scipy.linalg import _fblas as fblas
|
||||
|
||||
from numpy.testing import assert_array_equal, \
|
||||
assert_allclose, assert_array_almost_equal, assert_
|
||||
|
||||
import pytest
|
||||
|
||||
# decimal accuracy to require between Python and LAPACK/BLAS calculations
|
||||
accuracy = 5
|
||||
|
||||
# Since numpy.dot likely uses the same blas, use this routine
|
||||
# to check.
|
||||
|
||||
|
||||
def matrixmultiply(a, b):
|
||||
if len(b.shape) == 1:
|
||||
b_is_vector = True
|
||||
b = b[:, newaxis]
|
||||
else:
|
||||
b_is_vector = False
|
||||
assert_(a.shape[1] == b.shape[0])
|
||||
c = zeros((a.shape[0], b.shape[1]), common_type(a, b))
|
||||
for i in range(a.shape[0]):
|
||||
for j in range(b.shape[1]):
|
||||
s = 0
|
||||
for k in range(a.shape[1]):
|
||||
s += a[i, k] * b[k, j]
|
||||
c[i, j] = s
|
||||
if b_is_vector:
|
||||
c = c.reshape((a.shape[0],))
|
||||
return c
|
||||
|
||||
##################################################
|
||||
# Test blas ?axpy
|
||||
|
||||
|
||||
class BaseAxpy(object):
|
||||
''' Mixin class for axpy tests '''
|
||||
|
||||
def test_default_a(self):
|
||||
x = arange(3., dtype=self.dtype)
|
||||
y = arange(3., dtype=x.dtype)
|
||||
real_y = x*1.+y
|
||||
y = self.blas_func(x, y)
|
||||
assert_array_equal(real_y, y)
|
||||
|
||||
def test_simple(self):
|
||||
x = arange(3., dtype=self.dtype)
|
||||
y = arange(3., dtype=x.dtype)
|
||||
real_y = x*3.+y
|
||||
y = self.blas_func(x, y, a=3.)
|
||||
assert_array_equal(real_y, y)
|
||||
|
||||
def test_x_stride(self):
|
||||
x = arange(6., dtype=self.dtype)
|
||||
y = zeros(3, x.dtype)
|
||||
y = arange(3., dtype=x.dtype)
|
||||
real_y = x[::2]*3.+y
|
||||
y = self.blas_func(x, y, a=3., n=3, incx=2)
|
||||
assert_array_equal(real_y, y)
|
||||
|
||||
def test_y_stride(self):
|
||||
x = arange(3., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
real_y = x*3.+y[::2]
|
||||
y = self.blas_func(x, y, a=3., n=3, incy=2)
|
||||
assert_array_equal(real_y, y[::2])
|
||||
|
||||
def test_x_and_y_stride(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
real_y = x[::4]*3.+y[::2]
|
||||
y = self.blas_func(x, y, a=3., n=3, incx=4, incy=2)
|
||||
assert_array_equal(real_y, y[::2])
|
||||
|
||||
def test_x_bad_size(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
with pytest.raises(Exception, match='failed for 1st keyword'):
|
||||
self.blas_func(x, y, n=4, incx=5)
|
||||
|
||||
def test_y_bad_size(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
with pytest.raises(Exception, match='failed for 1st keyword'):
|
||||
self.blas_func(x, y, n=3, incy=5)
|
||||
|
||||
|
||||
try:
|
||||
class TestSaxpy(BaseAxpy):
|
||||
blas_func = fblas.saxpy
|
||||
dtype = float32
|
||||
except AttributeError:
|
||||
class TestSaxpy:
|
||||
pass
|
||||
|
||||
|
||||
class TestDaxpy(BaseAxpy):
|
||||
blas_func = fblas.daxpy
|
||||
dtype = float64
|
||||
|
||||
|
||||
try:
|
||||
class TestCaxpy(BaseAxpy):
|
||||
blas_func = fblas.caxpy
|
||||
dtype = complex64
|
||||
except AttributeError:
|
||||
class TestCaxpy:
|
||||
pass
|
||||
|
||||
|
||||
class TestZaxpy(BaseAxpy):
|
||||
blas_func = fblas.zaxpy
|
||||
dtype = complex128
|
||||
|
||||
|
||||
##################################################
|
||||
# Test blas ?scal
|
||||
|
||||
class BaseScal(object):
|
||||
''' Mixin class for scal testing '''
|
||||
|
||||
def test_simple(self):
|
||||
x = arange(3., dtype=self.dtype)
|
||||
real_x = x*3.
|
||||
x = self.blas_func(3., x)
|
||||
assert_array_equal(real_x, x)
|
||||
|
||||
def test_x_stride(self):
|
||||
x = arange(6., dtype=self.dtype)
|
||||
real_x = x.copy()
|
||||
real_x[::2] = x[::2]*array(3., self.dtype)
|
||||
x = self.blas_func(3., x, n=3, incx=2)
|
||||
assert_array_equal(real_x, x)
|
||||
|
||||
def test_x_bad_size(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
with pytest.raises(Exception, match='failed for 1st keyword'):
|
||||
self.blas_func(2., x, n=4, incx=5)
|
||||
|
||||
|
||||
try:
|
||||
class TestSscal(BaseScal):
|
||||
blas_func = fblas.sscal
|
||||
dtype = float32
|
||||
except AttributeError:
|
||||
class TestSscal:
|
||||
pass
|
||||
|
||||
|
||||
class TestDscal(BaseScal):
|
||||
blas_func = fblas.dscal
|
||||
dtype = float64
|
||||
|
||||
|
||||
try:
|
||||
class TestCscal(BaseScal):
|
||||
blas_func = fblas.cscal
|
||||
dtype = complex64
|
||||
except AttributeError:
|
||||
class TestCscal:
|
||||
pass
|
||||
|
||||
|
||||
class TestZscal(BaseScal):
|
||||
blas_func = fblas.zscal
|
||||
dtype = complex128
|
||||
|
||||
|
||||
##################################################
|
||||
# Test blas ?copy
|
||||
|
||||
class BaseCopy(object):
|
||||
''' Mixin class for copy testing '''
|
||||
|
||||
def test_simple(self):
|
||||
x = arange(3., dtype=self.dtype)
|
||||
y = zeros(shape(x), x.dtype)
|
||||
y = self.blas_func(x, y)
|
||||
assert_array_equal(x, y)
|
||||
|
||||
def test_x_stride(self):
|
||||
x = arange(6., dtype=self.dtype)
|
||||
y = zeros(3, x.dtype)
|
||||
y = self.blas_func(x, y, n=3, incx=2)
|
||||
assert_array_equal(x[::2], y)
|
||||
|
||||
def test_y_stride(self):
|
||||
x = arange(3., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
y = self.blas_func(x, y, n=3, incy=2)
|
||||
assert_array_equal(x, y[::2])
|
||||
|
||||
def test_x_and_y_stride(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
y = self.blas_func(x, y, n=3, incx=4, incy=2)
|
||||
assert_array_equal(x[::4], y[::2])
|
||||
|
||||
def test_x_bad_size(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
with pytest.raises(Exception, match='failed for 1st keyword'):
|
||||
self.blas_func(x, y, n=4, incx=5)
|
||||
|
||||
def test_y_bad_size(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
with pytest.raises(Exception, match='failed for 1st keyword'):
|
||||
self.blas_func(x, y, n=3, incy=5)
|
||||
|
||||
# def test_y_bad_type(self):
|
||||
## Hmmm. Should this work? What should be the output.
|
||||
# x = arange(3.,dtype=self.dtype)
|
||||
# y = zeros(shape(x))
|
||||
# self.blas_func(x,y)
|
||||
# assert_array_equal(x,y)
|
||||
|
||||
|
||||
try:
|
||||
class TestScopy(BaseCopy):
|
||||
blas_func = fblas.scopy
|
||||
dtype = float32
|
||||
except AttributeError:
|
||||
class TestScopy:
|
||||
pass
|
||||
|
||||
|
||||
class TestDcopy(BaseCopy):
|
||||
blas_func = fblas.dcopy
|
||||
dtype = float64
|
||||
|
||||
|
||||
try:
|
||||
class TestCcopy(BaseCopy):
|
||||
blas_func = fblas.ccopy
|
||||
dtype = complex64
|
||||
except AttributeError:
|
||||
class TestCcopy:
|
||||
pass
|
||||
|
||||
|
||||
class TestZcopy(BaseCopy):
|
||||
blas_func = fblas.zcopy
|
||||
dtype = complex128
|
||||
|
||||
|
||||
##################################################
|
||||
# Test blas ?swap
|
||||
|
||||
class BaseSwap(object):
|
||||
''' Mixin class for swap tests '''
|
||||
|
||||
def test_simple(self):
|
||||
x = arange(3., dtype=self.dtype)
|
||||
y = zeros(shape(x), x.dtype)
|
||||
desired_x = y.copy()
|
||||
desired_y = x.copy()
|
||||
x, y = self.blas_func(x, y)
|
||||
assert_array_equal(desired_x, x)
|
||||
assert_array_equal(desired_y, y)
|
||||
|
||||
def test_x_stride(self):
|
||||
x = arange(6., dtype=self.dtype)
|
||||
y = zeros(3, x.dtype)
|
||||
desired_x = y.copy()
|
||||
desired_y = x.copy()[::2]
|
||||
x, y = self.blas_func(x, y, n=3, incx=2)
|
||||
assert_array_equal(desired_x, x[::2])
|
||||
assert_array_equal(desired_y, y)
|
||||
|
||||
def test_y_stride(self):
|
||||
x = arange(3., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
desired_x = y.copy()[::2]
|
||||
desired_y = x.copy()
|
||||
x, y = self.blas_func(x, y, n=3, incy=2)
|
||||
assert_array_equal(desired_x, x)
|
||||
assert_array_equal(desired_y, y[::2])
|
||||
|
||||
def test_x_and_y_stride(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
desired_x = y.copy()[::2]
|
||||
desired_y = x.copy()[::4]
|
||||
x, y = self.blas_func(x, y, n=3, incx=4, incy=2)
|
||||
assert_array_equal(desired_x, x[::4])
|
||||
assert_array_equal(desired_y, y[::2])
|
||||
|
||||
def test_x_bad_size(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
with pytest.raises(Exception, match='failed for 1st keyword'):
|
||||
self.blas_func(x, y, n=4, incx=5)
|
||||
|
||||
def test_y_bad_size(self):
|
||||
x = arange(12., dtype=self.dtype)
|
||||
y = zeros(6, x.dtype)
|
||||
with pytest.raises(Exception, match='failed for 1st keyword'):
|
||||
self.blas_func(x, y, n=3, incy=5)
|
||||
|
||||
|
||||
try:
|
||||
class TestSswap(BaseSwap):
|
||||
blas_func = fblas.sswap
|
||||
dtype = float32
|
||||
except AttributeError:
|
||||
class TestSswap:
|
||||
pass
|
||||
|
||||
|
||||
class TestDswap(BaseSwap):
|
||||
blas_func = fblas.dswap
|
||||
dtype = float64
|
||||
|
||||
|
||||
try:
|
||||
class TestCswap(BaseSwap):
|
||||
blas_func = fblas.cswap
|
||||
dtype = complex64
|
||||
except AttributeError:
|
||||
class TestCswap:
|
||||
pass
|
||||
|
||||
|
||||
class TestZswap(BaseSwap):
|
||||
blas_func = fblas.zswap
|
||||
dtype = complex128
|
||||
|
||||
##################################################
|
||||
# Test blas ?gemv
|
||||
# This will be a mess to test all cases.
|
||||
|
||||
|
||||
class BaseGemv(object):
|
||||
''' Mixin class for gemv tests '''
|
||||
|
||||
def get_data(self, x_stride=1, y_stride=1):
|
||||
mult = array(1, dtype=self.dtype)
|
||||
if self.dtype in [complex64, complex128]:
|
||||
mult = array(1+1j, dtype=self.dtype)
|
||||
from numpy.random import normal, seed
|
||||
seed(1234)
|
||||
alpha = array(1., dtype=self.dtype) * mult
|
||||
beta = array(1., dtype=self.dtype) * mult
|
||||
a = normal(0., 1., (3, 3)).astype(self.dtype) * mult
|
||||
x = arange(shape(a)[0]*x_stride, dtype=self.dtype) * mult
|
||||
y = arange(shape(a)[1]*y_stride, dtype=self.dtype) * mult
|
||||
return alpha, beta, a, x, y
|
||||
|
||||
def test_simple(self):
|
||||
alpha, beta, a, x, y = self.get_data()
|
||||
desired_y = alpha*matrixmultiply(a, x)+beta*y
|
||||
y = self.blas_func(alpha, a, x, beta, y)
|
||||
assert_array_almost_equal(desired_y, y)
|
||||
|
||||
def test_default_beta_y(self):
|
||||
alpha, beta, a, x, y = self.get_data()
|
||||
desired_y = matrixmultiply(a, x)
|
||||
y = self.blas_func(1, a, x)
|
||||
assert_array_almost_equal(desired_y, y)
|
||||
|
||||
def test_simple_transpose(self):
|
||||
alpha, beta, a, x, y = self.get_data()
|
||||
desired_y = alpha*matrixmultiply(transpose(a), x)+beta*y
|
||||
y = self.blas_func(alpha, a, x, beta, y, trans=1)
|
||||
assert_array_almost_equal(desired_y, y)
|
||||
|
||||
def test_simple_transpose_conj(self):
|
||||
alpha, beta, a, x, y = self.get_data()
|
||||
desired_y = alpha*matrixmultiply(transpose(conjugate(a)), x)+beta*y
|
||||
y = self.blas_func(alpha, a, x, beta, y, trans=2)
|
||||
assert_array_almost_equal(desired_y, y)
|
||||
|
||||
def test_x_stride(self):
|
||||
alpha, beta, a, x, y = self.get_data(x_stride=2)
|
||||
desired_y = alpha*matrixmultiply(a, x[::2])+beta*y
|
||||
y = self.blas_func(alpha, a, x, beta, y, incx=2)
|
||||
assert_array_almost_equal(desired_y, y)
|
||||
|
||||
def test_x_stride_transpose(self):
|
||||
alpha, beta, a, x, y = self.get_data(x_stride=2)
|
||||
desired_y = alpha*matrixmultiply(transpose(a), x[::2])+beta*y
|
||||
y = self.blas_func(alpha, a, x, beta, y, trans=1, incx=2)
|
||||
assert_array_almost_equal(desired_y, y)
|
||||
|
||||
def test_x_stride_assert(self):
|
||||
# What is the use of this test?
|
||||
alpha, beta, a, x, y = self.get_data(x_stride=2)
|
||||
with pytest.raises(Exception, match='failed for 3rd argument'):
|
||||
y = self.blas_func(1, a, x, 1, y, trans=0, incx=3)
|
||||
with pytest.raises(Exception, match='failed for 3rd argument'):
|
||||
y = self.blas_func(1, a, x, 1, y, trans=1, incx=3)
|
||||
|
||||
def test_y_stride(self):
|
||||
alpha, beta, a, x, y = self.get_data(y_stride=2)
|
||||
desired_y = y.copy()
|
||||
desired_y[::2] = alpha*matrixmultiply(a, x)+beta*y[::2]
|
||||
y = self.blas_func(alpha, a, x, beta, y, incy=2)
|
||||
assert_array_almost_equal(desired_y, y)
|
||||
|
||||
def test_y_stride_transpose(self):
|
||||
alpha, beta, a, x, y = self.get_data(y_stride=2)
|
||||
desired_y = y.copy()
|
||||
desired_y[::2] = alpha*matrixmultiply(transpose(a), x)+beta*y[::2]
|
||||
y = self.blas_func(alpha, a, x, beta, y, trans=1, incy=2)
|
||||
assert_array_almost_equal(desired_y, y)
|
||||
|
||||
def test_y_stride_assert(self):
|
||||
# What is the use of this test?
|
||||
alpha, beta, a, x, y = self.get_data(y_stride=2)
|
||||
with pytest.raises(Exception, match='failed for 2nd keyword'):
|
||||
y = self.blas_func(1, a, x, 1, y, trans=0, incy=3)
|
||||
with pytest.raises(Exception, match='failed for 2nd keyword'):
|
||||
y = self.blas_func(1, a, x, 1, y, trans=1, incy=3)
|
||||
|
||||
|
||||
try:
|
||||
class TestSgemv(BaseGemv):
|
||||
blas_func = fblas.sgemv
|
||||
dtype = float32
|
||||
|
||||
def test_sgemv_on_osx(self):
|
||||
from itertools import product
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
if sys.platform != 'darwin':
|
||||
return
|
||||
|
||||
def aligned_array(shape, align, dtype, order='C'):
|
||||
# Make array shape `shape` with aligned at `align` bytes
|
||||
d = dtype()
|
||||
# Make array of correct size with `align` extra bytes
|
||||
N = np.prod(shape)
|
||||
tmp = np.zeros(N * d.nbytes + align, dtype=np.uint8)
|
||||
address = tmp.__array_interface__["data"][0]
|
||||
# Find offset into array giving desired alignment
|
||||
for offset in range(align):
|
||||
if (address + offset) % align == 0:
|
||||
break
|
||||
tmp = tmp[offset:offset+N*d.nbytes].view(dtype=dtype)
|
||||
return tmp.reshape(shape, order=order)
|
||||
|
||||
def as_aligned(arr, align, dtype, order='C'):
|
||||
# Copy `arr` into an aligned array with same shape
|
||||
aligned = aligned_array(arr.shape, align, dtype, order)
|
||||
aligned[:] = arr[:]
|
||||
return aligned
|
||||
|
||||
def assert_dot_close(A, X, desired):
|
||||
assert_allclose(self.blas_func(1.0, A, X), desired,
|
||||
rtol=1e-5, atol=1e-7)
|
||||
|
||||
testdata = product((15, 32), (10000,), (200, 89), ('C', 'F'))
|
||||
for align, m, n, a_order in testdata:
|
||||
A_d = np.random.rand(m, n)
|
||||
X_d = np.random.rand(n)
|
||||
desired = np.dot(A_d, X_d)
|
||||
# Calculation with aligned single precision
|
||||
A_f = as_aligned(A_d, align, np.float32, order=a_order)
|
||||
X_f = as_aligned(X_d, align, np.float32, order=a_order)
|
||||
assert_dot_close(A_f, X_f, desired)
|
||||
|
||||
except AttributeError:
|
||||
class TestSgemv:
|
||||
pass
|
||||
|
||||
|
||||
class TestDgemv(BaseGemv):
|
||||
blas_func = fblas.dgemv
|
||||
dtype = float64
|
||||
|
||||
|
||||
try:
|
||||
class TestCgemv(BaseGemv):
|
||||
blas_func = fblas.cgemv
|
||||
dtype = complex64
|
||||
except AttributeError:
|
||||
class TestCgemv:
|
||||
pass
|
||||
|
||||
|
||||
class TestZgemv(BaseGemv):
|
||||
blas_func = fblas.zgemv
|
||||
dtype = complex128
|
||||
|
||||
|
||||
"""
|
||||
##################################################
|
||||
### Test blas ?ger
|
||||
### This will be a mess to test all cases.
|
||||
|
||||
class BaseGer(object):
|
||||
def get_data(self,x_stride=1,y_stride=1):
|
||||
from numpy.random import normal, seed
|
||||
seed(1234)
|
||||
alpha = array(1., dtype = self.dtype)
|
||||
a = normal(0.,1.,(3,3)).astype(self.dtype)
|
||||
x = arange(shape(a)[0]*x_stride,dtype=self.dtype)
|
||||
y = arange(shape(a)[1]*y_stride,dtype=self.dtype)
|
||||
return alpha,a,x,y
|
||||
def test_simple(self):
|
||||
alpha,a,x,y = self.get_data()
|
||||
# tranpose takes care of Fortran vs. C(and Python) memory layout
|
||||
desired_a = alpha*transpose(x[:,newaxis]*y) + a
|
||||
self.blas_func(x,y,a)
|
||||
assert_array_almost_equal(desired_a,a)
|
||||
def test_x_stride(self):
|
||||
alpha,a,x,y = self.get_data(x_stride=2)
|
||||
desired_a = alpha*transpose(x[::2,newaxis]*y) + a
|
||||
self.blas_func(x,y,a,incx=2)
|
||||
assert_array_almost_equal(desired_a,a)
|
||||
def test_x_stride_assert(self):
|
||||
alpha,a,x,y = self.get_data(x_stride=2)
|
||||
with pytest.raises(ValueError, match='foo'):
|
||||
self.blas_func(x,y,a,incx=3)
|
||||
def test_y_stride(self):
|
||||
alpha,a,x,y = self.get_data(y_stride=2)
|
||||
desired_a = alpha*transpose(x[:,newaxis]*y[::2]) + a
|
||||
self.blas_func(x,y,a,incy=2)
|
||||
assert_array_almost_equal(desired_a,a)
|
||||
|
||||
def test_y_stride_assert(self):
|
||||
alpha,a,x,y = self.get_data(y_stride=2)
|
||||
with pytest.raises(ValueError, match='foo'):
|
||||
self.blas_func(a,x,y,incy=3)
|
||||
|
||||
class TestSger(BaseGer):
|
||||
blas_func = fblas.sger
|
||||
dtype = float32
|
||||
class TestDger(BaseGer):
|
||||
blas_func = fblas.dger
|
||||
dtype = float64
|
||||
"""
|
||||
##################################################
|
||||
# Test blas ?gerc
|
||||
# This will be a mess to test all cases.
|
||||
|
||||
"""
|
||||
class BaseGerComplex(BaseGer):
|
||||
def get_data(self,x_stride=1,y_stride=1):
|
||||
from numpy.random import normal, seed
|
||||
seed(1234)
|
||||
alpha = array(1+1j, dtype = self.dtype)
|
||||
a = normal(0.,1.,(3,3)).astype(self.dtype)
|
||||
a = a + normal(0.,1.,(3,3)) * array(1j, dtype = self.dtype)
|
||||
x = normal(0.,1.,shape(a)[0]*x_stride).astype(self.dtype)
|
||||
x = x + x * array(1j, dtype = self.dtype)
|
||||
y = normal(0.,1.,shape(a)[1]*y_stride).astype(self.dtype)
|
||||
y = y + y * array(1j, dtype = self.dtype)
|
||||
return alpha,a,x,y
|
||||
def test_simple(self):
|
||||
alpha,a,x,y = self.get_data()
|
||||
# tranpose takes care of Fortran vs. C(and Python) memory layout
|
||||
a = a * array(0.,dtype = self.dtype)
|
||||
#desired_a = alpha*transpose(x[:,newaxis]*self.transform(y)) + a
|
||||
desired_a = alpha*transpose(x[:,newaxis]*y) + a
|
||||
#self.blas_func(x,y,a,alpha = alpha)
|
||||
fblas.cgeru(x,y,a,alpha = alpha)
|
||||
assert_array_almost_equal(desired_a,a)
|
||||
|
||||
#def test_x_stride(self):
|
||||
# alpha,a,x,y = self.get_data(x_stride=2)
|
||||
# desired_a = alpha*transpose(x[::2,newaxis]*self.transform(y)) + a
|
||||
# self.blas_func(x,y,a,incx=2)
|
||||
# assert_array_almost_equal(desired_a,a)
|
||||
#def test_y_stride(self):
|
||||
# alpha,a,x,y = self.get_data(y_stride=2)
|
||||
# desired_a = alpha*transpose(x[:,newaxis]*self.transform(y[::2])) + a
|
||||
# self.blas_func(x,y,a,incy=2)
|
||||
# assert_array_almost_equal(desired_a,a)
|
||||
|
||||
class TestCgeru(BaseGerComplex):
|
||||
blas_func = fblas.cgeru
|
||||
dtype = complex64
|
||||
def transform(self,x):
|
||||
return x
|
||||
class TestZgeru(BaseGerComplex):
|
||||
blas_func = fblas.zgeru
|
||||
dtype = complex128
|
||||
def transform(self,x):
|
||||
return x
|
||||
|
||||
class TestCgerc(BaseGerComplex):
|
||||
blas_func = fblas.cgerc
|
||||
dtype = complex64
|
||||
def transform(self,x):
|
||||
return conjugate(x)
|
||||
|
||||
class TestZgerc(BaseGerComplex):
|
||||
blas_func = fblas.zgerc
|
||||
dtype = complex128
|
||||
def transform(self,x):
|
||||
return conjugate(x)
|
||||
"""
|
295
venv/Lib/site-packages/scipy/linalg/tests/test_interpolative.py
Normal file
295
venv/Lib/site-packages/scipy/linalg/tests/test_interpolative.py
Normal file
|
@ -0,0 +1,295 @@
|
|||
#******************************************************************************
|
||||
# Copyright (C) 2013 Kenneth L. Ho
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer. Redistributions in binary
|
||||
# form must reproduce the above copyright notice, this list of conditions and
|
||||
# the following disclaimer in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
#
|
||||
# None of the names of the copyright holders may be used to endorse or
|
||||
# promote products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#******************************************************************************
|
||||
|
||||
import scipy.linalg.interpolative as pymatrixid
|
||||
import numpy as np
|
||||
from scipy.linalg import hilbert, svdvals, norm
|
||||
from scipy.sparse.linalg import aslinearoperator
|
||||
from scipy.linalg.interpolative import interp_decomp
|
||||
import time
|
||||
import itertools
|
||||
|
||||
from numpy.testing import assert_, assert_allclose
|
||||
from pytest import raises as assert_raises
|
||||
|
||||
|
||||
def _debug_print(s):
|
||||
if 0:
|
||||
print(s)
|
||||
|
||||
|
||||
class TestInterpolativeDecomposition(object):
|
||||
def test_id(self):
|
||||
for dtype in [np.float64, np.complex128]:
|
||||
self.check_id(dtype)
|
||||
|
||||
def check_id(self, dtype):
|
||||
# Test ID routines on a Hilbert matrix.
|
||||
|
||||
# set parameters
|
||||
n = 300
|
||||
eps = 1e-12
|
||||
|
||||
# construct Hilbert matrix
|
||||
A = hilbert(n).astype(dtype)
|
||||
if np.issubdtype(dtype, np.complexfloating):
|
||||
A = A * (1 + 1j)
|
||||
L = aslinearoperator(A)
|
||||
|
||||
# find rank
|
||||
S = np.linalg.svd(A, compute_uv=False)
|
||||
try:
|
||||
rank = np.nonzero(S < eps)[0][0]
|
||||
except IndexError:
|
||||
rank = n
|
||||
|
||||
# print input summary
|
||||
_debug_print("Hilbert matrix dimension: %8i" % n)
|
||||
_debug_print("Working precision: %8.2e" % eps)
|
||||
_debug_print("Rank to working precision: %8i" % rank)
|
||||
|
||||
# set print format
|
||||
fmt = "%8.2e (s) / %5s"
|
||||
|
||||
# test real ID routines
|
||||
_debug_print("-----------------------------------------")
|
||||
_debug_print("Real ID routines")
|
||||
_debug_print("-----------------------------------------")
|
||||
|
||||
# fixed precision
|
||||
_debug_print("Calling iddp_id / idzp_id ...",)
|
||||
t0 = time.time()
|
||||
k, idx, proj = pymatrixid.interp_decomp(A, eps, rand=False)
|
||||
t = time.time() - t0
|
||||
B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj)
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
_debug_print("Calling iddp_aid / idzp_aid ...",)
|
||||
t0 = time.time()
|
||||
k, idx, proj = pymatrixid.interp_decomp(A, eps)
|
||||
t = time.time() - t0
|
||||
B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj)
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
_debug_print("Calling iddp_rid / idzp_rid ...",)
|
||||
t0 = time.time()
|
||||
k, idx, proj = pymatrixid.interp_decomp(L, eps)
|
||||
t = time.time() - t0
|
||||
B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj)
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
# fixed rank
|
||||
k = rank
|
||||
|
||||
_debug_print("Calling iddr_id / idzr_id ...",)
|
||||
t0 = time.time()
|
||||
idx, proj = pymatrixid.interp_decomp(A, k, rand=False)
|
||||
t = time.time() - t0
|
||||
B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj)
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
_debug_print("Calling iddr_aid / idzr_aid ...",)
|
||||
t0 = time.time()
|
||||
idx, proj = pymatrixid.interp_decomp(A, k)
|
||||
t = time.time() - t0
|
||||
B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj)
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
_debug_print("Calling iddr_rid / idzr_rid ...",)
|
||||
t0 = time.time()
|
||||
idx, proj = pymatrixid.interp_decomp(L, k)
|
||||
t = time.time() - t0
|
||||
B = pymatrixid.reconstruct_matrix_from_id(A[:, idx[:k]], idx, proj)
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
# check skeleton and interpolation matrices
|
||||
idx, proj = pymatrixid.interp_decomp(A, k, rand=False)
|
||||
P = pymatrixid.reconstruct_interp_matrix(idx, proj)
|
||||
B = pymatrixid.reconstruct_skel_matrix(A, k, idx)
|
||||
assert_(np.allclose(B, A[:,idx[:k]], eps))
|
||||
assert_(np.allclose(B.dot(P), A, eps))
|
||||
|
||||
# test SVD routines
|
||||
_debug_print("-----------------------------------------")
|
||||
_debug_print("SVD routines")
|
||||
_debug_print("-----------------------------------------")
|
||||
|
||||
# fixed precision
|
||||
_debug_print("Calling iddp_svd / idzp_svd ...",)
|
||||
t0 = time.time()
|
||||
U, S, V = pymatrixid.svd(A, eps, rand=False)
|
||||
t = time.time() - t0
|
||||
B = np.dot(U, np.dot(np.diag(S), V.T.conj()))
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
_debug_print("Calling iddp_asvd / idzp_asvd...",)
|
||||
t0 = time.time()
|
||||
U, S, V = pymatrixid.svd(A, eps)
|
||||
t = time.time() - t0
|
||||
B = np.dot(U, np.dot(np.diag(S), V.T.conj()))
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
_debug_print("Calling iddp_rsvd / idzp_rsvd...",)
|
||||
t0 = time.time()
|
||||
U, S, V = pymatrixid.svd(L, eps)
|
||||
t = time.time() - t0
|
||||
B = np.dot(U, np.dot(np.diag(S), V.T.conj()))
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
# fixed rank
|
||||
k = rank
|
||||
|
||||
_debug_print("Calling iddr_svd / idzr_svd ...",)
|
||||
t0 = time.time()
|
||||
U, S, V = pymatrixid.svd(A, k, rand=False)
|
||||
t = time.time() - t0
|
||||
B = np.dot(U, np.dot(np.diag(S), V.T.conj()))
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
_debug_print("Calling iddr_asvd / idzr_asvd ...",)
|
||||
t0 = time.time()
|
||||
U, S, V = pymatrixid.svd(A, k)
|
||||
t = time.time() - t0
|
||||
B = np.dot(U, np.dot(np.diag(S), V.T.conj()))
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
_debug_print("Calling iddr_rsvd / idzr_rsvd ...",)
|
||||
t0 = time.time()
|
||||
U, S, V = pymatrixid.svd(L, k)
|
||||
t = time.time() - t0
|
||||
B = np.dot(U, np.dot(np.diag(S), V.T.conj()))
|
||||
_debug_print(fmt % (t, np.allclose(A, B, eps)))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
# ID to SVD
|
||||
idx, proj = pymatrixid.interp_decomp(A, k, rand=False)
|
||||
Up, Sp, Vp = pymatrixid.id_to_svd(A[:, idx[:k]], idx, proj)
|
||||
B = U.dot(np.diag(S).dot(V.T.conj()))
|
||||
assert_(np.allclose(A, B, eps))
|
||||
|
||||
# Norm estimates
|
||||
s = svdvals(A)
|
||||
norm_2_est = pymatrixid.estimate_spectral_norm(A)
|
||||
assert_(np.allclose(norm_2_est, s[0], 1e-6))
|
||||
|
||||
B = A.copy()
|
||||
B[:,0] *= 1.2
|
||||
s = svdvals(A - B)
|
||||
norm_2_est = pymatrixid.estimate_spectral_norm_diff(A, B)
|
||||
assert_(np.allclose(norm_2_est, s[0], 1e-6))
|
||||
|
||||
# Rank estimates
|
||||
B = np.array([[1, 1, 0], [0, 0, 1], [0, 0, 1]], dtype=dtype)
|
||||
for M in [A, B]:
|
||||
ML = aslinearoperator(M)
|
||||
|
||||
rank_tol = 1e-9
|
||||
rank_np = np.linalg.matrix_rank(M, norm(M, 2)*rank_tol)
|
||||
rank_est = pymatrixid.estimate_rank(M, rank_tol)
|
||||
rank_est_2 = pymatrixid.estimate_rank(ML, rank_tol)
|
||||
|
||||
assert_(rank_est >= rank_np)
|
||||
assert_(rank_est <= rank_np + 10)
|
||||
|
||||
assert_(rank_est_2 >= rank_np - 4)
|
||||
assert_(rank_est_2 <= rank_np + 4)
|
||||
|
||||
def test_rand(self):
|
||||
pymatrixid.seed('default')
|
||||
assert_(np.allclose(pymatrixid.rand(2), [0.8932059, 0.64500803], 1e-4))
|
||||
|
||||
pymatrixid.seed(1234)
|
||||
x1 = pymatrixid.rand(2)
|
||||
assert_(np.allclose(x1, [0.7513823, 0.06861718], 1e-4))
|
||||
|
||||
np.random.seed(1234)
|
||||
pymatrixid.seed()
|
||||
x2 = pymatrixid.rand(2)
|
||||
|
||||
np.random.seed(1234)
|
||||
pymatrixid.seed(np.random.rand(55))
|
||||
x3 = pymatrixid.rand(2)
|
||||
|
||||
assert_allclose(x1, x2)
|
||||
assert_allclose(x1, x3)
|
||||
|
||||
def test_badcall(self):
|
||||
A = hilbert(5).astype(np.float32)
|
||||
assert_raises(ValueError, pymatrixid.interp_decomp, A, 1e-6, rand=False)
|
||||
|
||||
def test_rank_too_large(self):
|
||||
# svd(array, k) should not segfault
|
||||
a = np.ones((4, 3))
|
||||
with assert_raises(ValueError):
|
||||
pymatrixid.svd(a, 4)
|
||||
|
||||
def test_full_rank(self):
|
||||
eps = 1.0e-12
|
||||
|
||||
# fixed precision
|
||||
A = np.random.rand(16, 8)
|
||||
k, idx, proj = pymatrixid.interp_decomp(A, eps)
|
||||
assert_(k == A.shape[1])
|
||||
|
||||
P = pymatrixid.reconstruct_interp_matrix(idx, proj)
|
||||
B = pymatrixid.reconstruct_skel_matrix(A, k, idx)
|
||||
assert_allclose(A, B.dot(P))
|
||||
|
||||
# fixed rank
|
||||
idx, proj = pymatrixid.interp_decomp(A, k)
|
||||
|
||||
P = pymatrixid.reconstruct_interp_matrix(idx, proj)
|
||||
B = pymatrixid.reconstruct_skel_matrix(A, k, idx)
|
||||
assert_allclose(A, B.dot(P))
|
||||
|
||||
def test_bug_9793(self):
|
||||
dtypes = [np.float_, np.complex_]
|
||||
rands = [True, False]
|
||||
epss = [1, 0.1]
|
||||
|
||||
for dtype, eps, rand in itertools.product(dtypes, epss, rands):
|
||||
A = np.array([[-1, -1, -1, 0, 0, 0],
|
||||
[0, 0, 0, 1, 1, 1],
|
||||
[1, 0, 0, 1, 0, 0],
|
||||
[0, 1, 0, 0, 1, 0],
|
||||
[0, 0, 1, 0, 0, 1]],
|
||||
dtype=dtype, order="C")
|
||||
B = A.copy()
|
||||
interp_decomp(A.T, eps, rand=rand)
|
||||
assert_(np.array_equal(A, B))
|
2925
venv/Lib/site-packages/scipy/linalg/tests/test_lapack.py
Normal file
2925
venv/Lib/site-packages/scipy/linalg/tests/test_lapack.py
Normal file
File diff suppressed because it is too large
Load diff
895
venv/Lib/site-packages/scipy/linalg/tests/test_matfuncs.py
Normal file
895
venv/Lib/site-packages/scipy/linalg/tests/test_matfuncs.py
Normal file
|
@ -0,0 +1,895 @@
|
|||
#
|
||||
# Created by: Pearu Peterson, March 2002
|
||||
#
|
||||
""" Test functions for linalg.matfuncs module
|
||||
|
||||
"""
|
||||
import random
|
||||
import functools
|
||||
|
||||
import numpy as np
|
||||
from numpy import array, identity, dot, sqrt
|
||||
from numpy.testing import (
|
||||
assert_array_equal, assert_array_less, assert_equal,
|
||||
assert_array_almost_equal,
|
||||
assert_allclose, assert_, assert_warns)
|
||||
import pytest
|
||||
|
||||
import scipy.linalg
|
||||
from scipy.linalg import (funm, signm, logm, sqrtm, fractional_matrix_power,
|
||||
expm, expm_frechet, expm_cond, norm, khatri_rao)
|
||||
from scipy.linalg import _matfuncs_inv_ssq
|
||||
import scipy.linalg._expm_frechet
|
||||
|
||||
from scipy.optimize import minimize
|
||||
|
||||
|
||||
def _get_al_mohy_higham_2012_experiment_1():
|
||||
"""
|
||||
Return the test matrix from Experiment (1) of [1]_.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Awad H. Al-Mohy and Nicholas J. Higham (2012)
|
||||
"Improved Inverse Scaling and Squaring Algorithms
|
||||
for the Matrix Logarithm."
|
||||
SIAM Journal on Scientific Computing, 34 (4). C152-C169.
|
||||
ISSN 1095-7197
|
||||
|
||||
"""
|
||||
A = np.array([
|
||||
[3.2346e-1, 3e4, 3e4, 3e4],
|
||||
[0, 3.0089e-1, 3e4, 3e4],
|
||||
[0, 0, 3.2210e-1, 3e4],
|
||||
[0, 0, 0, 3.0744e-1]], dtype=float)
|
||||
return A
|
||||
|
||||
|
||||
class TestSignM(object):
|
||||
|
||||
def test_nils(self):
|
||||
a = array([[29.2, -24.2, 69.5, 49.8, 7.],
|
||||
[-9.2, 5.2, -18., -16.8, -2.],
|
||||
[-10., 6., -20., -18., -2.],
|
||||
[-9.6, 9.6, -25.5, -15.4, -2.],
|
||||
[9.8, -4.8, 18., 18.2, 2.]])
|
||||
cr = array([[11.94933333,-2.24533333,15.31733333,21.65333333,-2.24533333],
|
||||
[-3.84266667,0.49866667,-4.59066667,-7.18666667,0.49866667],
|
||||
[-4.08,0.56,-4.92,-7.6,0.56],
|
||||
[-4.03466667,1.04266667,-5.59866667,-7.02666667,1.04266667],
|
||||
[4.15733333,-0.50133333,4.90933333,7.81333333,-0.50133333]])
|
||||
r = signm(a)
|
||||
assert_array_almost_equal(r,cr)
|
||||
|
||||
def test_defective1(self):
|
||||
a = array([[0.0,1,0,0],[1,0,1,0],[0,0,0,1],[0,0,1,0]])
|
||||
signm(a, disp=False)
|
||||
#XXX: what would be the correct result?
|
||||
|
||||
def test_defective2(self):
|
||||
a = array((
|
||||
[29.2,-24.2,69.5,49.8,7.0],
|
||||
[-9.2,5.2,-18.0,-16.8,-2.0],
|
||||
[-10.0,6.0,-20.0,-18.0,-2.0],
|
||||
[-9.6,9.6,-25.5,-15.4,-2.0],
|
||||
[9.8,-4.8,18.0,18.2,2.0]))
|
||||
signm(a, disp=False)
|
||||
#XXX: what would be the correct result?
|
||||
|
||||
def test_defective3(self):
|
||||
a = array([[-2., 25., 0., 0., 0., 0., 0.],
|
||||
[0., -3., 10., 3., 3., 3., 0.],
|
||||
[0., 0., 2., 15., 3., 3., 0.],
|
||||
[0., 0., 0., 0., 15., 3., 0.],
|
||||
[0., 0., 0., 0., 3., 10., 0.],
|
||||
[0., 0., 0., 0., 0., -2., 25.],
|
||||
[0., 0., 0., 0., 0., 0., -3.]])
|
||||
signm(a, disp=False)
|
||||
#XXX: what would be the correct result?
|
||||
|
||||
|
||||
class TestLogM(object):
|
||||
|
||||
def test_nils(self):
|
||||
a = array([[-2., 25., 0., 0., 0., 0., 0.],
|
||||
[0., -3., 10., 3., 3., 3., 0.],
|
||||
[0., 0., 2., 15., 3., 3., 0.],
|
||||
[0., 0., 0., 0., 15., 3., 0.],
|
||||
[0., 0., 0., 0., 3., 10., 0.],
|
||||
[0., 0., 0., 0., 0., -2., 25.],
|
||||
[0., 0., 0., 0., 0., 0., -3.]])
|
||||
m = (identity(7)*3.1+0j)-a
|
||||
logm(m, disp=False)
|
||||
#XXX: what would be the correct result?
|
||||
|
||||
def test_al_mohy_higham_2012_experiment_1_logm(self):
|
||||
# The logm completes the round trip successfully.
|
||||
# Note that the expm leg of the round trip is badly conditioned.
|
||||
A = _get_al_mohy_higham_2012_experiment_1()
|
||||
A_logm, info = logm(A, disp=False)
|
||||
A_round_trip = expm(A_logm)
|
||||
assert_allclose(A_round_trip, A, rtol=1e-5, atol=1e-14)
|
||||
|
||||
def test_al_mohy_higham_2012_experiment_1_funm_log(self):
|
||||
# The raw funm with np.log does not complete the round trip.
|
||||
# Note that the expm leg of the round trip is badly conditioned.
|
||||
A = _get_al_mohy_higham_2012_experiment_1()
|
||||
A_funm_log, info = funm(A, np.log, disp=False)
|
||||
A_round_trip = expm(A_funm_log)
|
||||
assert_(not np.allclose(A_round_trip, A, rtol=1e-5, atol=1e-14))
|
||||
|
||||
def test_round_trip_random_float(self):
|
||||
np.random.seed(1234)
|
||||
for n in range(1, 6):
|
||||
M_unscaled = np.random.randn(n, n)
|
||||
for scale in np.logspace(-4, 4, 9):
|
||||
M = M_unscaled * scale
|
||||
|
||||
# Eigenvalues are related to the branch cut.
|
||||
W = np.linalg.eigvals(M)
|
||||
err_msg = 'M:{0} eivals:{1}'.format(M, W)
|
||||
|
||||
# Check sqrtm round trip because it is used within logm.
|
||||
M_sqrtm, info = sqrtm(M, disp=False)
|
||||
M_sqrtm_round_trip = M_sqrtm.dot(M_sqrtm)
|
||||
assert_allclose(M_sqrtm_round_trip, M)
|
||||
|
||||
# Check logm round trip.
|
||||
M_logm, info = logm(M, disp=False)
|
||||
M_logm_round_trip = expm(M_logm)
|
||||
assert_allclose(M_logm_round_trip, M, err_msg=err_msg)
|
||||
|
||||
def test_round_trip_random_complex(self):
|
||||
np.random.seed(1234)
|
||||
for n in range(1, 6):
|
||||
M_unscaled = np.random.randn(n, n) + 1j * np.random.randn(n, n)
|
||||
for scale in np.logspace(-4, 4, 9):
|
||||
M = M_unscaled * scale
|
||||
M_logm, info = logm(M, disp=False)
|
||||
M_round_trip = expm(M_logm)
|
||||
assert_allclose(M_round_trip, M)
|
||||
|
||||
def test_logm_type_preservation_and_conversion(self):
|
||||
# The logm matrix function should preserve the type of a matrix
|
||||
# whose eigenvalues are positive with zero imaginary part.
|
||||
# Test this preservation for variously structured matrices.
|
||||
complex_dtype_chars = ('F', 'D', 'G')
|
||||
for matrix_as_list in (
|
||||
[[1, 0], [0, 1]],
|
||||
[[1, 0], [1, 1]],
|
||||
[[2, 1], [1, 1]],
|
||||
[[2, 3], [1, 2]]):
|
||||
|
||||
# check that the spectrum has the expected properties
|
||||
W = scipy.linalg.eigvals(matrix_as_list)
|
||||
assert_(not any(w.imag or w.real < 0 for w in W))
|
||||
|
||||
# check float type preservation
|
||||
A = np.array(matrix_as_list, dtype=float)
|
||||
A_logm, info = logm(A, disp=False)
|
||||
assert_(A_logm.dtype.char not in complex_dtype_chars)
|
||||
|
||||
# check complex type preservation
|
||||
A = np.array(matrix_as_list, dtype=complex)
|
||||
A_logm, info = logm(A, disp=False)
|
||||
assert_(A_logm.dtype.char in complex_dtype_chars)
|
||||
|
||||
# check float->complex type conversion for the matrix negation
|
||||
A = -np.array(matrix_as_list, dtype=float)
|
||||
A_logm, info = logm(A, disp=False)
|
||||
assert_(A_logm.dtype.char in complex_dtype_chars)
|
||||
|
||||
def test_complex_spectrum_real_logm(self):
|
||||
# This matrix has complex eigenvalues and real logm.
|
||||
# Its output dtype depends on its input dtype.
|
||||
M = [[1, 1, 2], [2, 1, 1], [1, 2, 1]]
|
||||
for dt in float, complex:
|
||||
X = np.array(M, dtype=dt)
|
||||
w = scipy.linalg.eigvals(X)
|
||||
assert_(1e-2 < np.absolute(w.imag).sum())
|
||||
Y, info = logm(X, disp=False)
|
||||
assert_(np.issubdtype(Y.dtype, np.inexact))
|
||||
assert_allclose(expm(Y), X)
|
||||
|
||||
def test_real_mixed_sign_spectrum(self):
|
||||
# These matrices have real eigenvalues with mixed signs.
|
||||
# The output logm dtype is complex, regardless of input dtype.
|
||||
for M in (
|
||||
[[1, 0], [0, -1]],
|
||||
[[0, 1], [1, 0]]):
|
||||
for dt in float, complex:
|
||||
A = np.array(M, dtype=dt)
|
||||
A_logm, info = logm(A, disp=False)
|
||||
assert_(np.issubdtype(A_logm.dtype, np.complexfloating))
|
||||
|
||||
def test_exactly_singular(self):
|
||||
A = np.array([[0, 0], [1j, 1j]])
|
||||
B = np.asarray([[1, 1], [0, 0]])
|
||||
for M in A, A.T, B, B.T:
|
||||
expected_warning = _matfuncs_inv_ssq.LogmExactlySingularWarning
|
||||
L, info = assert_warns(expected_warning, logm, M, disp=False)
|
||||
E = expm(L)
|
||||
assert_allclose(E, M, atol=1e-14)
|
||||
|
||||
def test_nearly_singular(self):
|
||||
M = np.array([[1e-100]])
|
||||
expected_warning = _matfuncs_inv_ssq.LogmNearlySingularWarning
|
||||
L, info = assert_warns(expected_warning, logm, M, disp=False)
|
||||
E = expm(L)
|
||||
assert_allclose(E, M, atol=1e-14)
|
||||
|
||||
def test_opposite_sign_complex_eigenvalues(self):
|
||||
# See gh-6113
|
||||
E = [[0, 1], [-1, 0]]
|
||||
L = [[0, np.pi*0.5], [-np.pi*0.5, 0]]
|
||||
assert_allclose(expm(L), E, atol=1e-14)
|
||||
assert_allclose(logm(E), L, atol=1e-14)
|
||||
E = [[1j, 4], [0, -1j]]
|
||||
L = [[1j*np.pi*0.5, 2*np.pi], [0, -1j*np.pi*0.5]]
|
||||
assert_allclose(expm(L), E, atol=1e-14)
|
||||
assert_allclose(logm(E), L, atol=1e-14)
|
||||
E = [[1j, 0], [0, -1j]]
|
||||
L = [[1j*np.pi*0.5, 0], [0, -1j*np.pi*0.5]]
|
||||
assert_allclose(expm(L), E, atol=1e-14)
|
||||
assert_allclose(logm(E), L, atol=1e-14)
|
||||
|
||||
|
||||
class TestSqrtM(object):
|
||||
def test_round_trip_random_float(self):
|
||||
np.random.seed(1234)
|
||||
for n in range(1, 6):
|
||||
M_unscaled = np.random.randn(n, n)
|
||||
for scale in np.logspace(-4, 4, 9):
|
||||
M = M_unscaled * scale
|
||||
M_sqrtm, info = sqrtm(M, disp=False)
|
||||
M_sqrtm_round_trip = M_sqrtm.dot(M_sqrtm)
|
||||
assert_allclose(M_sqrtm_round_trip, M)
|
||||
|
||||
def test_round_trip_random_complex(self):
|
||||
np.random.seed(1234)
|
||||
for n in range(1, 6):
|
||||
M_unscaled = np.random.randn(n, n) + 1j * np.random.randn(n, n)
|
||||
for scale in np.logspace(-4, 4, 9):
|
||||
M = M_unscaled * scale
|
||||
M_sqrtm, info = sqrtm(M, disp=False)
|
||||
M_sqrtm_round_trip = M_sqrtm.dot(M_sqrtm)
|
||||
assert_allclose(M_sqrtm_round_trip, M)
|
||||
|
||||
def test_bad(self):
|
||||
# See https://web.archive.org/web/20051220232650/http://www.maths.man.ac.uk/~nareports/narep336.ps.gz
|
||||
e = 2**-5
|
||||
se = sqrt(e)
|
||||
a = array([[1.0,0,0,1],
|
||||
[0,e,0,0],
|
||||
[0,0,e,0],
|
||||
[0,0,0,1]])
|
||||
sa = array([[1,0,0,0.5],
|
||||
[0,se,0,0],
|
||||
[0,0,se,0],
|
||||
[0,0,0,1]])
|
||||
n = a.shape[0]
|
||||
assert_array_almost_equal(dot(sa,sa),a)
|
||||
# Check default sqrtm.
|
||||
esa = sqrtm(a, disp=False, blocksize=n)[0]
|
||||
assert_array_almost_equal(dot(esa,esa),a)
|
||||
# Check sqrtm with 2x2 blocks.
|
||||
esa = sqrtm(a, disp=False, blocksize=2)[0]
|
||||
assert_array_almost_equal(dot(esa,esa),a)
|
||||
|
||||
def test_sqrtm_type_preservation_and_conversion(self):
|
||||
# The sqrtm matrix function should preserve the type of a matrix
|
||||
# whose eigenvalues are nonnegative with zero imaginary part.
|
||||
# Test this preservation for variously structured matrices.
|
||||
complex_dtype_chars = ('F', 'D', 'G')
|
||||
for matrix_as_list in (
|
||||
[[1, 0], [0, 1]],
|
||||
[[1, 0], [1, 1]],
|
||||
[[2, 1], [1, 1]],
|
||||
[[2, 3], [1, 2]],
|
||||
[[1, 1], [1, 1]]):
|
||||
|
||||
# check that the spectrum has the expected properties
|
||||
W = scipy.linalg.eigvals(matrix_as_list)
|
||||
assert_(not any(w.imag or w.real < 0 for w in W))
|
||||
|
||||
# check float type preservation
|
||||
A = np.array(matrix_as_list, dtype=float)
|
||||
A_sqrtm, info = sqrtm(A, disp=False)
|
||||
assert_(A_sqrtm.dtype.char not in complex_dtype_chars)
|
||||
|
||||
# check complex type preservation
|
||||
A = np.array(matrix_as_list, dtype=complex)
|
||||
A_sqrtm, info = sqrtm(A, disp=False)
|
||||
assert_(A_sqrtm.dtype.char in complex_dtype_chars)
|
||||
|
||||
# check float->complex type conversion for the matrix negation
|
||||
A = -np.array(matrix_as_list, dtype=float)
|
||||
A_sqrtm, info = sqrtm(A, disp=False)
|
||||
assert_(A_sqrtm.dtype.char in complex_dtype_chars)
|
||||
|
||||
def test_sqrtm_type_conversion_mixed_sign_or_complex_spectrum(self):
|
||||
complex_dtype_chars = ('F', 'D', 'G')
|
||||
for matrix_as_list in (
|
||||
[[1, 0], [0, -1]],
|
||||
[[0, 1], [1, 0]],
|
||||
[[0, 1, 0], [0, 0, 1], [1, 0, 0]]):
|
||||
|
||||
# check that the spectrum has the expected properties
|
||||
W = scipy.linalg.eigvals(matrix_as_list)
|
||||
assert_(any(w.imag or w.real < 0 for w in W))
|
||||
|
||||
# check complex->complex
|
||||
A = np.array(matrix_as_list, dtype=complex)
|
||||
A_sqrtm, info = sqrtm(A, disp=False)
|
||||
assert_(A_sqrtm.dtype.char in complex_dtype_chars)
|
||||
|
||||
# check float->complex
|
||||
A = np.array(matrix_as_list, dtype=float)
|
||||
A_sqrtm, info = sqrtm(A, disp=False)
|
||||
assert_(A_sqrtm.dtype.char in complex_dtype_chars)
|
||||
|
||||
def test_blocksizes(self):
|
||||
# Make sure I do not goof up the blocksizes when they do not divide n.
|
||||
np.random.seed(1234)
|
||||
for n in range(1, 8):
|
||||
A = np.random.rand(n, n) + 1j*np.random.randn(n, n)
|
||||
A_sqrtm_default, info = sqrtm(A, disp=False, blocksize=n)
|
||||
assert_allclose(A, np.linalg.matrix_power(A_sqrtm_default, 2))
|
||||
for blocksize in range(1, 10):
|
||||
A_sqrtm_new, info = sqrtm(A, disp=False, blocksize=blocksize)
|
||||
assert_allclose(A_sqrtm_default, A_sqrtm_new)
|
||||
|
||||
def test_al_mohy_higham_2012_experiment_1(self):
|
||||
# Matrix square root of a tricky upper triangular matrix.
|
||||
A = _get_al_mohy_higham_2012_experiment_1()
|
||||
A_sqrtm, info = sqrtm(A, disp=False)
|
||||
A_round_trip = A_sqrtm.dot(A_sqrtm)
|
||||
assert_allclose(A_round_trip, A, rtol=1e-5)
|
||||
assert_allclose(np.tril(A_round_trip), np.tril(A))
|
||||
|
||||
def test_strict_upper_triangular(self):
|
||||
# This matrix has no square root.
|
||||
for dt in int, float:
|
||||
A = np.array([
|
||||
[0, 3, 0, 0],
|
||||
[0, 0, 3, 0],
|
||||
[0, 0, 0, 3],
|
||||
[0, 0, 0, 0]], dtype=dt)
|
||||
A_sqrtm, info = sqrtm(A, disp=False)
|
||||
assert_(np.isnan(A_sqrtm).all())
|
||||
|
||||
def test_weird_matrix(self):
|
||||
# The square root of matrix B exists.
|
||||
for dt in int, float:
|
||||
A = np.array([
|
||||
[0, 0, 1],
|
||||
[0, 0, 0],
|
||||
[0, 1, 0]], dtype=dt)
|
||||
B = np.array([
|
||||
[0, 1, 0],
|
||||
[0, 0, 0],
|
||||
[0, 0, 0]], dtype=dt)
|
||||
assert_array_equal(B, A.dot(A))
|
||||
|
||||
# But scipy sqrtm is not clever enough to find it.
|
||||
B_sqrtm, info = sqrtm(B, disp=False)
|
||||
assert_(np.isnan(B_sqrtm).all())
|
||||
|
||||
def test_disp(self):
|
||||
np.random.seed(1234)
|
||||
|
||||
A = np.random.rand(3, 3)
|
||||
B = sqrtm(A, disp=True)
|
||||
assert_allclose(B.dot(B), A)
|
||||
|
||||
def test_opposite_sign_complex_eigenvalues(self):
|
||||
M = [[2j, 4], [0, -2j]]
|
||||
R = [[1+1j, 2], [0, 1-1j]]
|
||||
assert_allclose(np.dot(R, R), M, atol=1e-14)
|
||||
assert_allclose(sqrtm(M), R, atol=1e-14)
|
||||
|
||||
def test_gh4866(self):
|
||||
M = np.array([[1, 0, 0, 1],
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0],
|
||||
[1, 0, 0, 1]])
|
||||
R = np.array([[sqrt(0.5), 0, 0, sqrt(0.5)],
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0],
|
||||
[sqrt(0.5), 0, 0, sqrt(0.5)]])
|
||||
assert_allclose(np.dot(R, R), M, atol=1e-14)
|
||||
assert_allclose(sqrtm(M), R, atol=1e-14)
|
||||
|
||||
def test_gh5336(self):
|
||||
M = np.diag([2, 1, 0])
|
||||
R = np.diag([sqrt(2), 1, 0])
|
||||
assert_allclose(np.dot(R, R), M, atol=1e-14)
|
||||
assert_allclose(sqrtm(M), R, atol=1e-14)
|
||||
|
||||
def test_gh7839(self):
|
||||
M = np.zeros((2, 2))
|
||||
R = np.zeros((2, 2))
|
||||
assert_allclose(np.dot(R, R), M, atol=1e-14)
|
||||
assert_allclose(sqrtm(M), R, atol=1e-14)
|
||||
|
||||
|
||||
class TestFractionalMatrixPower(object):
|
||||
def test_round_trip_random_complex(self):
|
||||
np.random.seed(1234)
|
||||
for p in range(1, 5):
|
||||
for n in range(1, 5):
|
||||
M_unscaled = np.random.randn(n, n) + 1j * np.random.randn(n, n)
|
||||
for scale in np.logspace(-4, 4, 9):
|
||||
M = M_unscaled * scale
|
||||
M_root = fractional_matrix_power(M, 1/p)
|
||||
M_round_trip = np.linalg.matrix_power(M_root, p)
|
||||
assert_allclose(M_round_trip, M)
|
||||
|
||||
def test_round_trip_random_float(self):
|
||||
# This test is more annoying because it can hit the branch cut;
|
||||
# this happens when the matrix has an eigenvalue
|
||||
# with no imaginary component and with a real negative component,
|
||||
# and it means that the principal branch does not exist.
|
||||
np.random.seed(1234)
|
||||
for p in range(1, 5):
|
||||
for n in range(1, 5):
|
||||
M_unscaled = np.random.randn(n, n)
|
||||
for scale in np.logspace(-4, 4, 9):
|
||||
M = M_unscaled * scale
|
||||
M_root = fractional_matrix_power(M, 1/p)
|
||||
M_round_trip = np.linalg.matrix_power(M_root, p)
|
||||
assert_allclose(M_round_trip, M)
|
||||
|
||||
def test_larger_abs_fractional_matrix_powers(self):
|
||||
np.random.seed(1234)
|
||||
for n in (2, 3, 5):
|
||||
for i in range(10):
|
||||
M = np.random.randn(n, n) + 1j * np.random.randn(n, n)
|
||||
M_one_fifth = fractional_matrix_power(M, 0.2)
|
||||
# Test the round trip.
|
||||
M_round_trip = np.linalg.matrix_power(M_one_fifth, 5)
|
||||
assert_allclose(M, M_round_trip)
|
||||
# Test a large abs fractional power.
|
||||
X = fractional_matrix_power(M, -5.4)
|
||||
Y = np.linalg.matrix_power(M_one_fifth, -27)
|
||||
assert_allclose(X, Y)
|
||||
# Test another large abs fractional power.
|
||||
X = fractional_matrix_power(M, 3.8)
|
||||
Y = np.linalg.matrix_power(M_one_fifth, 19)
|
||||
assert_allclose(X, Y)
|
||||
|
||||
def test_random_matrices_and_powers(self):
|
||||
# Each independent iteration of this fuzz test picks random parameters.
|
||||
# It tries to hit some edge cases.
|
||||
np.random.seed(1234)
|
||||
nsamples = 20
|
||||
for i in range(nsamples):
|
||||
# Sample a matrix size and a random real power.
|
||||
n = random.randrange(1, 5)
|
||||
p = np.random.randn()
|
||||
|
||||
# Sample a random real or complex matrix.
|
||||
matrix_scale = np.exp(random.randrange(-4, 5))
|
||||
A = np.random.randn(n, n)
|
||||
if random.choice((True, False)):
|
||||
A = A + 1j * np.random.randn(n, n)
|
||||
A = A * matrix_scale
|
||||
|
||||
# Check a couple of analytically equivalent ways
|
||||
# to compute the fractional matrix power.
|
||||
# These can be compared because they both use the principal branch.
|
||||
A_power = fractional_matrix_power(A, p)
|
||||
A_logm, info = logm(A, disp=False)
|
||||
A_power_expm_logm = expm(A_logm * p)
|
||||
assert_allclose(A_power, A_power_expm_logm)
|
||||
|
||||
def test_al_mohy_higham_2012_experiment_1(self):
|
||||
# Fractional powers of a tricky upper triangular matrix.
|
||||
A = _get_al_mohy_higham_2012_experiment_1()
|
||||
|
||||
# Test remainder matrix power.
|
||||
A_funm_sqrt, info = funm(A, np.sqrt, disp=False)
|
||||
A_sqrtm, info = sqrtm(A, disp=False)
|
||||
A_rem_power = _matfuncs_inv_ssq._remainder_matrix_power(A, 0.5)
|
||||
A_power = fractional_matrix_power(A, 0.5)
|
||||
assert_array_equal(A_rem_power, A_power)
|
||||
assert_allclose(A_sqrtm, A_power)
|
||||
assert_allclose(A_sqrtm, A_funm_sqrt)
|
||||
|
||||
# Test more fractional powers.
|
||||
for p in (1/2, 5/3):
|
||||
A_power = fractional_matrix_power(A, p)
|
||||
A_round_trip = fractional_matrix_power(A_power, 1/p)
|
||||
assert_allclose(A_round_trip, A, rtol=1e-2)
|
||||
assert_allclose(np.tril(A_round_trip, 1), np.tril(A, 1))
|
||||
|
||||
def test_briggs_helper_function(self):
|
||||
np.random.seed(1234)
|
||||
for a in np.random.randn(10) + 1j * np.random.randn(10):
|
||||
for k in range(5):
|
||||
x_observed = _matfuncs_inv_ssq._briggs_helper_function(a, k)
|
||||
x_expected = a ** np.exp2(-k) - 1
|
||||
assert_allclose(x_observed, x_expected)
|
||||
|
||||
def test_type_preservation_and_conversion(self):
|
||||
# The fractional_matrix_power matrix function should preserve
|
||||
# the type of a matrix whose eigenvalues
|
||||
# are positive with zero imaginary part.
|
||||
# Test this preservation for variously structured matrices.
|
||||
complex_dtype_chars = ('F', 'D', 'G')
|
||||
for matrix_as_list in (
|
||||
[[1, 0], [0, 1]],
|
||||
[[1, 0], [1, 1]],
|
||||
[[2, 1], [1, 1]],
|
||||
[[2, 3], [1, 2]]):
|
||||
|
||||
# check that the spectrum has the expected properties
|
||||
W = scipy.linalg.eigvals(matrix_as_list)
|
||||
assert_(not any(w.imag or w.real < 0 for w in W))
|
||||
|
||||
# Check various positive and negative powers
|
||||
# with absolute values bigger and smaller than 1.
|
||||
for p in (-2.4, -0.9, 0.2, 3.3):
|
||||
|
||||
# check float type preservation
|
||||
A = np.array(matrix_as_list, dtype=float)
|
||||
A_power = fractional_matrix_power(A, p)
|
||||
assert_(A_power.dtype.char not in complex_dtype_chars)
|
||||
|
||||
# check complex type preservation
|
||||
A = np.array(matrix_as_list, dtype=complex)
|
||||
A_power = fractional_matrix_power(A, p)
|
||||
assert_(A_power.dtype.char in complex_dtype_chars)
|
||||
|
||||
# check float->complex for the matrix negation
|
||||
A = -np.array(matrix_as_list, dtype=float)
|
||||
A_power = fractional_matrix_power(A, p)
|
||||
assert_(A_power.dtype.char in complex_dtype_chars)
|
||||
|
||||
def test_type_conversion_mixed_sign_or_complex_spectrum(self):
|
||||
complex_dtype_chars = ('F', 'D', 'G')
|
||||
for matrix_as_list in (
|
||||
[[1, 0], [0, -1]],
|
||||
[[0, 1], [1, 0]],
|
||||
[[0, 1, 0], [0, 0, 1], [1, 0, 0]]):
|
||||
|
||||
# check that the spectrum has the expected properties
|
||||
W = scipy.linalg.eigvals(matrix_as_list)
|
||||
assert_(any(w.imag or w.real < 0 for w in W))
|
||||
|
||||
# Check various positive and negative powers
|
||||
# with absolute values bigger and smaller than 1.
|
||||
for p in (-2.4, -0.9, 0.2, 3.3):
|
||||
|
||||
# check complex->complex
|
||||
A = np.array(matrix_as_list, dtype=complex)
|
||||
A_power = fractional_matrix_power(A, p)
|
||||
assert_(A_power.dtype.char in complex_dtype_chars)
|
||||
|
||||
# check float->complex
|
||||
A = np.array(matrix_as_list, dtype=float)
|
||||
A_power = fractional_matrix_power(A, p)
|
||||
assert_(A_power.dtype.char in complex_dtype_chars)
|
||||
|
||||
@pytest.mark.xfail(reason='Too unstable across LAPACKs.')
|
||||
def test_singular(self):
|
||||
# Negative fractional powers do not work with singular matrices.
|
||||
for matrix_as_list in (
|
||||
[[0, 0], [0, 0]],
|
||||
[[1, 1], [1, 1]],
|
||||
[[1, 2], [3, 6]],
|
||||
[[0, 0, 0], [0, 1, 1], [0, -1, 1]]):
|
||||
|
||||
# Check fractional powers both for float and for complex types.
|
||||
for newtype in (float, complex):
|
||||
A = np.array(matrix_as_list, dtype=newtype)
|
||||
for p in (-0.7, -0.9, -2.4, -1.3):
|
||||
A_power = fractional_matrix_power(A, p)
|
||||
assert_(np.isnan(A_power).all())
|
||||
for p in (0.2, 1.43):
|
||||
A_power = fractional_matrix_power(A, p)
|
||||
A_round_trip = fractional_matrix_power(A_power, 1/p)
|
||||
assert_allclose(A_round_trip, A)
|
||||
|
||||
def test_opposite_sign_complex_eigenvalues(self):
|
||||
M = [[2j, 4], [0, -2j]]
|
||||
R = [[1+1j, 2], [0, 1-1j]]
|
||||
assert_allclose(np.dot(R, R), M, atol=1e-14)
|
||||
assert_allclose(fractional_matrix_power(M, 0.5), R, atol=1e-14)
|
||||
|
||||
|
||||
class TestExpM(object):
|
||||
def test_zero(self):
|
||||
a = array([[0.,0],[0,0]])
|
||||
assert_array_almost_equal(expm(a),[[1,0],[0,1]])
|
||||
|
||||
def test_single_elt(self):
|
||||
# See gh-5853
|
||||
from scipy.sparse import csc_matrix
|
||||
|
||||
vOne = -2.02683397006j
|
||||
vTwo = -2.12817566856j
|
||||
|
||||
mOne = csc_matrix([[vOne]], dtype='complex')
|
||||
mTwo = csc_matrix([[vTwo]], dtype='complex')
|
||||
|
||||
outOne = expm(mOne)
|
||||
outTwo = expm(mTwo)
|
||||
|
||||
assert_equal(type(outOne), type(mOne))
|
||||
assert_equal(type(outTwo), type(mTwo))
|
||||
|
||||
assert_allclose(outOne[0, 0], complex(-0.44039415155949196,
|
||||
-0.8978045395698304))
|
||||
assert_allclose(outTwo[0, 0], complex(-0.52896401032626006,
|
||||
-0.84864425749518878))
|
||||
|
||||
def test_empty_matrix_input(self):
|
||||
# handle gh-11082
|
||||
A = np.zeros((0, 0))
|
||||
result = expm(A)
|
||||
assert result.size == 0
|
||||
|
||||
|
||||
class TestExpmFrechet(object):
|
||||
|
||||
def test_expm_frechet(self):
|
||||
# a test of the basic functionality
|
||||
M = np.array([
|
||||
[1, 2, 3, 4],
|
||||
[5, 6, 7, 8],
|
||||
[0, 0, 1, 2],
|
||||
[0, 0, 5, 6],
|
||||
], dtype=float)
|
||||
A = np.array([
|
||||
[1, 2],
|
||||
[5, 6],
|
||||
], dtype=float)
|
||||
E = np.array([
|
||||
[3, 4],
|
||||
[7, 8],
|
||||
], dtype=float)
|
||||
expected_expm = scipy.linalg.expm(A)
|
||||
expected_frechet = scipy.linalg.expm(M)[:2, 2:]
|
||||
for kwargs in ({}, {'method':'SPS'}, {'method':'blockEnlarge'}):
|
||||
observed_expm, observed_frechet = expm_frechet(A, E, **kwargs)
|
||||
assert_allclose(expected_expm, observed_expm)
|
||||
assert_allclose(expected_frechet, observed_frechet)
|
||||
|
||||
def test_small_norm_expm_frechet(self):
|
||||
# methodically test matrices with a range of norms, for better coverage
|
||||
M_original = np.array([
|
||||
[1, 2, 3, 4],
|
||||
[5, 6, 7, 8],
|
||||
[0, 0, 1, 2],
|
||||
[0, 0, 5, 6],
|
||||
], dtype=float)
|
||||
A_original = np.array([
|
||||
[1, 2],
|
||||
[5, 6],
|
||||
], dtype=float)
|
||||
E_original = np.array([
|
||||
[3, 4],
|
||||
[7, 8],
|
||||
], dtype=float)
|
||||
A_original_norm_1 = scipy.linalg.norm(A_original, 1)
|
||||
selected_m_list = [1, 3, 5, 7, 9, 11, 13, 15]
|
||||
m_neighbor_pairs = zip(selected_m_list[:-1], selected_m_list[1:])
|
||||
for ma, mb in m_neighbor_pairs:
|
||||
ell_a = scipy.linalg._expm_frechet.ell_table_61[ma]
|
||||
ell_b = scipy.linalg._expm_frechet.ell_table_61[mb]
|
||||
target_norm_1 = 0.5 * (ell_a + ell_b)
|
||||
scale = target_norm_1 / A_original_norm_1
|
||||
M = scale * M_original
|
||||
A = scale * A_original
|
||||
E = scale * E_original
|
||||
expected_expm = scipy.linalg.expm(A)
|
||||
expected_frechet = scipy.linalg.expm(M)[:2, 2:]
|
||||
observed_expm, observed_frechet = expm_frechet(A, E)
|
||||
assert_allclose(expected_expm, observed_expm)
|
||||
assert_allclose(expected_frechet, observed_frechet)
|
||||
|
||||
def test_fuzz(self):
|
||||
# try a bunch of crazy inputs
|
||||
rfuncs = (
|
||||
np.random.uniform,
|
||||
np.random.normal,
|
||||
np.random.standard_cauchy,
|
||||
np.random.exponential)
|
||||
ntests = 100
|
||||
for i in range(ntests):
|
||||
rfunc = random.choice(rfuncs)
|
||||
target_norm_1 = random.expovariate(1.0)
|
||||
n = random.randrange(2, 16)
|
||||
A_original = rfunc(size=(n,n))
|
||||
E_original = rfunc(size=(n,n))
|
||||
A_original_norm_1 = scipy.linalg.norm(A_original, 1)
|
||||
scale = target_norm_1 / A_original_norm_1
|
||||
A = scale * A_original
|
||||
E = scale * E_original
|
||||
M = np.vstack([
|
||||
np.hstack([A, E]),
|
||||
np.hstack([np.zeros_like(A), A])])
|
||||
expected_expm = scipy.linalg.expm(A)
|
||||
expected_frechet = scipy.linalg.expm(M)[:n, n:]
|
||||
observed_expm, observed_frechet = expm_frechet(A, E)
|
||||
assert_allclose(expected_expm, observed_expm)
|
||||
assert_allclose(expected_frechet, observed_frechet)
|
||||
|
||||
def test_problematic_matrix(self):
|
||||
# this test case uncovered a bug which has since been fixed
|
||||
A = np.array([
|
||||
[1.50591997, 1.93537998],
|
||||
[0.41203263, 0.23443516],
|
||||
], dtype=float)
|
||||
E = np.array([
|
||||
[1.87864034, 2.07055038],
|
||||
[1.34102727, 0.67341123],
|
||||
], dtype=float)
|
||||
scipy.linalg.norm(A, 1)
|
||||
sps_expm, sps_frechet = expm_frechet(
|
||||
A, E, method='SPS')
|
||||
blockEnlarge_expm, blockEnlarge_frechet = expm_frechet(
|
||||
A, E, method='blockEnlarge')
|
||||
assert_allclose(sps_expm, blockEnlarge_expm)
|
||||
assert_allclose(sps_frechet, blockEnlarge_frechet)
|
||||
|
||||
@pytest.mark.slow
|
||||
@pytest.mark.skip(reason='this test is deliberately slow')
|
||||
def test_medium_matrix(self):
|
||||
# profile this to see the speed difference
|
||||
n = 1000
|
||||
A = np.random.exponential(size=(n, n))
|
||||
E = np.random.exponential(size=(n, n))
|
||||
sps_expm, sps_frechet = expm_frechet(
|
||||
A, E, method='SPS')
|
||||
blockEnlarge_expm, blockEnlarge_frechet = expm_frechet(
|
||||
A, E, method='blockEnlarge')
|
||||
assert_allclose(sps_expm, blockEnlarge_expm)
|
||||
assert_allclose(sps_frechet, blockEnlarge_frechet)
|
||||
|
||||
|
||||
def _help_expm_cond_search(A, A_norm, X, X_norm, eps, p):
|
||||
p = np.reshape(p, A.shape)
|
||||
p_norm = norm(p)
|
||||
perturbation = eps * p * (A_norm / p_norm)
|
||||
X_prime = expm(A + perturbation)
|
||||
scaled_relative_error = norm(X_prime - X) / (X_norm * eps)
|
||||
return -scaled_relative_error
|
||||
|
||||
|
||||
def _normalized_like(A, B):
|
||||
return A * (scipy.linalg.norm(B) / scipy.linalg.norm(A))
|
||||
|
||||
|
||||
def _relative_error(f, A, perturbation):
|
||||
X = f(A)
|
||||
X_prime = f(A + perturbation)
|
||||
return norm(X_prime - X) / norm(X)
|
||||
|
||||
|
||||
class TestExpmConditionNumber(object):
|
||||
def test_expm_cond_smoke(self):
|
||||
np.random.seed(1234)
|
||||
for n in range(1, 4):
|
||||
A = np.random.randn(n, n)
|
||||
kappa = expm_cond(A)
|
||||
assert_array_less(0, kappa)
|
||||
|
||||
def test_expm_bad_condition_number(self):
|
||||
A = np.array([
|
||||
[-1.128679820, 9.614183771e4, -4.524855739e9, 2.924969411e14],
|
||||
[0, -1.201010529, 9.634696872e4, -4.681048289e9],
|
||||
[0, 0, -1.132893222, 9.532491830e4],
|
||||
[0, 0, 0, -1.179475332],
|
||||
])
|
||||
kappa = expm_cond(A)
|
||||
assert_array_less(1e36, kappa)
|
||||
|
||||
def test_univariate(self):
|
||||
np.random.seed(12345)
|
||||
for x in np.linspace(-5, 5, num=11):
|
||||
A = np.array([[x]])
|
||||
assert_allclose(expm_cond(A), abs(x))
|
||||
for x in np.logspace(-2, 2, num=11):
|
||||
A = np.array([[x]])
|
||||
assert_allclose(expm_cond(A), abs(x))
|
||||
for i in range(10):
|
||||
A = np.random.randn(1, 1)
|
||||
assert_allclose(expm_cond(A), np.absolute(A)[0, 0])
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_expm_cond_fuzz(self):
|
||||
np.random.seed(12345)
|
||||
eps = 1e-5
|
||||
nsamples = 10
|
||||
for i in range(nsamples):
|
||||
n = np.random.randint(2, 5)
|
||||
A = np.random.randn(n, n)
|
||||
A_norm = scipy.linalg.norm(A)
|
||||
X = expm(A)
|
||||
X_norm = scipy.linalg.norm(X)
|
||||
kappa = expm_cond(A)
|
||||
|
||||
# Look for the small perturbation that gives the greatest
|
||||
# relative error.
|
||||
f = functools.partial(_help_expm_cond_search,
|
||||
A, A_norm, X, X_norm, eps)
|
||||
guess = np.ones(n*n)
|
||||
out = minimize(f, guess, method='L-BFGS-B')
|
||||
xopt = out.x
|
||||
yopt = f(xopt)
|
||||
p_best = eps * _normalized_like(np.reshape(xopt, A.shape), A)
|
||||
p_best_relerr = _relative_error(expm, A, p_best)
|
||||
assert_allclose(p_best_relerr, -yopt * eps)
|
||||
|
||||
# Check that the identified perturbation indeed gives greater
|
||||
# relative error than random perturbations with similar norms.
|
||||
for j in range(5):
|
||||
p_rand = eps * _normalized_like(np.random.randn(*A.shape), A)
|
||||
assert_allclose(norm(p_best), norm(p_rand))
|
||||
p_rand_relerr = _relative_error(expm, A, p_rand)
|
||||
assert_array_less(p_rand_relerr, p_best_relerr)
|
||||
|
||||
# The greatest relative error should not be much greater than
|
||||
# eps times the condition number kappa.
|
||||
# In the limit as eps approaches zero it should never be greater.
|
||||
assert_array_less(p_best_relerr, (1 + 2*eps) * eps * kappa)
|
||||
|
||||
|
||||
class TestKhatriRao(object):
|
||||
|
||||
def test_basic(self):
|
||||
a = khatri_rao(array([[1, 2], [3, 4]]),
|
||||
array([[5, 6], [7, 8]]))
|
||||
|
||||
assert_array_equal(a, array([[5, 12],
|
||||
[7, 16],
|
||||
[15, 24],
|
||||
[21, 32]]))
|
||||
|
||||
b = khatri_rao(np.empty([2, 2]), np.empty([2, 2]))
|
||||
assert_array_equal(b.shape, (4, 2))
|
||||
|
||||
def test_number_of_columns_equality(self):
|
||||
with pytest.raises(ValueError):
|
||||
a = array([[1, 2, 3],
|
||||
[4, 5, 6]])
|
||||
b = array([[1, 2],
|
||||
[3, 4]])
|
||||
khatri_rao(a, b)
|
||||
|
||||
def test_to_assure_2d_array(self):
|
||||
with pytest.raises(ValueError):
|
||||
# both arrays are 1-D
|
||||
a = array([1, 2, 3])
|
||||
b = array([4, 5, 6])
|
||||
khatri_rao(a, b)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
# first array is 1-D
|
||||
a = array([1, 2, 3])
|
||||
b = array([
|
||||
[1, 2, 3],
|
||||
[4, 5, 6]
|
||||
])
|
||||
khatri_rao(a, b)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
# second array is 1-D
|
||||
a = array([
|
||||
[1, 2, 3],
|
||||
[7, 8, 9]
|
||||
])
|
||||
b = array([4, 5, 6])
|
||||
khatri_rao(a, b)
|
||||
|
||||
def test_equality_of_two_equations(self):
|
||||
a = array([[1, 2], [3, 4]])
|
||||
b = array([[5, 6], [7, 8]])
|
||||
|
||||
res1 = khatri_rao(a, b)
|
||||
res2 = np.vstack([np.kron(a[:, k], b[:, k])
|
||||
for k in range(b.shape[1])]).T
|
||||
|
||||
assert_array_equal(res1, res2)
|
191
venv/Lib/site-packages/scipy/linalg/tests/test_procrustes.py
Normal file
191
venv/Lib/site-packages/scipy/linalg/tests/test_procrustes.py
Normal file
|
@ -0,0 +1,191 @@
|
|||
from itertools import product, permutations
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_less, assert_allclose
|
||||
from pytest import raises as assert_raises
|
||||
|
||||
from scipy.linalg import inv, eigh, norm
|
||||
from scipy.linalg import orthogonal_procrustes
|
||||
from scipy.sparse.sputils import matrix
|
||||
|
||||
|
||||
def test_orthogonal_procrustes_ndim_too_large():
|
||||
np.random.seed(1234)
|
||||
A = np.random.randn(3, 4, 5)
|
||||
B = np.random.randn(3, 4, 5)
|
||||
assert_raises(ValueError, orthogonal_procrustes, A, B)
|
||||
|
||||
|
||||
def test_orthogonal_procrustes_ndim_too_small():
|
||||
np.random.seed(1234)
|
||||
A = np.random.randn(3)
|
||||
B = np.random.randn(3)
|
||||
assert_raises(ValueError, orthogonal_procrustes, A, B)
|
||||
|
||||
|
||||
def test_orthogonal_procrustes_shape_mismatch():
|
||||
np.random.seed(1234)
|
||||
shapes = ((3, 3), (3, 4), (4, 3), (4, 4))
|
||||
for a, b in permutations(shapes, 2):
|
||||
A = np.random.randn(*a)
|
||||
B = np.random.randn(*b)
|
||||
assert_raises(ValueError, orthogonal_procrustes, A, B)
|
||||
|
||||
|
||||
def test_orthogonal_procrustes_checkfinite_exception():
|
||||
np.random.seed(1234)
|
||||
m, n = 2, 3
|
||||
A_good = np.random.randn(m, n)
|
||||
B_good = np.random.randn(m, n)
|
||||
for bad_value in np.inf, -np.inf, np.nan:
|
||||
A_bad = A_good.copy()
|
||||
A_bad[1, 2] = bad_value
|
||||
B_bad = B_good.copy()
|
||||
B_bad[1, 2] = bad_value
|
||||
for A, B in ((A_good, B_bad), (A_bad, B_good), (A_bad, B_bad)):
|
||||
assert_raises(ValueError, orthogonal_procrustes, A, B)
|
||||
|
||||
|
||||
def test_orthogonal_procrustes_scale_invariance():
|
||||
np.random.seed(1234)
|
||||
m, n = 4, 3
|
||||
for i in range(3):
|
||||
A_orig = np.random.randn(m, n)
|
||||
B_orig = np.random.randn(m, n)
|
||||
R_orig, s = orthogonal_procrustes(A_orig, B_orig)
|
||||
for A_scale in np.square(np.random.randn(3)):
|
||||
for B_scale in np.square(np.random.randn(3)):
|
||||
R, s = orthogonal_procrustes(A_orig * A_scale, B_orig * B_scale)
|
||||
assert_allclose(R, R_orig)
|
||||
|
||||
|
||||
def test_orthogonal_procrustes_array_conversion():
|
||||
np.random.seed(1234)
|
||||
for m, n in ((6, 4), (4, 4), (4, 6)):
|
||||
A_arr = np.random.randn(m, n)
|
||||
B_arr = np.random.randn(m, n)
|
||||
As = (A_arr, A_arr.tolist(), matrix(A_arr))
|
||||
Bs = (B_arr, B_arr.tolist(), matrix(B_arr))
|
||||
R_arr, s = orthogonal_procrustes(A_arr, B_arr)
|
||||
AR_arr = A_arr.dot(R_arr)
|
||||
for A, B in product(As, Bs):
|
||||
R, s = orthogonal_procrustes(A, B)
|
||||
AR = A_arr.dot(R)
|
||||
assert_allclose(AR, AR_arr)
|
||||
|
||||
|
||||
def test_orthogonal_procrustes():
|
||||
np.random.seed(1234)
|
||||
for m, n in ((6, 4), (4, 4), (4, 6)):
|
||||
# Sample a random target matrix.
|
||||
B = np.random.randn(m, n)
|
||||
# Sample a random orthogonal matrix
|
||||
# by computing eigh of a sampled symmetric matrix.
|
||||
X = np.random.randn(n, n)
|
||||
w, V = eigh(X.T + X)
|
||||
assert_allclose(inv(V), V.T)
|
||||
# Compute a matrix with a known orthogonal transformation that gives B.
|
||||
A = np.dot(B, V.T)
|
||||
# Check that an orthogonal transformation from A to B can be recovered.
|
||||
R, s = orthogonal_procrustes(A, B)
|
||||
assert_allclose(inv(R), R.T)
|
||||
assert_allclose(A.dot(R), B)
|
||||
# Create a perturbed input matrix.
|
||||
A_perturbed = A + 1e-2 * np.random.randn(m, n)
|
||||
# Check that the orthogonal procrustes function can find an orthogonal
|
||||
# transformation that is better than the orthogonal transformation
|
||||
# computed from the original input matrix.
|
||||
R_prime, s = orthogonal_procrustes(A_perturbed, B)
|
||||
assert_allclose(inv(R_prime), R_prime.T)
|
||||
# Compute the naive and optimal transformations of the perturbed input.
|
||||
naive_approx = A_perturbed.dot(R)
|
||||
optim_approx = A_perturbed.dot(R_prime)
|
||||
# Compute the Frobenius norm errors of the matrix approximations.
|
||||
naive_approx_error = norm(naive_approx - B, ord='fro')
|
||||
optim_approx_error = norm(optim_approx - B, ord='fro')
|
||||
# Check that the orthogonal Procrustes approximation is better.
|
||||
assert_array_less(optim_approx_error, naive_approx_error)
|
||||
|
||||
|
||||
def _centered(A):
|
||||
mu = A.mean(axis=0)
|
||||
return A - mu, mu
|
||||
|
||||
|
||||
def test_orthogonal_procrustes_exact_example():
|
||||
# Check a small application.
|
||||
# It uses translation, scaling, reflection, and rotation.
|
||||
#
|
||||
# |
|
||||
# a b |
|
||||
# |
|
||||
# d c | w
|
||||
# |
|
||||
# --------+--- x ----- z ---
|
||||
# |
|
||||
# | y
|
||||
# |
|
||||
#
|
||||
A_orig = np.array([[-3, 3], [-2, 3], [-2, 2], [-3, 2]], dtype=float)
|
||||
B_orig = np.array([[3, 2], [1, 0], [3, -2], [5, 0]], dtype=float)
|
||||
A, A_mu = _centered(A_orig)
|
||||
B, B_mu = _centered(B_orig)
|
||||
R, s = orthogonal_procrustes(A, B)
|
||||
scale = s / np.square(norm(A))
|
||||
B_approx = scale * np.dot(A, R) + B_mu
|
||||
assert_allclose(B_approx, B_orig, atol=1e-8)
|
||||
|
||||
|
||||
def test_orthogonal_procrustes_stretched_example():
|
||||
# Try again with a target with a stretched y axis.
|
||||
A_orig = np.array([[-3, 3], [-2, 3], [-2, 2], [-3, 2]], dtype=float)
|
||||
B_orig = np.array([[3, 40], [1, 0], [3, -40], [5, 0]], dtype=float)
|
||||
A, A_mu = _centered(A_orig)
|
||||
B, B_mu = _centered(B_orig)
|
||||
R, s = orthogonal_procrustes(A, B)
|
||||
scale = s / np.square(norm(A))
|
||||
B_approx = scale * np.dot(A, R) + B_mu
|
||||
expected = np.array([[3, 21], [-18, 0], [3, -21], [24, 0]], dtype=float)
|
||||
assert_allclose(B_approx, expected, atol=1e-8)
|
||||
# Check disparity symmetry.
|
||||
expected_disparity = 0.4501246882793018
|
||||
AB_disparity = np.square(norm(B_approx - B_orig) / norm(B))
|
||||
assert_allclose(AB_disparity, expected_disparity)
|
||||
R, s = orthogonal_procrustes(B, A)
|
||||
scale = s / np.square(norm(B))
|
||||
A_approx = scale * np.dot(B, R) + A_mu
|
||||
BA_disparity = np.square(norm(A_approx - A_orig) / norm(A))
|
||||
assert_allclose(BA_disparity, expected_disparity)
|
||||
|
||||
|
||||
def test_orthogonal_procrustes_skbio_example():
|
||||
# This transformation is also exact.
|
||||
# It uses translation, scaling, and reflection.
|
||||
#
|
||||
# |
|
||||
# | a
|
||||
# | b
|
||||
# | c d
|
||||
# --+---------
|
||||
# |
|
||||
# | w
|
||||
# |
|
||||
# | x
|
||||
# |
|
||||
# | z y
|
||||
# |
|
||||
#
|
||||
A_orig = np.array([[4, -2], [4, -4], [4, -6], [2, -6]], dtype=float)
|
||||
B_orig = np.array([[1, 3], [1, 2], [1, 1], [2, 1]], dtype=float)
|
||||
B_standardized = np.array([
|
||||
[-0.13363062, 0.6681531],
|
||||
[-0.13363062, 0.13363062],
|
||||
[-0.13363062, -0.40089186],
|
||||
[0.40089186, -0.40089186]])
|
||||
A, A_mu = _centered(A_orig)
|
||||
B, B_mu = _centered(B_orig)
|
||||
R, s = orthogonal_procrustes(A, B)
|
||||
scale = s / np.square(norm(A))
|
||||
B_approx = scale * np.dot(A, R) + B_mu
|
||||
assert_allclose(B_approx, B_orig)
|
||||
assert_allclose(B / norm(B), B_standardized)
|
118
venv/Lib/site-packages/scipy/linalg/tests/test_sketches.py
Normal file
118
venv/Lib/site-packages/scipy/linalg/tests/test_sketches.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
"""Tests for _sketches.py."""
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_, assert_equal
|
||||
from scipy.linalg import clarkson_woodruff_transform
|
||||
from scipy.linalg._sketches import cwt_matrix
|
||||
from scipy.sparse import issparse, rand
|
||||
from scipy.sparse.linalg import norm
|
||||
|
||||
|
||||
class TestClarksonWoodruffTransform(object):
|
||||
"""
|
||||
Testing the Clarkson Woodruff Transform
|
||||
"""
|
||||
# set seed for generating test matrices
|
||||
rng = np.random.RandomState(seed=1179103485)
|
||||
|
||||
# Test matrix parameters
|
||||
n_rows = 2000
|
||||
n_cols = 100
|
||||
density = 0.1
|
||||
|
||||
# Sketch matrix dimensions
|
||||
n_sketch_rows = 200
|
||||
|
||||
# Seeds to test with
|
||||
seeds = [1755490010, 934377150, 1391612830, 1752708722, 2008891431,
|
||||
1302443994, 1521083269, 1501189312, 1126232505, 1533465685]
|
||||
|
||||
A_dense = rng.randn(n_rows, n_cols)
|
||||
A_csc = rand(
|
||||
n_rows, n_cols, density=density, format='csc', random_state=rng,
|
||||
)
|
||||
A_csr = rand(
|
||||
n_rows, n_cols, density=density, format='csr', random_state=rng,
|
||||
)
|
||||
A_coo = rand(
|
||||
n_rows, n_cols, density=density, format='coo', random_state=rng,
|
||||
)
|
||||
|
||||
# Collect the test matrices
|
||||
test_matrices = [
|
||||
A_dense, A_csc, A_csr, A_coo,
|
||||
]
|
||||
|
||||
# Test vector with norm ~1
|
||||
x = rng.randn(n_rows, 1) / np.sqrt(n_rows)
|
||||
|
||||
def test_sketch_dimensions(self):
|
||||
for A in self.test_matrices:
|
||||
for seed in self.seeds:
|
||||
sketch = clarkson_woodruff_transform(
|
||||
A, self.n_sketch_rows, seed=seed
|
||||
)
|
||||
assert_(sketch.shape == (self.n_sketch_rows, self.n_cols))
|
||||
|
||||
def test_seed_returns_identical_transform_matrix(self):
|
||||
for A in self.test_matrices:
|
||||
for seed in self.seeds:
|
||||
S1 = cwt_matrix(
|
||||
self.n_sketch_rows, self.n_rows, seed=seed
|
||||
).todense()
|
||||
S2 = cwt_matrix(
|
||||
self.n_sketch_rows, self.n_rows, seed=seed
|
||||
).todense()
|
||||
assert_equal(S1, S2)
|
||||
|
||||
def test_seed_returns_identically(self):
|
||||
for A in self.test_matrices:
|
||||
for seed in self.seeds:
|
||||
sketch1 = clarkson_woodruff_transform(
|
||||
A, self.n_sketch_rows, seed=seed
|
||||
)
|
||||
sketch2 = clarkson_woodruff_transform(
|
||||
A, self.n_sketch_rows, seed=seed
|
||||
)
|
||||
if issparse(sketch1):
|
||||
sketch1 = sketch1.todense()
|
||||
if issparse(sketch2):
|
||||
sketch2 = sketch2.todense()
|
||||
assert_equal(sketch1, sketch2)
|
||||
|
||||
def test_sketch_preserves_frobenius_norm(self):
|
||||
# Given the probabilistic nature of the sketches
|
||||
# we run the test multiple times and check that
|
||||
# we pass all/almost all the tries.
|
||||
n_errors = 0
|
||||
for A in self.test_matrices:
|
||||
if issparse(A):
|
||||
true_norm = norm(A)
|
||||
else:
|
||||
true_norm = np.linalg.norm(A)
|
||||
for seed in self.seeds:
|
||||
sketch = clarkson_woodruff_transform(
|
||||
A, self.n_sketch_rows, seed=seed,
|
||||
)
|
||||
if issparse(sketch):
|
||||
sketch_norm = norm(sketch)
|
||||
else:
|
||||
sketch_norm = np.linalg.norm(sketch)
|
||||
|
||||
if np.abs(true_norm - sketch_norm) > 0.1 * true_norm:
|
||||
n_errors += 1
|
||||
assert_(n_errors == 0)
|
||||
|
||||
def test_sketch_preserves_vector_norm(self):
|
||||
n_errors = 0
|
||||
n_sketch_rows = int(np.ceil(2. / (0.01 * 0.5**2)))
|
||||
true_norm = np.linalg.norm(self.x)
|
||||
for seed in self.seeds:
|
||||
sketch = clarkson_woodruff_transform(
|
||||
self.x, n_sketch_rows, seed=seed,
|
||||
)
|
||||
sketch_norm = np.linalg.norm(sketch)
|
||||
|
||||
if np.abs(true_norm - sketch_norm) > 0.5 * true_norm:
|
||||
n_errors += 1
|
||||
assert_(n_errors == 0)
|
121
venv/Lib/site-packages/scipy/linalg/tests/test_solve_toeplitz.py
Normal file
121
venv/Lib/site-packages/scipy/linalg/tests/test_solve_toeplitz.py
Normal file
|
@ -0,0 +1,121 @@
|
|||
"""Test functions for linalg._solve_toeplitz module
|
||||
"""
|
||||
import numpy as np
|
||||
from scipy.linalg._solve_toeplitz import levinson
|
||||
from scipy.linalg import solve, toeplitz, solve_toeplitz
|
||||
from numpy.testing import assert_equal, assert_allclose
|
||||
|
||||
import pytest
|
||||
from pytest import raises as assert_raises
|
||||
|
||||
|
||||
def test_solve_equivalence():
|
||||
# For toeplitz matrices, solve_toeplitz() should be equivalent to solve().
|
||||
random = np.random.RandomState(1234)
|
||||
for n in (1, 2, 3, 10):
|
||||
c = random.randn(n)
|
||||
if random.rand() < 0.5:
|
||||
c = c + 1j * random.randn(n)
|
||||
r = random.randn(n)
|
||||
if random.rand() < 0.5:
|
||||
r = r + 1j * random.randn(n)
|
||||
y = random.randn(n)
|
||||
if random.rand() < 0.5:
|
||||
y = y + 1j * random.randn(n)
|
||||
|
||||
# Check equivalence when both the column and row are provided.
|
||||
actual = solve_toeplitz((c,r), y)
|
||||
desired = solve(toeplitz(c, r=r), y)
|
||||
assert_allclose(actual, desired)
|
||||
|
||||
# Check equivalence when the column is provided but not the row.
|
||||
actual = solve_toeplitz(c, b=y)
|
||||
desired = solve(toeplitz(c), y)
|
||||
assert_allclose(actual, desired)
|
||||
|
||||
|
||||
def test_multiple_rhs():
|
||||
random = np.random.RandomState(1234)
|
||||
c = random.randn(4)
|
||||
r = random.randn(4)
|
||||
for offset in [0, 1j]:
|
||||
for yshape in ((4,), (4, 3), (4, 3, 2)):
|
||||
y = random.randn(*yshape) + offset
|
||||
actual = solve_toeplitz((c,r), b=y)
|
||||
desired = solve(toeplitz(c, r=r), y)
|
||||
assert_equal(actual.shape, yshape)
|
||||
assert_equal(desired.shape, yshape)
|
||||
assert_allclose(actual, desired)
|
||||
|
||||
|
||||
def test_native_list_arguments():
|
||||
c = [1,2,4,7]
|
||||
r = [1,3,9,12]
|
||||
y = [5,1,4,2]
|
||||
actual = solve_toeplitz((c,r), y)
|
||||
desired = solve(toeplitz(c, r=r), y)
|
||||
assert_allclose(actual, desired)
|
||||
|
||||
|
||||
def test_zero_diag_error():
|
||||
# The Levinson-Durbin implementation fails when the diagonal is zero.
|
||||
random = np.random.RandomState(1234)
|
||||
n = 4
|
||||
c = random.randn(n)
|
||||
r = random.randn(n)
|
||||
y = random.randn(n)
|
||||
c[0] = 0
|
||||
assert_raises(np.linalg.LinAlgError,
|
||||
solve_toeplitz, (c, r), b=y)
|
||||
|
||||
|
||||
def test_wikipedia_counterexample():
|
||||
# The Levinson-Durbin implementation also fails in other cases.
|
||||
# This example is from the talk page of the wikipedia article.
|
||||
random = np.random.RandomState(1234)
|
||||
c = [2, 2, 1]
|
||||
y = random.randn(3)
|
||||
assert_raises(np.linalg.LinAlgError, solve_toeplitz, c, b=y)
|
||||
|
||||
|
||||
def test_reflection_coeffs():
|
||||
# check that that the partial solutions are given by the reflection
|
||||
# coefficients
|
||||
|
||||
random = np.random.RandomState(1234)
|
||||
y_d = random.randn(10)
|
||||
y_z = random.randn(10) + 1j
|
||||
reflection_coeffs_d = [1]
|
||||
reflection_coeffs_z = [1]
|
||||
for i in range(2, 10):
|
||||
reflection_coeffs_d.append(solve_toeplitz(y_d[:(i-1)], b=y_d[1:i])[-1])
|
||||
reflection_coeffs_z.append(solve_toeplitz(y_z[:(i-1)], b=y_z[1:i])[-1])
|
||||
|
||||
y_d_concat = np.concatenate((y_d[-2:0:-1], y_d[:-1]))
|
||||
y_z_concat = np.concatenate((y_z[-2:0:-1].conj(), y_z[:-1]))
|
||||
_, ref_d = levinson(y_d_concat, b=y_d[1:])
|
||||
_, ref_z = levinson(y_z_concat, b=y_z[1:])
|
||||
|
||||
assert_allclose(reflection_coeffs_d, ref_d[:-1])
|
||||
assert_allclose(reflection_coeffs_z, ref_z[:-1])
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason='Instability of Levinson iteration')
|
||||
def test_unstable():
|
||||
# this is a "Gaussian Toeplitz matrix", as mentioned in Example 2 of
|
||||
# I. Gohbert, T. Kailath and V. Olshevsky "Fast Gaussian Elimination with
|
||||
# Partial Pivoting for Matrices with Displacement Structure"
|
||||
# Mathematics of Computation, 64, 212 (1995), pp 1557-1576
|
||||
# which can be unstable for levinson recursion.
|
||||
|
||||
# other fast toeplitz solvers such as GKO or Burg should be better.
|
||||
random = np.random.RandomState(1234)
|
||||
n = 100
|
||||
c = 0.9 ** (np.arange(n)**2)
|
||||
y = random.randn(n)
|
||||
|
||||
solution1 = solve_toeplitz(c, b=y)
|
||||
solution2 = solve(toeplitz(c), y)
|
||||
|
||||
assert_allclose(solution1, solution2)
|
||||
|
766
venv/Lib/site-packages/scipy/linalg/tests/test_solvers.py
Normal file
766
venv/Lib/site-packages/scipy/linalg/tests/test_solvers.py
Normal file
|
@ -0,0 +1,766 @@
|
|||
import os
|
||||
import numpy as np
|
||||
|
||||
from numpy.testing import assert_array_almost_equal
|
||||
import pytest
|
||||
from pytest import raises as assert_raises
|
||||
|
||||
from scipy.linalg import solve_sylvester
|
||||
from scipy.linalg import solve_continuous_lyapunov, solve_discrete_lyapunov
|
||||
from scipy.linalg import solve_continuous_are, solve_discrete_are
|
||||
from scipy.linalg import block_diag, solve, LinAlgError
|
||||
from scipy.sparse.sputils import matrix
|
||||
|
||||
|
||||
def _load_data(name):
|
||||
"""
|
||||
Load npz data file under data/
|
||||
Returns a copy of the data, rather than keeping the npz file open.
|
||||
"""
|
||||
filename = os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
||||
'data', name)
|
||||
with np.load(filename) as f:
|
||||
return dict(f.items())
|
||||
|
||||
|
||||
class TestSolveLyapunov(object):
|
||||
|
||||
cases = [
|
||||
(np.array([[1, 2], [3, 4]]),
|
||||
np.array([[9, 10], [11, 12]])),
|
||||
# a, q all complex.
|
||||
(np.array([[1.0+1j, 2.0], [3.0-4.0j, 5.0]]),
|
||||
np.array([[2.0-2j, 2.0+2j], [-1.0-1j, 2.0]])),
|
||||
# a real; q complex.
|
||||
(np.array([[1.0, 2.0], [3.0, 5.0]]),
|
||||
np.array([[2.0-2j, 2.0+2j], [-1.0-1j, 2.0]])),
|
||||
# a complex; q real.
|
||||
(np.array([[1.0+1j, 2.0], [3.0-4.0j, 5.0]]),
|
||||
np.array([[2.0, 2.0], [-1.0, 2.0]])),
|
||||
# An example from Kitagawa, 1977
|
||||
(np.array([[3, 9, 5, 1, 4], [1, 2, 3, 8, 4], [4, 6, 6, 6, 3],
|
||||
[1, 5, 2, 0, 7], [5, 3, 3, 1, 5]]),
|
||||
np.array([[2, 4, 1, 0, 1], [4, 1, 0, 2, 0], [1, 0, 3, 0, 3],
|
||||
[0, 2, 0, 1, 0], [1, 0, 3, 0, 4]])),
|
||||
# Companion matrix example. a complex; q real; a.shape[0] = 11
|
||||
(np.array([[0.100+0.j, 0.091+0.j, 0.082+0.j, 0.073+0.j, 0.064+0.j,
|
||||
0.055+0.j, 0.046+0.j, 0.037+0.j, 0.028+0.j, 0.019+0.j,
|
||||
0.010+0.j],
|
||||
[1.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j],
|
||||
[0.000+0.j, 1.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j],
|
||||
[0.000+0.j, 0.000+0.j, 1.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j],
|
||||
[0.000+0.j, 0.000+0.j, 0.000+0.j, 1.000+0.j, 0.000+0.j,
|
||||
0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j],
|
||||
[0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 1.000+0.j,
|
||||
0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j],
|
||||
[0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
1.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j],
|
||||
[0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j, 1.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j],
|
||||
[0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j, 0.000+0.j, 1.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j],
|
||||
[0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j, 0.000+0.j, 0.000+0.j, 1.000+0.j, 0.000+0.j,
|
||||
0.000+0.j],
|
||||
[0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j,
|
||||
0.000+0.j, 0.000+0.j, 0.000+0.j, 0.000+0.j, 1.000+0.j,
|
||||
0.000+0.j]]),
|
||||
np.eye(11)),
|
||||
# https://github.com/scipy/scipy/issues/4176
|
||||
(matrix([[0, 1], [-1/2, -1]]),
|
||||
(matrix([0, 3]).T @ matrix([0, 3]).T.T)),
|
||||
# https://github.com/scipy/scipy/issues/4176
|
||||
(matrix([[0, 1], [-1/2, -1]]),
|
||||
(np.array(matrix([0, 3]).T @ matrix([0, 3]).T.T))),
|
||||
]
|
||||
|
||||
def test_continuous_squareness_and_shape(self):
|
||||
nsq = np.ones((3, 2))
|
||||
sq = np.eye(3)
|
||||
assert_raises(ValueError, solve_continuous_lyapunov, nsq, sq)
|
||||
assert_raises(ValueError, solve_continuous_lyapunov, sq, nsq)
|
||||
assert_raises(ValueError, solve_continuous_lyapunov, sq, np.eye(2))
|
||||
|
||||
def check_continuous_case(self, a, q):
|
||||
x = solve_continuous_lyapunov(a, q)
|
||||
assert_array_almost_equal(
|
||||
np.dot(a, x) + np.dot(x, a.conj().transpose()), q)
|
||||
|
||||
def check_discrete_case(self, a, q, method=None):
|
||||
x = solve_discrete_lyapunov(a, q, method=method)
|
||||
assert_array_almost_equal(
|
||||
np.dot(np.dot(a, x), a.conj().transpose()) - x, -1.0*q)
|
||||
|
||||
def test_cases(self):
|
||||
for case in self.cases:
|
||||
self.check_continuous_case(case[0], case[1])
|
||||
self.check_discrete_case(case[0], case[1])
|
||||
self.check_discrete_case(case[0], case[1], method='direct')
|
||||
self.check_discrete_case(case[0], case[1], method='bilinear')
|
||||
|
||||
|
||||
def test_solve_continuous_are():
|
||||
mat6 = _load_data('carex_6_data.npz')
|
||||
mat15 = _load_data('carex_15_data.npz')
|
||||
mat18 = _load_data('carex_18_data.npz')
|
||||
mat19 = _load_data('carex_19_data.npz')
|
||||
mat20 = _load_data('carex_20_data.npz')
|
||||
cases = [
|
||||
# Carex examples taken from (with default parameters):
|
||||
# [1] P.BENNER, A.J. LAUB, V. MEHRMANN: 'A Collection of Benchmark
|
||||
# Examples for the Numerical Solution of Algebraic Riccati
|
||||
# Equations II: Continuous-Time Case', Tech. Report SPC 95_23,
|
||||
# Fak. f. Mathematik, TU Chemnitz-Zwickau (Germany), 1995.
|
||||
#
|
||||
# The format of the data is (a, b, q, r, knownfailure), where
|
||||
# knownfailure is None if the test passes or a string
|
||||
# indicating the reason for failure.
|
||||
#
|
||||
# Test Case 0: carex #1
|
||||
(np.diag([1.], 1),
|
||||
np.array([[0], [1]]),
|
||||
block_diag(1., 2.),
|
||||
1,
|
||||
None),
|
||||
# Test Case 1: carex #2
|
||||
(np.array([[4, 3], [-4.5, -3.5]]),
|
||||
np.array([[1], [-1]]),
|
||||
np.array([[9, 6], [6, 4.]]),
|
||||
1,
|
||||
None),
|
||||
# Test Case 2: carex #3
|
||||
(np.array([[0, 1, 0, 0],
|
||||
[0, -1.89, 0.39, -5.53],
|
||||
[0, -0.034, -2.98, 2.43],
|
||||
[0.034, -0.0011, -0.99, -0.21]]),
|
||||
np.array([[0, 0], [0.36, -1.6], [-0.95, -0.032], [0.03, 0]]),
|
||||
np.array([[2.313, 2.727, 0.688, 0.023],
|
||||
[2.727, 4.271, 1.148, 0.323],
|
||||
[0.688, 1.148, 0.313, 0.102],
|
||||
[0.023, 0.323, 0.102, 0.083]]),
|
||||
np.eye(2),
|
||||
None),
|
||||
# Test Case 3: carex #4
|
||||
(np.array([[-0.991, 0.529, 0, 0, 0, 0, 0, 0],
|
||||
[0.522, -1.051, 0.596, 0, 0, 0, 0, 0],
|
||||
[0, 0.522, -1.118, 0.596, 0, 0, 0, 0],
|
||||
[0, 0, 0.522, -1.548, 0.718, 0, 0, 0],
|
||||
[0, 0, 0, 0.922, -1.64, 0.799, 0, 0],
|
||||
[0, 0, 0, 0, 0.922, -1.721, 0.901, 0],
|
||||
[0, 0, 0, 0, 0, 0.922, -1.823, 1.021],
|
||||
[0, 0, 0, 0, 0, 0, 0.922, -1.943]]),
|
||||
np.array([[3.84, 4.00, 37.60, 3.08, 2.36, 2.88, 3.08, 3.00],
|
||||
[-2.88, -3.04, -2.80, -2.32, -3.32, -3.82, -4.12, -3.96]]
|
||||
).T * 0.001,
|
||||
np.array([[1.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.1],
|
||||
[0.0, 1.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0],
|
||||
[0.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.0, 0.0],
|
||||
[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.5, 0.1, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0],
|
||||
[0.0, 0.0, 0.5, 0.0, 0.0, 0.1, 0.0, 0.0],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0],
|
||||
[0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1]]),
|
||||
np.eye(2),
|
||||
None),
|
||||
# Test Case 4: carex #5
|
||||
(np.array(
|
||||
[[-4.019, 5.120, 0., 0., -2.082, 0., 0., 0., 0.870],
|
||||
[-0.346, 0.986, 0., 0., -2.340, 0., 0., 0., 0.970],
|
||||
[-7.909, 15.407, -4.069, 0., -6.450, 0., 0., 0., 2.680],
|
||||
[-21.816, 35.606, -0.339, -3.870, -17.800, 0., 0., 0., 7.390],
|
||||
[-60.196, 98.188, -7.907, 0.340, -53.008, 0., 0., 0., 20.400],
|
||||
[0, 0, 0, 0, 94.000, -147.200, 0., 53.200, 0.],
|
||||
[0, 0, 0, 0, 0, 94.000, -147.200, 0, 0],
|
||||
[0, 0, 0, 0, 0, 12.800, 0.000, -31.600, 0],
|
||||
[0, 0, 0, 0, 12.800, 0.000, 0.000, 18.800, -31.600]]),
|
||||
np.array([[0.010, -0.011, -0.151],
|
||||
[0.003, -0.021, 0.000],
|
||||
[0.009, -0.059, 0.000],
|
||||
[0.024, -0.162, 0.000],
|
||||
[0.068, -0.445, 0.000],
|
||||
[0.000, 0.000, 0.000],
|
||||
[0.000, 0.000, 0.000],
|
||||
[0.000, 0.000, 0.000],
|
||||
[0.000, 0.000, 0.000]]),
|
||||
np.eye(9),
|
||||
np.eye(3),
|
||||
None),
|
||||
# Test Case 5: carex #6
|
||||
(mat6['A'], mat6['B'], mat6['Q'], mat6['R'], None),
|
||||
# Test Case 6: carex #7
|
||||
(np.array([[1, 0], [0, -2.]]),
|
||||
np.array([[1e-6], [0]]),
|
||||
np.ones((2, 2)),
|
||||
1.,
|
||||
'Bad residual accuracy'),
|
||||
# Test Case 7: carex #8
|
||||
(block_diag(-0.1, -0.02),
|
||||
np.array([[0.100, 0.000], [0.001, 0.010]]),
|
||||
np.array([[100, 1000], [1000, 10000]]),
|
||||
np.ones((2, 2)) + block_diag(1e-6, 0),
|
||||
None),
|
||||
# Test Case 8: carex #9
|
||||
(np.array([[0, 1e6], [0, 0]]),
|
||||
np.array([[0], [1.]]),
|
||||
np.eye(2),
|
||||
1.,
|
||||
None),
|
||||
# Test Case 9: carex #10
|
||||
(np.array([[1.0000001, 1], [1., 1.0000001]]),
|
||||
np.eye(2),
|
||||
np.eye(2),
|
||||
np.eye(2),
|
||||
None),
|
||||
# Test Case 10: carex #11
|
||||
(np.array([[3, 1.], [4, 2]]),
|
||||
np.array([[1], [1]]),
|
||||
np.array([[-11, -5], [-5, -2.]]),
|
||||
1.,
|
||||
None),
|
||||
# Test Case 11: carex #12
|
||||
(np.array([[7000000., 2000000., -0.],
|
||||
[2000000., 6000000., -2000000.],
|
||||
[0., -2000000., 5000000.]]) / 3,
|
||||
np.eye(3),
|
||||
np.array([[1., -2., -2.], [-2., 1., -2.], [-2., -2., 1.]]).dot(
|
||||
np.diag([1e-6, 1, 1e6])).dot(
|
||||
np.array([[1., -2., -2.], [-2., 1., -2.], [-2., -2., 1.]])) / 9,
|
||||
np.eye(3) * 1e6,
|
||||
'Bad Residual Accuracy'),
|
||||
# Test Case 12: carex #13
|
||||
(np.array([[0, 0.4, 0, 0],
|
||||
[0, 0, 0.345, 0],
|
||||
[0, -0.524e6, -0.465e6, 0.262e6],
|
||||
[0, 0, 0, -1e6]]),
|
||||
np.array([[0, 0, 0, 1e6]]).T,
|
||||
np.diag([1, 0, 1, 0]),
|
||||
1.,
|
||||
None),
|
||||
# Test Case 13: carex #14
|
||||
(np.array([[-1e-6, 1, 0, 0],
|
||||
[-1, -1e-6, 0, 0],
|
||||
[0, 0, 1e-6, 1],
|
||||
[0, 0, -1, 1e-6]]),
|
||||
np.ones((4, 1)),
|
||||
np.ones((4, 4)),
|
||||
1.,
|
||||
None),
|
||||
# Test Case 14: carex #15
|
||||
(mat15['A'], mat15['B'], mat15['Q'], mat15['R'], None),
|
||||
# Test Case 15: carex #16
|
||||
(np.eye(64, 64, k=-1) + np.eye(64, 64)*(-2.) + np.rot90(
|
||||
block_diag(1, np.zeros((62, 62)), 1)) + np.eye(64, 64, k=1),
|
||||
np.eye(64),
|
||||
np.eye(64),
|
||||
np.eye(64),
|
||||
None),
|
||||
# Test Case 16: carex #17
|
||||
(np.diag(np.ones((20, )), 1),
|
||||
np.flipud(np.eye(21, 1)),
|
||||
np.eye(21, 1) * np.eye(21, 1).T,
|
||||
1,
|
||||
'Bad Residual Accuracy'),
|
||||
# Test Case 17: carex #18
|
||||
(mat18['A'], mat18['B'], mat18['Q'], mat18['R'], None),
|
||||
# Test Case 18: carex #19
|
||||
(mat19['A'], mat19['B'], mat19['Q'], mat19['R'],
|
||||
'Bad Residual Accuracy'),
|
||||
# Test Case 19: carex #20
|
||||
(mat20['A'], mat20['B'], mat20['Q'], mat20['R'],
|
||||
'Bad Residual Accuracy')
|
||||
]
|
||||
# Makes the minimum precision requirements customized to the test.
|
||||
# Here numbers represent the number of decimals that agrees with zero
|
||||
# matrix when the solution x is plugged in to the equation.
|
||||
#
|
||||
# res = array([[8e-3,1e-16],[1e-16,1e-20]]) --> min_decimal[k] = 2
|
||||
#
|
||||
# If the test is failing use "None" for that entry.
|
||||
#
|
||||
min_decimal = (14, 12, 13, 14, 11, 6, None, 5, 7, 14, 14,
|
||||
None, 9, 14, 13, 14, None, 12, None, None)
|
||||
|
||||
def _test_factory(case, dec):
|
||||
"""Checks if 0 = XA + A'X - XB(R)^{-1} B'X + Q is true"""
|
||||
a, b, q, r, knownfailure = case
|
||||
if knownfailure:
|
||||
pytest.xfail(reason=knownfailure)
|
||||
|
||||
x = solve_continuous_are(a, b, q, r)
|
||||
res = x.dot(a) + a.conj().T.dot(x) + q
|
||||
out_fact = x.dot(b)
|
||||
res -= out_fact.dot(solve(np.atleast_2d(r), out_fact.conj().T))
|
||||
assert_array_almost_equal(res, np.zeros_like(res), decimal=dec)
|
||||
|
||||
for ind, case in enumerate(cases):
|
||||
_test_factory(case, min_decimal[ind])
|
||||
|
||||
|
||||
def test_solve_discrete_are():
|
||||
|
||||
cases = [
|
||||
# Darex examples taken from (with default parameters):
|
||||
# [1] P.BENNER, A.J. LAUB, V. MEHRMANN: 'A Collection of Benchmark
|
||||
# Examples for the Numerical Solution of Algebraic Riccati
|
||||
# Equations II: Discrete-Time Case', Tech. Report SPC 95_23,
|
||||
# Fak. f. Mathematik, TU Chemnitz-Zwickau (Germany), 1995.
|
||||
# [2] T. GUDMUNDSSON, C. KENNEY, A.J. LAUB: 'Scaling of the
|
||||
# Discrete-Time Algebraic Riccati Equation to Enhance Stability
|
||||
# of the Schur Solution Method', IEEE Trans.Aut.Cont., vol.37(4)
|
||||
#
|
||||
# The format of the data is (a, b, q, r, knownfailure), where
|
||||
# knownfailure is None if the test passes or a string
|
||||
# indicating the reason for failure.
|
||||
#
|
||||
# TEST CASE 0 : Complex a; real b, q, r
|
||||
(np.array([[2, 1-2j], [0, -3j]]),
|
||||
np.array([[0], [1]]),
|
||||
np.array([[1, 0], [0, 2]]),
|
||||
np.array([[1]]),
|
||||
None),
|
||||
# TEST CASE 1 :Real a, q, r; complex b
|
||||
(np.array([[2, 1], [0, -1]]),
|
||||
np.array([[-2j], [1j]]),
|
||||
np.array([[1, 0], [0, 2]]),
|
||||
np.array([[1]]),
|
||||
None),
|
||||
# TEST CASE 2 : Real a, b; complex q, r
|
||||
(np.array([[3, 1], [0, -1]]),
|
||||
np.array([[1, 2], [1, 3]]),
|
||||
np.array([[1, 1+1j], [1-1j, 2]]),
|
||||
np.array([[2, -2j], [2j, 3]]),
|
||||
None),
|
||||
# TEST CASE 3 : User-reported gh-2251 (Trac #1732)
|
||||
(np.array([[0.63399379, 0.54906824, 0.76253406],
|
||||
[0.5404729, 0.53745766, 0.08731853],
|
||||
[0.27524045, 0.84922129, 0.4681622]]),
|
||||
np.array([[0.96861695], [0.05532739], [0.78934047]]),
|
||||
np.eye(3),
|
||||
np.eye(1),
|
||||
None),
|
||||
# TEST CASE 4 : darex #1
|
||||
(np.array([[4, 3], [-4.5, -3.5]]),
|
||||
np.array([[1], [-1]]),
|
||||
np.array([[9, 6], [6, 4]]),
|
||||
np.array([[1]]),
|
||||
None),
|
||||
# TEST CASE 5 : darex #2
|
||||
(np.array([[0.9512, 0], [0, 0.9048]]),
|
||||
np.array([[4.877, 4.877], [-1.1895, 3.569]]),
|
||||
np.array([[0.005, 0], [0, 0.02]]),
|
||||
np.array([[1/3, 0], [0, 3]]),
|
||||
None),
|
||||
# TEST CASE 6 : darex #3
|
||||
(np.array([[2, -1], [1, 0]]),
|
||||
np.array([[1], [0]]),
|
||||
np.array([[0, 0], [0, 1]]),
|
||||
np.array([[0]]),
|
||||
None),
|
||||
# TEST CASE 7 : darex #4 (skipped the gen. Ric. term S)
|
||||
(np.array([[0, 1], [0, -1]]),
|
||||
np.array([[1, 0], [2, 1]]),
|
||||
np.array([[-4, -4], [-4, 7]]) * (1/11),
|
||||
np.array([[9, 3], [3, 1]]),
|
||||
None),
|
||||
# TEST CASE 8 : darex #5
|
||||
(np.array([[0, 1], [0, 0]]),
|
||||
np.array([[0], [1]]),
|
||||
np.array([[1, 2], [2, 4]]),
|
||||
np.array([[1]]),
|
||||
None),
|
||||
# TEST CASE 9 : darex #6
|
||||
(np.array([[0.998, 0.067, 0, 0],
|
||||
[-.067, 0.998, 0, 0],
|
||||
[0, 0, 0.998, 0.153],
|
||||
[0, 0, -.153, 0.998]]),
|
||||
np.array([[0.0033, 0.0200],
|
||||
[0.1000, -.0007],
|
||||
[0.0400, 0.0073],
|
||||
[-.0028, 0.1000]]),
|
||||
np.array([[1.87, 0, 0, -0.244],
|
||||
[0, 0.744, 0.205, 0],
|
||||
[0, 0.205, 0.589, 0],
|
||||
[-0.244, 0, 0, 1.048]]),
|
||||
np.eye(2),
|
||||
None),
|
||||
# TEST CASE 10 : darex #7
|
||||
(np.array([[0.984750, -.079903, 0.0009054, -.0010765],
|
||||
[0.041588, 0.998990, -.0358550, 0.0126840],
|
||||
[-.546620, 0.044916, -.3299100, 0.1931800],
|
||||
[2.662400, -.100450, -.9245500, -.2632500]]),
|
||||
np.array([[0.0037112, 0.0007361],
|
||||
[-.0870510, 9.3411e-6],
|
||||
[-1.198440, -4.1378e-4],
|
||||
[-3.192700, 9.2535e-4]]),
|
||||
np.eye(4)*1e-2,
|
||||
np.eye(2),
|
||||
None),
|
||||
# TEST CASE 11 : darex #8
|
||||
(np.array([[-0.6000000, -2.2000000, -3.6000000, -5.4000180],
|
||||
[1.0000000, 0.6000000, 0.8000000, 3.3999820],
|
||||
[0.0000000, 1.0000000, 1.8000000, 3.7999820],
|
||||
[0.0000000, 0.0000000, 0.0000000, -0.9999820]]),
|
||||
np.array([[1.0, -1.0, -1.0, -1.0],
|
||||
[0.0, 1.0, -1.0, -1.0],
|
||||
[0.0, 0.0, 1.0, -1.0],
|
||||
[0.0, 0.0, 0.0, 1.0]]),
|
||||
np.array([[2, 1, 3, 6],
|
||||
[1, 2, 2, 5],
|
||||
[3, 2, 6, 11],
|
||||
[6, 5, 11, 22]]),
|
||||
np.eye(4),
|
||||
None),
|
||||
# TEST CASE 12 : darex #9
|
||||
(np.array([[95.4070, 1.9643, 0.3597, 0.0673, 0.0190],
|
||||
[40.8490, 41.3170, 16.0840, 4.4679, 1.1971],
|
||||
[12.2170, 26.3260, 36.1490, 15.9300, 12.3830],
|
||||
[4.1118, 12.8580, 27.2090, 21.4420, 40.9760],
|
||||
[0.1305, 0.5808, 1.8750, 3.6162, 94.2800]]) * 0.01,
|
||||
np.array([[0.0434, -0.0122],
|
||||
[2.6606, -1.0453],
|
||||
[3.7530, -5.5100],
|
||||
[3.6076, -6.6000],
|
||||
[0.4617, -0.9148]]) * 0.01,
|
||||
np.eye(5),
|
||||
np.eye(2),
|
||||
None),
|
||||
# TEST CASE 13 : darex #10
|
||||
(np.kron(np.eye(2), np.diag([1, 1], k=1)),
|
||||
np.kron(np.eye(2), np.array([[0], [0], [1]])),
|
||||
np.array([[1, 1, 0, 0, 0, 0],
|
||||
[1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, -1, 0],
|
||||
[0, 0, 0, -1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0]]),
|
||||
np.array([[3, 0], [0, 1]]),
|
||||
None),
|
||||
# TEST CASE 14 : darex #11
|
||||
(0.001 * np.array(
|
||||
[[870.1, 135.0, 11.59, .5014, -37.22, .3484, 0, 4.242, 7.249],
|
||||
[76.55, 897.4, 12.72, 0.5504, -40.16, .3743, 0, 4.53, 7.499],
|
||||
[-127.2, 357.5, 817, 1.455, -102.8, .987, 0, 11.85, 18.72],
|
||||
[-363.5, 633.9, 74.91, 796.6, -273.5, 2.653, 0, 31.72, 48.82],
|
||||
[-960, 1645.9, -128.9, -5.597, 71.42, 7.108, 0, 84.52, 125.9],
|
||||
[-664.4, 112.96, -88.89, -3.854, 84.47, 13.6, 0, 144.3, 101.6],
|
||||
[-410.2, 693, -54.71, -2.371, 66.49, 12.49, .1063, 99.97, 69.67],
|
||||
[-179.9, 301.7, -23.93, -1.035, 60.59, 22.16, 0, 213.9, 35.54],
|
||||
[-345.1, 580.4, -45.96, -1.989, 105.6, 19.86, 0, 219.1, 215.2]]),
|
||||
np.array([[4.7600, -0.5701, -83.6800],
|
||||
[0.8790, -4.7730, -2.7300],
|
||||
[1.4820, -13.1200, 8.8760],
|
||||
[3.8920, -35.1300, 24.8000],
|
||||
[10.3400, -92.7500, 66.8000],
|
||||
[7.2030, -61.5900, 38.3400],
|
||||
[4.4540, -36.8300, 20.2900],
|
||||
[1.9710, -15.5400, 6.9370],
|
||||
[3.7730, -30.2800, 14.6900]]) * 0.001,
|
||||
np.diag([50, 0, 0, 0, 50, 0, 0, 0, 0]),
|
||||
np.eye(3),
|
||||
None),
|
||||
# TEST CASE 15 : darex #12 - numerically least accurate example
|
||||
(np.array([[0, 1e6], [0, 0]]),
|
||||
np.array([[0], [1]]),
|
||||
np.eye(2),
|
||||
np.array([[1]]),
|
||||
None),
|
||||
# TEST CASE 16 : darex #13
|
||||
(np.array([[16, 10, -2],
|
||||
[10, 13, -8],
|
||||
[-2, -8, 7]]) * (1/9),
|
||||
np.eye(3),
|
||||
1e6 * np.eye(3),
|
||||
1e6 * np.eye(3),
|
||||
None),
|
||||
# TEST CASE 17 : darex #14
|
||||
(np.array([[1 - 1/1e8, 0, 0, 0],
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 1, 0]]),
|
||||
np.array([[1e-08], [0], [0], [0]]),
|
||||
np.diag([0, 0, 0, 1]),
|
||||
np.array([[0.25]]),
|
||||
None),
|
||||
# TEST CASE 18 : darex #15
|
||||
(np.eye(100, k=1),
|
||||
np.flipud(np.eye(100, 1)),
|
||||
np.eye(100),
|
||||
np.array([[1]]),
|
||||
None)
|
||||
]
|
||||
|
||||
# Makes the minimum precision requirements customized to the test.
|
||||
# Here numbers represent the number of decimals that agrees with zero
|
||||
# matrix when the solution x is plugged in to the equation.
|
||||
#
|
||||
# res = array([[8e-3,1e-16],[1e-16,1e-20]]) --> min_decimal[k] = 2
|
||||
#
|
||||
# If the test is failing use "None" for that entry.
|
||||
#
|
||||
min_decimal = (12, 14, 13, 14, 13, 16, 18, 14, 14, 13,
|
||||
14, 13, 13, 14, 12, 2, 5, 6, 10)
|
||||
|
||||
def _test_factory(case, dec):
|
||||
"""Checks if X = A'XA-(A'XB)(R+B'XB)^-1(B'XA)+Q) is true"""
|
||||
a, b, q, r, knownfailure = case
|
||||
if knownfailure:
|
||||
pytest.xfail(reason=knownfailure)
|
||||
|
||||
x = solve_discrete_are(a, b, q, r)
|
||||
res = a.conj().T.dot(x.dot(a)) - x + q
|
||||
res -= a.conj().T.dot(x.dot(b)).dot(
|
||||
solve(r+b.conj().T.dot(x.dot(b)), b.conj().T).dot(x.dot(a))
|
||||
)
|
||||
assert_array_almost_equal(res, np.zeros_like(res), decimal=dec)
|
||||
|
||||
for ind, case in enumerate(cases):
|
||||
_test_factory(case, min_decimal[ind])
|
||||
|
||||
# An infeasible example taken from https://arxiv.org/abs/1505.04861v1
|
||||
A = np.triu(np.ones((3, 3)))
|
||||
A[0, 1] = -1
|
||||
B = np.array([[1, 1, 0], [0, 0, 1]]).T
|
||||
Q = np.full_like(A, -2) + np.diag([8, -1, -1.9])
|
||||
R = np.diag([-10, 0.1])
|
||||
assert_raises(LinAlgError, solve_continuous_are, A, B, Q, R)
|
||||
|
||||
|
||||
def test_solve_generalized_continuous_are():
|
||||
cases = [
|
||||
# Two random examples differ by s term
|
||||
# in the absence of any literature for demanding examples.
|
||||
(np.array([[2.769230e-01, 8.234578e-01, 9.502220e-01],
|
||||
[4.617139e-02, 6.948286e-01, 3.444608e-02],
|
||||
[9.713178e-02, 3.170995e-01, 4.387444e-01]]),
|
||||
np.array([[3.815585e-01, 1.868726e-01],
|
||||
[7.655168e-01, 4.897644e-01],
|
||||
[7.951999e-01, 4.455862e-01]]),
|
||||
np.eye(3),
|
||||
np.eye(2),
|
||||
np.array([[6.463130e-01, 2.760251e-01, 1.626117e-01],
|
||||
[7.093648e-01, 6.797027e-01, 1.189977e-01],
|
||||
[7.546867e-01, 6.550980e-01, 4.983641e-01]]),
|
||||
np.zeros((3, 2)),
|
||||
None),
|
||||
(np.array([[2.769230e-01, 8.234578e-01, 9.502220e-01],
|
||||
[4.617139e-02, 6.948286e-01, 3.444608e-02],
|
||||
[9.713178e-02, 3.170995e-01, 4.387444e-01]]),
|
||||
np.array([[3.815585e-01, 1.868726e-01],
|
||||
[7.655168e-01, 4.897644e-01],
|
||||
[7.951999e-01, 4.455862e-01]]),
|
||||
np.eye(3),
|
||||
np.eye(2),
|
||||
np.array([[6.463130e-01, 2.760251e-01, 1.626117e-01],
|
||||
[7.093648e-01, 6.797027e-01, 1.189977e-01],
|
||||
[7.546867e-01, 6.550980e-01, 4.983641e-01]]),
|
||||
np.ones((3, 2)),
|
||||
None)
|
||||
]
|
||||
|
||||
min_decimal = (10, 10)
|
||||
|
||||
def _test_factory(case, dec):
|
||||
"""Checks if X = A'XA-(A'XB)(R+B'XB)^-1(B'XA)+Q) is true"""
|
||||
a, b, q, r, e, s, knownfailure = case
|
||||
if knownfailure:
|
||||
pytest.xfail(reason=knownfailure)
|
||||
|
||||
x = solve_continuous_are(a, b, q, r, e, s)
|
||||
res = a.conj().T.dot(x.dot(e)) + e.conj().T.dot(x.dot(a)) + q
|
||||
out_fact = e.conj().T.dot(x).dot(b) + s
|
||||
res -= out_fact.dot(solve(np.atleast_2d(r), out_fact.conj().T))
|
||||
assert_array_almost_equal(res, np.zeros_like(res), decimal=dec)
|
||||
|
||||
for ind, case in enumerate(cases):
|
||||
_test_factory(case, min_decimal[ind])
|
||||
|
||||
|
||||
def test_solve_generalized_discrete_are():
|
||||
mat20170120 = _load_data('gendare_20170120_data.npz')
|
||||
|
||||
cases = [
|
||||
# Two random examples differ by s term
|
||||
# in the absence of any literature for demanding examples.
|
||||
(np.array([[2.769230e-01, 8.234578e-01, 9.502220e-01],
|
||||
[4.617139e-02, 6.948286e-01, 3.444608e-02],
|
||||
[9.713178e-02, 3.170995e-01, 4.387444e-01]]),
|
||||
np.array([[3.815585e-01, 1.868726e-01],
|
||||
[7.655168e-01, 4.897644e-01],
|
||||
[7.951999e-01, 4.455862e-01]]),
|
||||
np.eye(3),
|
||||
np.eye(2),
|
||||
np.array([[6.463130e-01, 2.760251e-01, 1.626117e-01],
|
||||
[7.093648e-01, 6.797027e-01, 1.189977e-01],
|
||||
[7.546867e-01, 6.550980e-01, 4.983641e-01]]),
|
||||
np.zeros((3, 2)),
|
||||
None),
|
||||
(np.array([[2.769230e-01, 8.234578e-01, 9.502220e-01],
|
||||
[4.617139e-02, 6.948286e-01, 3.444608e-02],
|
||||
[9.713178e-02, 3.170995e-01, 4.387444e-01]]),
|
||||
np.array([[3.815585e-01, 1.868726e-01],
|
||||
[7.655168e-01, 4.897644e-01],
|
||||
[7.951999e-01, 4.455862e-01]]),
|
||||
np.eye(3),
|
||||
np.eye(2),
|
||||
np.array([[6.463130e-01, 2.760251e-01, 1.626117e-01],
|
||||
[7.093648e-01, 6.797027e-01, 1.189977e-01],
|
||||
[7.546867e-01, 6.550980e-01, 4.983641e-01]]),
|
||||
np.ones((3, 2)),
|
||||
None),
|
||||
# user-reported (under PR-6616) 20-Jan-2017
|
||||
# tests against the case where E is None but S is provided
|
||||
(mat20170120['A'],
|
||||
mat20170120['B'],
|
||||
mat20170120['Q'],
|
||||
mat20170120['R'],
|
||||
None,
|
||||
mat20170120['S'],
|
||||
None),
|
||||
]
|
||||
|
||||
min_decimal = (11, 11, 16)
|
||||
|
||||
def _test_factory(case, dec):
|
||||
"""Checks if X = A'XA-(A'XB)(R+B'XB)^-1(B'XA)+Q) is true"""
|
||||
a, b, q, r, e, s, knownfailure = case
|
||||
if knownfailure:
|
||||
pytest.xfail(reason=knownfailure)
|
||||
|
||||
x = solve_discrete_are(a, b, q, r, e, s)
|
||||
if e is None:
|
||||
e = np.eye(a.shape[0])
|
||||
if s is None:
|
||||
s = np.zeros_like(b)
|
||||
res = a.conj().T.dot(x.dot(a)) - e.conj().T.dot(x.dot(e)) + q
|
||||
res -= (a.conj().T.dot(x.dot(b)) + s).dot(
|
||||
solve(r+b.conj().T.dot(x.dot(b)),
|
||||
(b.conj().T.dot(x.dot(a)) + s.conj().T)
|
||||
)
|
||||
)
|
||||
assert_array_almost_equal(res, np.zeros_like(res), decimal=dec)
|
||||
|
||||
for ind, case in enumerate(cases):
|
||||
_test_factory(case, min_decimal[ind])
|
||||
|
||||
|
||||
def test_are_validate_args():
|
||||
|
||||
def test_square_shape():
|
||||
nsq = np.ones((3, 2))
|
||||
sq = np.eye(3)
|
||||
for x in (solve_continuous_are, solve_discrete_are):
|
||||
assert_raises(ValueError, x, nsq, 1, 1, 1)
|
||||
assert_raises(ValueError, x, sq, sq, nsq, 1)
|
||||
assert_raises(ValueError, x, sq, sq, sq, nsq)
|
||||
assert_raises(ValueError, x, sq, sq, sq, sq, nsq)
|
||||
|
||||
def test_compatible_sizes():
|
||||
nsq = np.ones((3, 2))
|
||||
sq = np.eye(4)
|
||||
for x in (solve_continuous_are, solve_discrete_are):
|
||||
assert_raises(ValueError, x, sq, nsq, 1, 1)
|
||||
assert_raises(ValueError, x, sq, sq, sq, sq, sq, nsq)
|
||||
assert_raises(ValueError, x, sq, sq, np.eye(3), sq)
|
||||
assert_raises(ValueError, x, sq, sq, sq, np.eye(3))
|
||||
assert_raises(ValueError, x, sq, sq, sq, sq, np.eye(3))
|
||||
|
||||
def test_symmetry():
|
||||
nsym = np.arange(9).reshape(3, 3)
|
||||
sym = np.eye(3)
|
||||
for x in (solve_continuous_are, solve_discrete_are):
|
||||
assert_raises(ValueError, x, sym, sym, nsym, sym)
|
||||
assert_raises(ValueError, x, sym, sym, sym, nsym)
|
||||
|
||||
def test_singularity():
|
||||
sing = np.full((3, 3), 1e12)
|
||||
sing[2, 2] -= 1
|
||||
sq = np.eye(3)
|
||||
for x in (solve_continuous_are, solve_discrete_are):
|
||||
assert_raises(ValueError, x, sq, sq, sq, sq, sing)
|
||||
|
||||
assert_raises(ValueError, solve_continuous_are, sq, sq, sq, sing)
|
||||
|
||||
def test_finiteness():
|
||||
nm = np.full((2, 2), np.nan)
|
||||
sq = np.eye(2)
|
||||
for x in (solve_continuous_are, solve_discrete_are):
|
||||
assert_raises(ValueError, x, nm, sq, sq, sq)
|
||||
assert_raises(ValueError, x, sq, nm, sq, sq)
|
||||
assert_raises(ValueError, x, sq, sq, nm, sq)
|
||||
assert_raises(ValueError, x, sq, sq, sq, nm)
|
||||
assert_raises(ValueError, x, sq, sq, sq, sq, nm)
|
||||
assert_raises(ValueError, x, sq, sq, sq, sq, sq, nm)
|
||||
|
||||
|
||||
class TestSolveSylvester(object):
|
||||
|
||||
cases = [
|
||||
# a, b, c all real.
|
||||
(np.array([[1, 2], [0, 4]]),
|
||||
np.array([[5, 6], [0, 8]]),
|
||||
np.array([[9, 10], [11, 12]])),
|
||||
# a, b, c all real, 4x4. a and b have non-trival 2x2 blocks in their
|
||||
# quasi-triangular form.
|
||||
(np.array([[1.0, 0, 0, 0],
|
||||
[0, 1.0, 2.0, 0.0],
|
||||
[0, 0, 3.0, -4],
|
||||
[0, 0, 2, 5]]),
|
||||
np.array([[2.0, 0, 0, 1.0],
|
||||
[0, 1.0, 0.0, 0.0],
|
||||
[0, 0, 1.0, -1],
|
||||
[0, 0, 1, 1]]),
|
||||
np.array([[1.0, 0, 0, 0],
|
||||
[0, 1.0, 0, 0],
|
||||
[0, 0, 1.0, 0],
|
||||
[0, 0, 0, 1.0]])),
|
||||
# a, b, c all complex.
|
||||
(np.array([[1.0+1j, 2.0], [3.0-4.0j, 5.0]]),
|
||||
np.array([[-1.0, 2j], [3.0, 4.0]]),
|
||||
np.array([[2.0-2j, 2.0+2j], [-1.0-1j, 2.0]])),
|
||||
# a and b real; c complex.
|
||||
(np.array([[1.0, 2.0], [3.0, 5.0]]),
|
||||
np.array([[-1.0, 0], [3.0, 4.0]]),
|
||||
np.array([[2.0-2j, 2.0+2j], [-1.0-1j, 2.0]])),
|
||||
# a and c complex; b real.
|
||||
(np.array([[1.0+1j, 2.0], [3.0-4.0j, 5.0]]),
|
||||
np.array([[-1.0, 0], [3.0, 4.0]]),
|
||||
np.array([[2.0-2j, 2.0+2j], [-1.0-1j, 2.0]])),
|
||||
# a complex; b and c real.
|
||||
(np.array([[1.0+1j, 2.0], [3.0-4.0j, 5.0]]),
|
||||
np.array([[-1.0, 0], [3.0, 4.0]]),
|
||||
np.array([[2.0, 2.0], [-1.0, 2.0]])),
|
||||
# not square matrices, real
|
||||
(np.array([[8, 1, 6], [3, 5, 7], [4, 9, 2]]),
|
||||
np.array([[2, 3], [4, 5]]),
|
||||
np.array([[1, 2], [3, 4], [5, 6]])),
|
||||
# not square matrices, complex
|
||||
(np.array([[8, 1j, 6+2j], [3, 5, 7], [4, 9, 2]]),
|
||||
np.array([[2, 3], [4, 5-1j]]),
|
||||
np.array([[1, 2j], [3, 4j], [5j, 6+7j]])),
|
||||
]
|
||||
|
||||
def check_case(self, a, b, c):
|
||||
x = solve_sylvester(a, b, c)
|
||||
assert_array_almost_equal(np.dot(a, x) + np.dot(x, b), c)
|
||||
|
||||
def test_cases(self):
|
||||
for case in self.cases:
|
||||
self.check_case(case[0], case[1], case[2])
|
||||
|
||||
def test_trivial(self):
|
||||
a = np.array([[1.0, 0.0], [0.0, 1.0]])
|
||||
b = np.array([[1.0]])
|
||||
c = np.array([2.0, 2.0]).reshape(-1, 1)
|
||||
x = solve_sylvester(a, b, c)
|
||||
assert_array_almost_equal(x, np.array([1.0, 1.0]).reshape(-1, 1))
|
|
@ -0,0 +1,690 @@
|
|||
|
||||
import pytest
|
||||
import numpy as np
|
||||
from numpy import arange, add, array, eye, copy, sqrt
|
||||
from numpy.testing import (assert_equal, assert_array_equal,
|
||||
assert_array_almost_equal, assert_allclose)
|
||||
from pytest import raises as assert_raises
|
||||
|
||||
from scipy.fft import fft
|
||||
from scipy.special import comb
|
||||
from scipy.linalg import (toeplitz, hankel, circulant, hadamard, leslie, dft,
|
||||
companion, tri, triu, tril, kron, block_diag,
|
||||
helmert, hilbert, invhilbert, pascal, invpascal,
|
||||
fiedler, fiedler_companion, eigvals,
|
||||
convolution_matrix)
|
||||
from numpy.linalg import cond
|
||||
|
||||
|
||||
def get_mat(n):
|
||||
data = arange(n)
|
||||
data = add.outer(data, data)
|
||||
return data
|
||||
|
||||
|
||||
class TestTri(object):
|
||||
def test_basic(self):
|
||||
assert_equal(tri(4), array([[1, 0, 0, 0],
|
||||
[1, 1, 0, 0],
|
||||
[1, 1, 1, 0],
|
||||
[1, 1, 1, 1]]))
|
||||
assert_equal(tri(4, dtype='f'), array([[1, 0, 0, 0],
|
||||
[1, 1, 0, 0],
|
||||
[1, 1, 1, 0],
|
||||
[1, 1, 1, 1]], 'f'))
|
||||
|
||||
def test_diag(self):
|
||||
assert_equal(tri(4, k=1), array([[1, 1, 0, 0],
|
||||
[1, 1, 1, 0],
|
||||
[1, 1, 1, 1],
|
||||
[1, 1, 1, 1]]))
|
||||
assert_equal(tri(4, k=-1), array([[0, 0, 0, 0],
|
||||
[1, 0, 0, 0],
|
||||
[1, 1, 0, 0],
|
||||
[1, 1, 1, 0]]))
|
||||
|
||||
def test_2d(self):
|
||||
assert_equal(tri(4, 3), array([[1, 0, 0],
|
||||
[1, 1, 0],
|
||||
[1, 1, 1],
|
||||
[1, 1, 1]]))
|
||||
assert_equal(tri(3, 4), array([[1, 0, 0, 0],
|
||||
[1, 1, 0, 0],
|
||||
[1, 1, 1, 0]]))
|
||||
|
||||
def test_diag2d(self):
|
||||
assert_equal(tri(3, 4, k=2), array([[1, 1, 1, 0],
|
||||
[1, 1, 1, 1],
|
||||
[1, 1, 1, 1]]))
|
||||
assert_equal(tri(4, 3, k=-2), array([[0, 0, 0],
|
||||
[0, 0, 0],
|
||||
[1, 0, 0],
|
||||
[1, 1, 0]]))
|
||||
|
||||
|
||||
class TestTril(object):
|
||||
def test_basic(self):
|
||||
a = (100*get_mat(5)).astype('l')
|
||||
b = a.copy()
|
||||
for k in range(5):
|
||||
for l in range(k+1, 5):
|
||||
b[k, l] = 0
|
||||
assert_equal(tril(a), b)
|
||||
|
||||
def test_diag(self):
|
||||
a = (100*get_mat(5)).astype('f')
|
||||
b = a.copy()
|
||||
for k in range(5):
|
||||
for l in range(k+3, 5):
|
||||
b[k, l] = 0
|
||||
assert_equal(tril(a, k=2), b)
|
||||
b = a.copy()
|
||||
for k in range(5):
|
||||
for l in range(max((k-1, 0)), 5):
|
||||
b[k, l] = 0
|
||||
assert_equal(tril(a, k=-2), b)
|
||||
|
||||
|
||||
class TestTriu(object):
|
||||
def test_basic(self):
|
||||
a = (100*get_mat(5)).astype('l')
|
||||
b = a.copy()
|
||||
for k in range(5):
|
||||
for l in range(k+1, 5):
|
||||
b[l, k] = 0
|
||||
assert_equal(triu(a), b)
|
||||
|
||||
def test_diag(self):
|
||||
a = (100*get_mat(5)).astype('f')
|
||||
b = a.copy()
|
||||
for k in range(5):
|
||||
for l in range(max((k-1, 0)), 5):
|
||||
b[l, k] = 0
|
||||
assert_equal(triu(a, k=2), b)
|
||||
b = a.copy()
|
||||
for k in range(5):
|
||||
for l in range(k+3, 5):
|
||||
b[l, k] = 0
|
||||
assert_equal(triu(a, k=-2), b)
|
||||
|
||||
|
||||
class TestToeplitz(object):
|
||||
|
||||
def test_basic(self):
|
||||
y = toeplitz([1, 2, 3])
|
||||
assert_array_equal(y, [[1, 2, 3], [2, 1, 2], [3, 2, 1]])
|
||||
y = toeplitz([1, 2, 3], [1, 4, 5])
|
||||
assert_array_equal(y, [[1, 4, 5], [2, 1, 4], [3, 2, 1]])
|
||||
|
||||
def test_complex_01(self):
|
||||
data = (1.0 + arange(3.0)) * (1.0 + 1.0j)
|
||||
x = copy(data)
|
||||
t = toeplitz(x)
|
||||
# Calling toeplitz should not change x.
|
||||
assert_array_equal(x, data)
|
||||
# According to the docstring, x should be the first column of t.
|
||||
col0 = t[:, 0]
|
||||
assert_array_equal(col0, data)
|
||||
assert_array_equal(t[0, 1:], data[1:].conj())
|
||||
|
||||
def test_scalar_00(self):
|
||||
"""Scalar arguments still produce a 2D array."""
|
||||
t = toeplitz(10)
|
||||
assert_array_equal(t, [[10]])
|
||||
t = toeplitz(10, 20)
|
||||
assert_array_equal(t, [[10]])
|
||||
|
||||
def test_scalar_01(self):
|
||||
c = array([1, 2, 3])
|
||||
t = toeplitz(c, 1)
|
||||
assert_array_equal(t, [[1], [2], [3]])
|
||||
|
||||
def test_scalar_02(self):
|
||||
c = array([1, 2, 3])
|
||||
t = toeplitz(c, array(1))
|
||||
assert_array_equal(t, [[1], [2], [3]])
|
||||
|
||||
def test_scalar_03(self):
|
||||
c = array([1, 2, 3])
|
||||
t = toeplitz(c, array([1]))
|
||||
assert_array_equal(t, [[1], [2], [3]])
|
||||
|
||||
def test_scalar_04(self):
|
||||
r = array([10, 2, 3])
|
||||
t = toeplitz(1, r)
|
||||
assert_array_equal(t, [[1, 2, 3]])
|
||||
|
||||
|
||||
class TestHankel(object):
|
||||
def test_basic(self):
|
||||
y = hankel([1, 2, 3])
|
||||
assert_array_equal(y, [[1, 2, 3], [2, 3, 0], [3, 0, 0]])
|
||||
y = hankel([1, 2, 3], [3, 4, 5])
|
||||
assert_array_equal(y, [[1, 2, 3], [2, 3, 4], [3, 4, 5]])
|
||||
|
||||
|
||||
class TestCirculant(object):
|
||||
def test_basic(self):
|
||||
y = circulant([1, 2, 3])
|
||||
assert_array_equal(y, [[1, 3, 2], [2, 1, 3], [3, 2, 1]])
|
||||
|
||||
|
||||
class TestHadamard(object):
|
||||
|
||||
def test_basic(self):
|
||||
|
||||
y = hadamard(1)
|
||||
assert_array_equal(y, [[1]])
|
||||
|
||||
y = hadamard(2, dtype=float)
|
||||
assert_array_equal(y, [[1.0, 1.0], [1.0, -1.0]])
|
||||
|
||||
y = hadamard(4)
|
||||
assert_array_equal(y, [[1, 1, 1, 1],
|
||||
[1, -1, 1, -1],
|
||||
[1, 1, -1, -1],
|
||||
[1, -1, -1, 1]])
|
||||
|
||||
assert_raises(ValueError, hadamard, 0)
|
||||
assert_raises(ValueError, hadamard, 5)
|
||||
|
||||
|
||||
class TestLeslie(object):
|
||||
|
||||
def test_bad_shapes(self):
|
||||
assert_raises(ValueError, leslie, [[1, 1], [2, 2]], [3, 4, 5])
|
||||
assert_raises(ValueError, leslie, [3, 4, 5], [[1, 1], [2, 2]])
|
||||
assert_raises(ValueError, leslie, [1, 2], [1, 2])
|
||||
assert_raises(ValueError, leslie, [1], [])
|
||||
|
||||
def test_basic(self):
|
||||
a = leslie([1, 2, 3], [0.25, 0.5])
|
||||
expected = array([[1.0, 2.0, 3.0],
|
||||
[0.25, 0.0, 0.0],
|
||||
[0.0, 0.5, 0.0]])
|
||||
assert_array_equal(a, expected)
|
||||
|
||||
|
||||
class TestCompanion(object):
|
||||
|
||||
def test_bad_shapes(self):
|
||||
assert_raises(ValueError, companion, [[1, 1], [2, 2]])
|
||||
assert_raises(ValueError, companion, [0, 4, 5])
|
||||
assert_raises(ValueError, companion, [1])
|
||||
assert_raises(ValueError, companion, [])
|
||||
|
||||
def test_basic(self):
|
||||
c = companion([1, 2, 3])
|
||||
expected = array([
|
||||
[-2.0, -3.0],
|
||||
[1.0, 0.0]])
|
||||
assert_array_equal(c, expected)
|
||||
|
||||
c = companion([2.0, 5.0, -10.0])
|
||||
expected = array([
|
||||
[-2.5, 5.0],
|
||||
[1.0, 0.0]])
|
||||
assert_array_equal(c, expected)
|
||||
|
||||
|
||||
class TestBlockDiag:
|
||||
def test_basic(self):
|
||||
x = block_diag(eye(2), [[1, 2], [3, 4], [5, 6]], [[1, 2, 3]])
|
||||
assert_array_equal(x, [[1, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 2, 0, 0, 0],
|
||||
[0, 0, 3, 4, 0, 0, 0],
|
||||
[0, 0, 5, 6, 0, 0, 0],
|
||||
[0, 0, 0, 0, 1, 2, 3]])
|
||||
|
||||
def test_dtype(self):
|
||||
x = block_diag([[1.5]])
|
||||
assert_equal(x.dtype, float)
|
||||
|
||||
x = block_diag([[True]])
|
||||
assert_equal(x.dtype, bool)
|
||||
|
||||
def test_mixed_dtypes(self):
|
||||
actual = block_diag([[1]], [[1j]])
|
||||
desired = np.array([[1, 0], [0, 1j]])
|
||||
assert_array_equal(actual, desired)
|
||||
|
||||
def test_scalar_and_1d_args(self):
|
||||
a = block_diag(1)
|
||||
assert_equal(a.shape, (1, 1))
|
||||
assert_array_equal(a, [[1]])
|
||||
|
||||
a = block_diag([2, 3], 4)
|
||||
assert_array_equal(a, [[2, 3, 0], [0, 0, 4]])
|
||||
|
||||
def test_bad_arg(self):
|
||||
assert_raises(ValueError, block_diag, [[[1]]])
|
||||
|
||||
def test_no_args(self):
|
||||
a = block_diag()
|
||||
assert_equal(a.ndim, 2)
|
||||
assert_equal(a.nbytes, 0)
|
||||
|
||||
def test_empty_matrix_arg(self):
|
||||
# regression test for gh-4596: check the shape of the result
|
||||
# for empty matrix inputs. Empty matrices are no longer ignored
|
||||
# (gh-4908) it is viewed as a shape (1, 0) matrix.
|
||||
a = block_diag([[1, 0], [0, 1]],
|
||||
[],
|
||||
[[2, 3], [4, 5], [6, 7]])
|
||||
assert_array_equal(a, [[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 2, 3],
|
||||
[0, 0, 4, 5],
|
||||
[0, 0, 6, 7]])
|
||||
|
||||
def test_zerosized_matrix_arg(self):
|
||||
# test for gh-4908: check the shape of the result for
|
||||
# zero-sized matrix inputs, i.e. matrices with shape (0,n) or (n,0).
|
||||
# note that [[]] takes shape (1,0)
|
||||
a = block_diag([[1, 0], [0, 1]],
|
||||
[[]],
|
||||
[[2, 3], [4, 5], [6, 7]],
|
||||
np.zeros([0, 2], dtype='int32'))
|
||||
assert_array_equal(a, [[1, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 2, 3, 0, 0],
|
||||
[0, 0, 4, 5, 0, 0],
|
||||
[0, 0, 6, 7, 0, 0]])
|
||||
|
||||
|
||||
class TestKron:
|
||||
|
||||
def test_basic(self):
|
||||
|
||||
a = kron(array([[1, 2], [3, 4]]), array([[1, 1, 1]]))
|
||||
assert_array_equal(a, array([[1, 1, 1, 2, 2, 2],
|
||||
[3, 3, 3, 4, 4, 4]]))
|
||||
|
||||
m1 = array([[1, 2], [3, 4]])
|
||||
m2 = array([[10], [11]])
|
||||
a = kron(m1, m2)
|
||||
expected = array([[10, 20],
|
||||
[11, 22],
|
||||
[30, 40],
|
||||
[33, 44]])
|
||||
assert_array_equal(a, expected)
|
||||
|
||||
|
||||
class TestHelmert(object):
|
||||
|
||||
def test_orthogonality(self):
|
||||
for n in range(1, 7):
|
||||
H = helmert(n, full=True)
|
||||
Id = np.eye(n)
|
||||
assert_allclose(H.dot(H.T), Id, atol=1e-12)
|
||||
assert_allclose(H.T.dot(H), Id, atol=1e-12)
|
||||
|
||||
def test_subspace(self):
|
||||
for n in range(2, 7):
|
||||
H_full = helmert(n, full=True)
|
||||
H_partial = helmert(n)
|
||||
for U in H_full[1:, :].T, H_partial.T:
|
||||
C = np.eye(n) - np.full((n, n), 1 / n)
|
||||
assert_allclose(U.dot(U.T), C)
|
||||
assert_allclose(U.T.dot(U), np.eye(n-1), atol=1e-12)
|
||||
|
||||
|
||||
class TestHilbert(object):
|
||||
|
||||
def test_basic(self):
|
||||
h3 = array([[1.0, 1/2., 1/3.],
|
||||
[1/2., 1/3., 1/4.],
|
||||
[1/3., 1/4., 1/5.]])
|
||||
assert_array_almost_equal(hilbert(3), h3)
|
||||
|
||||
assert_array_equal(hilbert(1), [[1.0]])
|
||||
|
||||
h0 = hilbert(0)
|
||||
assert_equal(h0.shape, (0, 0))
|
||||
|
||||
|
||||
class TestInvHilbert(object):
|
||||
|
||||
def test_basic(self):
|
||||
invh1 = array([[1]])
|
||||
assert_array_equal(invhilbert(1, exact=True), invh1)
|
||||
assert_array_equal(invhilbert(1), invh1)
|
||||
|
||||
invh2 = array([[4, -6],
|
||||
[-6, 12]])
|
||||
assert_array_equal(invhilbert(2, exact=True), invh2)
|
||||
assert_array_almost_equal(invhilbert(2), invh2)
|
||||
|
||||
invh3 = array([[9, -36, 30],
|
||||
[-36, 192, -180],
|
||||
[30, -180, 180]])
|
||||
assert_array_equal(invhilbert(3, exact=True), invh3)
|
||||
assert_array_almost_equal(invhilbert(3), invh3)
|
||||
|
||||
invh4 = array([[16, -120, 240, -140],
|
||||
[-120, 1200, -2700, 1680],
|
||||
[240, -2700, 6480, -4200],
|
||||
[-140, 1680, -4200, 2800]])
|
||||
assert_array_equal(invhilbert(4, exact=True), invh4)
|
||||
assert_array_almost_equal(invhilbert(4), invh4)
|
||||
|
||||
invh5 = array([[25, -300, 1050, -1400, 630],
|
||||
[-300, 4800, -18900, 26880, -12600],
|
||||
[1050, -18900, 79380, -117600, 56700],
|
||||
[-1400, 26880, -117600, 179200, -88200],
|
||||
[630, -12600, 56700, -88200, 44100]])
|
||||
assert_array_equal(invhilbert(5, exact=True), invh5)
|
||||
assert_array_almost_equal(invhilbert(5), invh5)
|
||||
|
||||
invh17 = array([
|
||||
[289, -41616, 1976760, -46124400, 629598060, -5540462928,
|
||||
33374693352, -143034400080, 446982500250, -1033026222800,
|
||||
1774926873720, -2258997839280, 2099709530100, -1384423866000,
|
||||
613101997800, -163493866080, 19835652870],
|
||||
[-41616, 7990272, -426980160, 10627061760, -151103534400,
|
||||
1367702848512, -8410422724704, 36616806420480, -115857864064800,
|
||||
270465047424000, -468580694662080, 600545887119360,
|
||||
-561522320049600, 372133135180800, -165537539406000,
|
||||
44316454993920, -5395297580640],
|
||||
[1976760, -426980160, 24337869120, -630981792000, 9228108708000,
|
||||
-85267724461920, 532660105897920, -2348052711713280,
|
||||
7504429831470000, -17664748409880000, 30818191841236800,
|
||||
-39732544853164800, 37341234283298400, -24857330514030000,
|
||||
11100752642520000, -2982128117299200, 364182586693200],
|
||||
[-46124400, 10627061760, -630981792000, 16826181120000,
|
||||
-251209625940000, 2358021022156800, -14914482965141760,
|
||||
66409571644416000, -214015221119700000, 507295338950400000,
|
||||
-890303319857952000, 1153715376477081600, -1089119333262870000,
|
||||
727848632044800000, -326170262829600000, 87894302404608000,
|
||||
-10763618673376800],
|
||||
[629598060, -151103534400, 9228108708000,
|
||||
-251209625940000, 3810012660090000, -36210360321495360,
|
||||
231343968720664800, -1038687206500944000, 3370739732635275000,
|
||||
-8037460526495400000, 14178080368737885600, -18454939322943942000,
|
||||
17489975175339030000, -11728977435138600000, 5272370630081100000,
|
||||
-1424711708039692800, 174908803442373000],
|
||||
[-5540462928, 1367702848512, -85267724461920, 2358021022156800,
|
||||
-36210360321495360, 347619459086355456, -2239409617216035264,
|
||||
10124803292907663360, -33052510749726468000,
|
||||
79217210949138662400, -140362995650505067440,
|
||||
183420385176741672960, -174433352415381259200,
|
||||
117339159519533952000, -52892422160973595200,
|
||||
14328529177999196160, -1763080738699119840],
|
||||
[33374693352, -8410422724704, 532660105897920,
|
||||
-14914482965141760, 231343968720664800, -2239409617216035264,
|
||||
14527452132196331328, -66072377044391477760,
|
||||
216799987176909536400, -521925895055522958000,
|
||||
928414062734059661760, -1217424500995626443520,
|
||||
1161358898976091015200, -783401860847777371200,
|
||||
354015418167362952000, -96120549902411274240,
|
||||
11851820521255194480],
|
||||
[-143034400080, 36616806420480, -2348052711713280,
|
||||
66409571644416000, -1038687206500944000, 10124803292907663360,
|
||||
-66072377044391477760, 302045152202932469760,
|
||||
-995510145200094810000, 2405996923185123840000,
|
||||
-4294704507885446054400, 5649058909023744614400,
|
||||
-5403874060541811254400, 3654352703663101440000,
|
||||
-1655137020003255360000, 450325202737117593600,
|
||||
-55630994283442749600],
|
||||
[446982500250, -115857864064800, 7504429831470000,
|
||||
-214015221119700000, 3370739732635275000, -33052510749726468000,
|
||||
216799987176909536400, -995510145200094810000,
|
||||
3293967392206196062500, -7988661659013106500000,
|
||||
14303908928401362270000, -18866974090684772052000,
|
||||
18093328327706957325000, -12263364009096700500000,
|
||||
5565847995255512250000, -1517208935002984080000,
|
||||
187754605706619279900],
|
||||
[-1033026222800, 270465047424000, -17664748409880000,
|
||||
507295338950400000, -8037460526495400000, 79217210949138662400,
|
||||
-521925895055522958000, 2405996923185123840000,
|
||||
-7988661659013106500000, 19434404971634224000000,
|
||||
-34894474126569249192000, 46141453390504792320000,
|
||||
-44349976506971935800000, 30121928988527376000000,
|
||||
-13697025107665828500000, 3740200989399948902400,
|
||||
-463591619028689580000],
|
||||
[1774926873720, -468580694662080,
|
||||
30818191841236800, -890303319857952000, 14178080368737885600,
|
||||
-140362995650505067440, 928414062734059661760,
|
||||
-4294704507885446054400, 14303908928401362270000,
|
||||
-34894474126569249192000, 62810053427824648545600,
|
||||
-83243376594051600326400, 80177044485212743068000,
|
||||
-54558343880470209780000, 24851882355348879230400,
|
||||
-6797096028813368678400, 843736746632215035600],
|
||||
[-2258997839280, 600545887119360, -39732544853164800,
|
||||
1153715376477081600, -18454939322943942000, 183420385176741672960,
|
||||
-1217424500995626443520, 5649058909023744614400,
|
||||
-18866974090684772052000, 46141453390504792320000,
|
||||
-83243376594051600326400, 110552468520163390156800,
|
||||
-106681852579497947388000, 72720410752415168870400,
|
||||
-33177973900974346080000, 9087761081682520473600,
|
||||
-1129631016152221783200],
|
||||
[2099709530100, -561522320049600, 37341234283298400,
|
||||
-1089119333262870000, 17489975175339030000,
|
||||
-174433352415381259200, 1161358898976091015200,
|
||||
-5403874060541811254400, 18093328327706957325000,
|
||||
-44349976506971935800000, 80177044485212743068000,
|
||||
-106681852579497947388000, 103125790826848015808400,
|
||||
-70409051543137015800000, 32171029219823375700000,
|
||||
-8824053728865840192000, 1098252376814660067000],
|
||||
[-1384423866000, 372133135180800,
|
||||
-24857330514030000, 727848632044800000, -11728977435138600000,
|
||||
117339159519533952000, -783401860847777371200,
|
||||
3654352703663101440000, -12263364009096700500000,
|
||||
30121928988527376000000, -54558343880470209780000,
|
||||
72720410752415168870400, -70409051543137015800000,
|
||||
48142941226076592000000, -22027500987368499000000,
|
||||
6049545098753157120000, -753830033789944188000],
|
||||
[613101997800, -165537539406000,
|
||||
11100752642520000, -326170262829600000, 5272370630081100000,
|
||||
-52892422160973595200, 354015418167362952000,
|
||||
-1655137020003255360000, 5565847995255512250000,
|
||||
-13697025107665828500000, 24851882355348879230400,
|
||||
-33177973900974346080000, 32171029219823375700000,
|
||||
-22027500987368499000000, 10091416708498869000000,
|
||||
-2774765838662800128000, 346146444087219270000],
|
||||
[-163493866080, 44316454993920, -2982128117299200,
|
||||
87894302404608000, -1424711708039692800,
|
||||
14328529177999196160, -96120549902411274240,
|
||||
450325202737117593600, -1517208935002984080000,
|
||||
3740200989399948902400, -6797096028813368678400,
|
||||
9087761081682520473600, -8824053728865840192000,
|
||||
6049545098753157120000, -2774765838662800128000,
|
||||
763806510427609497600, -95382575704033754400],
|
||||
[19835652870, -5395297580640, 364182586693200, -10763618673376800,
|
||||
174908803442373000, -1763080738699119840, 11851820521255194480,
|
||||
-55630994283442749600, 187754605706619279900,
|
||||
-463591619028689580000, 843736746632215035600,
|
||||
-1129631016152221783200, 1098252376814660067000,
|
||||
-753830033789944188000, 346146444087219270000,
|
||||
-95382575704033754400, 11922821963004219300]
|
||||
])
|
||||
assert_array_equal(invhilbert(17, exact=True), invh17)
|
||||
assert_allclose(invhilbert(17), invh17.astype(float), rtol=1e-12)
|
||||
|
||||
def test_inverse(self):
|
||||
for n in range(1, 10):
|
||||
a = hilbert(n)
|
||||
b = invhilbert(n)
|
||||
# The Hilbert matrix is increasingly badly conditioned,
|
||||
# so take that into account in the test
|
||||
c = cond(a)
|
||||
assert_allclose(a.dot(b), eye(n), atol=1e-15*c, rtol=1e-15*c)
|
||||
|
||||
|
||||
class TestPascal(object):
|
||||
|
||||
cases = [
|
||||
(1, array([[1]]), array([[1]])),
|
||||
(2, array([[1, 1],
|
||||
[1, 2]]),
|
||||
array([[1, 0],
|
||||
[1, 1]])),
|
||||
(3, array([[1, 1, 1],
|
||||
[1, 2, 3],
|
||||
[1, 3, 6]]),
|
||||
array([[1, 0, 0],
|
||||
[1, 1, 0],
|
||||
[1, 2, 1]])),
|
||||
(4, array([[1, 1, 1, 1],
|
||||
[1, 2, 3, 4],
|
||||
[1, 3, 6, 10],
|
||||
[1, 4, 10, 20]]),
|
||||
array([[1, 0, 0, 0],
|
||||
[1, 1, 0, 0],
|
||||
[1, 2, 1, 0],
|
||||
[1, 3, 3, 1]])),
|
||||
]
|
||||
|
||||
def check_case(self, n, sym, low):
|
||||
assert_array_equal(pascal(n), sym)
|
||||
assert_array_equal(pascal(n, kind='lower'), low)
|
||||
assert_array_equal(pascal(n, kind='upper'), low.T)
|
||||
assert_array_almost_equal(pascal(n, exact=False), sym)
|
||||
assert_array_almost_equal(pascal(n, exact=False, kind='lower'), low)
|
||||
assert_array_almost_equal(pascal(n, exact=False, kind='upper'), low.T)
|
||||
|
||||
def test_cases(self):
|
||||
for n, sym, low in self.cases:
|
||||
self.check_case(n, sym, low)
|
||||
|
||||
def test_big(self):
|
||||
p = pascal(50)
|
||||
assert_equal(p[-1, -1], comb(98, 49, exact=True))
|
||||
|
||||
def test_threshold(self):
|
||||
# Regression test. An early version of `pascal` returned an
|
||||
# array of type np.uint64 for n=35, but that data type is too small
|
||||
# to hold p[-1, -1]. The second assert_equal below would fail
|
||||
# because p[-1, -1] overflowed.
|
||||
p = pascal(34)
|
||||
assert_equal(2*p.item(-1, -2), p.item(-1, -1), err_msg="n = 34")
|
||||
p = pascal(35)
|
||||
assert_equal(2*p.item(-1, -2), p.item(-1, -1), err_msg="n = 35")
|
||||
|
||||
|
||||
def test_invpascal():
|
||||
|
||||
def check_invpascal(n, kind, exact):
|
||||
ip = invpascal(n, kind=kind, exact=exact)
|
||||
p = pascal(n, kind=kind, exact=exact)
|
||||
# Matrix-multiply ip and p, and check that we get the identity matrix.
|
||||
# We can't use the simple expression e = ip.dot(p), because when
|
||||
# n < 35 and exact is True, p.dtype is np.uint64 and ip.dtype is
|
||||
# np.int64. The product of those dtypes is np.float64, which loses
|
||||
# precision when n is greater than 18. Instead we'll cast both to
|
||||
# object arrays, and then multiply.
|
||||
e = ip.astype(object).dot(p.astype(object))
|
||||
assert_array_equal(e, eye(n), err_msg="n=%d kind=%r exact=%r" %
|
||||
(n, kind, exact))
|
||||
|
||||
kinds = ['symmetric', 'lower', 'upper']
|
||||
|
||||
ns = [1, 2, 5, 18]
|
||||
for n in ns:
|
||||
for kind in kinds:
|
||||
for exact in [True, False]:
|
||||
check_invpascal(n, kind, exact)
|
||||
|
||||
ns = [19, 34, 35, 50]
|
||||
for n in ns:
|
||||
for kind in kinds:
|
||||
check_invpascal(n, kind, True)
|
||||
|
||||
|
||||
def test_dft():
|
||||
m = dft(2)
|
||||
expected = array([[1.0, 1.0], [1.0, -1.0]])
|
||||
assert_array_almost_equal(m, expected)
|
||||
m = dft(2, scale='n')
|
||||
assert_array_almost_equal(m, expected/2.0)
|
||||
m = dft(2, scale='sqrtn')
|
||||
assert_array_almost_equal(m, expected/sqrt(2.0))
|
||||
|
||||
x = array([0, 1, 2, 3, 4, 5, 0, 1])
|
||||
m = dft(8)
|
||||
mx = m.dot(x)
|
||||
fx = fft(x)
|
||||
assert_array_almost_equal(mx, fx)
|
||||
|
||||
|
||||
def test_fiedler():
|
||||
f = fiedler([])
|
||||
assert_equal(f.size, 0)
|
||||
f = fiedler([123.])
|
||||
assert_array_equal(f, np.array([[0.]]))
|
||||
f = fiedler(np.arange(1, 7))
|
||||
des = np.array([[0, 1, 2, 3, 4, 5],
|
||||
[1, 0, 1, 2, 3, 4],
|
||||
[2, 1, 0, 1, 2, 3],
|
||||
[3, 2, 1, 0, 1, 2],
|
||||
[4, 3, 2, 1, 0, 1],
|
||||
[5, 4, 3, 2, 1, 0]])
|
||||
assert_array_equal(f, des)
|
||||
|
||||
|
||||
def test_fiedler_companion():
|
||||
fc = fiedler_companion([])
|
||||
assert_equal(fc.size, 0)
|
||||
fc = fiedler_companion([1.])
|
||||
assert_equal(fc.size, 0)
|
||||
fc = fiedler_companion([1., 2.])
|
||||
assert_array_equal(fc, np.array([[-2.]]))
|
||||
fc = fiedler_companion([1e-12, 2., 3.])
|
||||
assert_array_almost_equal(fc, companion([1e-12, 2., 3.]))
|
||||
with assert_raises(ValueError):
|
||||
fiedler_companion([0, 1, 2])
|
||||
fc = fiedler_companion([1., -16., 86., -176., 105.])
|
||||
assert_array_almost_equal(eigvals(fc),
|
||||
np.array([7., 5., 3., 1.]))
|
||||
|
||||
|
||||
class TestConvolutionMatrix:
|
||||
"""
|
||||
Test convolution_matrix vs. numpy.convolve for various parameters.
|
||||
"""
|
||||
|
||||
def create_vector(self, n, cpx):
|
||||
"""Make a complex or real test vector of length n."""
|
||||
x = np.linspace(-2.5, 2.2, n)
|
||||
if cpx:
|
||||
x = x + 1j*np.linspace(-1.5, 3.1, n)
|
||||
return x
|
||||
|
||||
def test_bad_n(self):
|
||||
# n must be a positive integer
|
||||
with pytest.raises(ValueError, match='n must be a positive integer'):
|
||||
convolution_matrix([1, 2, 3], 0)
|
||||
|
||||
def test_bad_first_arg(self):
|
||||
# first arg must be a 1d array, otherwise ValueError
|
||||
with pytest.raises(ValueError, match='one-dimensional'):
|
||||
convolution_matrix(1, 4)
|
||||
|
||||
def test_empty_first_arg(self):
|
||||
# first arg must have at least one value
|
||||
with pytest.raises(ValueError, match=r'len\(a\)'):
|
||||
convolution_matrix([], 4)
|
||||
|
||||
def test_bad_mode(self):
|
||||
# mode must be in ('full', 'valid', 'same')
|
||||
with pytest.raises(ValueError, match='mode.*must be one of'):
|
||||
convolution_matrix((1, 1), 4, mode='invalid argument')
|
||||
|
||||
@pytest.mark.parametrize('cpx', [False, True])
|
||||
@pytest.mark.parametrize('na', [1, 2, 9])
|
||||
@pytest.mark.parametrize('nv', [1, 2, 9])
|
||||
@pytest.mark.parametrize('mode', [None, 'full', 'valid', 'same'])
|
||||
def test_against_numpy_convolve(self, cpx, na, nv, mode):
|
||||
a = self.create_vector(na, cpx)
|
||||
v = self.create_vector(nv, cpx)
|
||||
if mode is None:
|
||||
y1 = np.convolve(v, a)
|
||||
A = convolution_matrix(a, nv)
|
||||
else:
|
||||
y1 = np.convolve(v, a, mode)
|
||||
A = convolution_matrix(a, nv, mode)
|
||||
y2 = A @ v
|
||||
assert_array_almost_equal(y1, y2)
|
Loading…
Add table
Add a link
Reference in a new issue