Traktor/myenv/Lib/site-packages/scipy/linalg/tests/test_basic.py

1818 lines
68 KiB
Python
Raw Normal View History

2024-05-26 05:12:46 +02:00
import itertools
import warnings
import numpy as np
from numpy import (arange, array, dot, zeros, identity, conjugate, transpose,
float32)
from numpy.random import random
from numpy.testing import (assert_equal, assert_almost_equal, assert_,
assert_array_almost_equal, assert_allclose,
assert_array_equal, suppress_warnings)
import pytest
from pytest import raises as assert_raises
from scipy.linalg import (solve, inv, det, lstsq, pinv, pinvh, norm,
solve_banded, solveh_banded, solve_triangular,
solve_circulant, circulant, LinAlgError, block_diag,
matrix_balance, qr, LinAlgWarning)
from scipy.linalg._testutils import assert_no_overwrite
from scipy._lib._testutils import check_free_memory, IS_MUSL
from scipy.linalg.blas import HAS_ILP64
from scipy._lib.deprecation import _NoValue
REAL_DTYPES = (np.float32, np.float64, np.longdouble)
COMPLEX_DTYPES = (np.complex64, np.complex128, np.clongdouble)
DTYPES = REAL_DTYPES + COMPLEX_DTYPES
def _eps_cast(dtyp):
"""Get the epsilon for dtype, possibly downcast to BLAS types."""
dt = dtyp
if dt == np.longdouble:
dt = np.float64
elif dt == np.clongdouble:
dt = np.complex128
return np.finfo(dt).eps
class TestSolveBanded:
def test_real(self):
a = array([[1.0, 20, 0, 0],
[-30, 4, 6, 0],
[2, 1, 20, 2],
[0, -1, 7, 14]])
ab = array([[0.0, 20, 6, 2],
[1, 4, 20, 14],
[-30, 1, 7, 0],
[2, -1, 0, 0]])
l, u = 2, 1
b4 = array([10.0, 0.0, 2.0, 14.0])
b4by1 = b4.reshape(-1, 1)
b4by2 = array([[2, 1],
[-30, 4],
[2, 3],
[1, 3]])
b4by4 = array([[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 1, 0, 0],
[0, 1, 0, 0]])
for b in [b4, b4by1, b4by2, b4by4]:
x = solve_banded((l, u), ab, b)
assert_array_almost_equal(dot(a, x), b)
def test_complex(self):
a = array([[1.0, 20, 0, 0],
[-30, 4, 6, 0],
[2j, 1, 20, 2j],
[0, -1, 7, 14]])
ab = array([[0.0, 20, 6, 2j],
[1, 4, 20, 14],
[-30, 1, 7, 0],
[2j, -1, 0, 0]])
l, u = 2, 1
b4 = array([10.0, 0.0, 2.0, 14.0j])
b4by1 = b4.reshape(-1, 1)
b4by2 = array([[2, 1],
[-30, 4],
[2, 3],
[1, 3]])
b4by4 = array([[1, 0, 0, 0],
[0, 0, 0, 1j],
[0, 1, 0, 0],
[0, 1, 0, 0]])
for b in [b4, b4by1, b4by2, b4by4]:
x = solve_banded((l, u), ab, b)
assert_array_almost_equal(dot(a, x), b)
def test_tridiag_real(self):
ab = array([[0.0, 20, 6, 2],
[1, 4, 20, 14],
[-30, 1, 7, 0]])
a = np.diag(ab[0, 1:], 1) + np.diag(ab[1, :], 0) + np.diag(
ab[2, :-1], -1)
b4 = array([10.0, 0.0, 2.0, 14.0])
b4by1 = b4.reshape(-1, 1)
b4by2 = array([[2, 1],
[-30, 4],
[2, 3],
[1, 3]])
b4by4 = array([[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 1, 0, 0],
[0, 1, 0, 0]])
for b in [b4, b4by1, b4by2, b4by4]:
x = solve_banded((1, 1), ab, b)
assert_array_almost_equal(dot(a, x), b)
def test_tridiag_complex(self):
ab = array([[0.0, 20, 6, 2j],
[1, 4, 20, 14],
[-30, 1, 7, 0]])
a = np.diag(ab[0, 1:], 1) + np.diag(ab[1, :], 0) + np.diag(
ab[2, :-1], -1)
b4 = array([10.0, 0.0, 2.0, 14.0j])
b4by1 = b4.reshape(-1, 1)
b4by2 = array([[2, 1],
[-30, 4],
[2, 3],
[1, 3]])
b4by4 = array([[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 1, 0, 0],
[0, 1, 0, 0]])
for b in [b4, b4by1, b4by2, b4by4]:
x = solve_banded((1, 1), ab, b)
assert_array_almost_equal(dot(a, x), b)
def test_check_finite(self):
a = array([[1.0, 20, 0, 0],
[-30, 4, 6, 0],
[2, 1, 20, 2],
[0, -1, 7, 14]])
ab = array([[0.0, 20, 6, 2],
[1, 4, 20, 14],
[-30, 1, 7, 0],
[2, -1, 0, 0]])
l, u = 2, 1
b4 = array([10.0, 0.0, 2.0, 14.0])
x = solve_banded((l, u), ab, b4, check_finite=False)
assert_array_almost_equal(dot(a, x), b4)
def test_bad_shape(self):
ab = array([[0.0, 20, 6, 2],
[1, 4, 20, 14],
[-30, 1, 7, 0],
[2, -1, 0, 0]])
l, u = 2, 1
bad = array([1.0, 2.0, 3.0, 4.0]).reshape(-1, 4)
assert_raises(ValueError, solve_banded, (l, u), ab, bad)
assert_raises(ValueError, solve_banded, (l, u), ab, [1.0, 2.0])
# Values of (l,u) are not compatible with ab.
assert_raises(ValueError, solve_banded, (1, 1), ab, [1.0, 2.0])
def test_1x1(self):
b = array([[1., 2., 3.]])
x = solve_banded((1, 1), [[0], [2], [0]], b)
assert_array_equal(x, [[0.5, 1.0, 1.5]])
assert_equal(x.dtype, np.dtype('f8'))
assert_array_equal(b, [[1.0, 2.0, 3.0]])
def test_native_list_arguments(self):
a = [[1.0, 20, 0, 0],
[-30, 4, 6, 0],
[2, 1, 20, 2],
[0, -1, 7, 14]]
ab = [[0.0, 20, 6, 2],
[1, 4, 20, 14],
[-30, 1, 7, 0],
[2, -1, 0, 0]]
l, u = 2, 1
b = [10.0, 0.0, 2.0, 14.0]
x = solve_banded((l, u), ab, b)
assert_array_almost_equal(dot(a, x), b)
class TestSolveHBanded:
def test_01_upper(self):
# Solve
# [ 4 1 2 0] [1]
# [ 1 4 1 2] X = [4]
# [ 2 1 4 1] [1]
# [ 0 2 1 4] [2]
# with the RHS as a 1D array.
ab = array([[0.0, 0.0, 2.0, 2.0],
[-99, 1.0, 1.0, 1.0],
[4.0, 4.0, 4.0, 4.0]])
b = array([1.0, 4.0, 1.0, 2.0])
x = solveh_banded(ab, b)
assert_array_almost_equal(x, [0.0, 1.0, 0.0, 0.0])
def test_02_upper(self):
# Solve
# [ 4 1 2 0] [1 6]
# [ 1 4 1 2] X = [4 2]
# [ 2 1 4 1] [1 6]
# [ 0 2 1 4] [2 1]
#
ab = array([[0.0, 0.0, 2.0, 2.0],
[-99, 1.0, 1.0, 1.0],
[4.0, 4.0, 4.0, 4.0]])
b = array([[1.0, 6.0],
[4.0, 2.0],
[1.0, 6.0],
[2.0, 1.0]])
x = solveh_banded(ab, b)
expected = array([[0.0, 1.0],
[1.0, 0.0],
[0.0, 1.0],
[0.0, 0.0]])
assert_array_almost_equal(x, expected)
def test_03_upper(self):
# Solve
# [ 4 1 2 0] [1]
# [ 1 4 1 2] X = [4]
# [ 2 1 4 1] [1]
# [ 0 2 1 4] [2]
# with the RHS as a 2D array with shape (3,1).
ab = array([[0.0, 0.0, 2.0, 2.0],
[-99, 1.0, 1.0, 1.0],
[4.0, 4.0, 4.0, 4.0]])
b = array([1.0, 4.0, 1.0, 2.0]).reshape(-1, 1)
x = solveh_banded(ab, b)
assert_array_almost_equal(x, array([0., 1., 0., 0.]).reshape(-1, 1))
def test_01_lower(self):
# Solve
# [ 4 1 2 0] [1]
# [ 1 4 1 2] X = [4]
# [ 2 1 4 1] [1]
# [ 0 2 1 4] [2]
#
ab = array([[4.0, 4.0, 4.0, 4.0],
[1.0, 1.0, 1.0, -99],
[2.0, 2.0, 0.0, 0.0]])
b = array([1.0, 4.0, 1.0, 2.0])
x = solveh_banded(ab, b, lower=True)
assert_array_almost_equal(x, [0.0, 1.0, 0.0, 0.0])
def test_02_lower(self):
# Solve
# [ 4 1 2 0] [1 6]
# [ 1 4 1 2] X = [4 2]
# [ 2 1 4 1] [1 6]
# [ 0 2 1 4] [2 1]
#
ab = array([[4.0, 4.0, 4.0, 4.0],
[1.0, 1.0, 1.0, -99],
[2.0, 2.0, 0.0, 0.0]])
b = array([[1.0, 6.0],
[4.0, 2.0],
[1.0, 6.0],
[2.0, 1.0]])
x = solveh_banded(ab, b, lower=True)
expected = array([[0.0, 1.0],
[1.0, 0.0],
[0.0, 1.0],
[0.0, 0.0]])
assert_array_almost_equal(x, expected)
def test_01_float32(self):
# Solve
# [ 4 1 2 0] [1]
# [ 1 4 1 2] X = [4]
# [ 2 1 4 1] [1]
# [ 0 2 1 4] [2]
#
ab = array([[0.0, 0.0, 2.0, 2.0],
[-99, 1.0, 1.0, 1.0],
[4.0, 4.0, 4.0, 4.0]], dtype=float32)
b = array([1.0, 4.0, 1.0, 2.0], dtype=float32)
x = solveh_banded(ab, b)
assert_array_almost_equal(x, [0.0, 1.0, 0.0, 0.0])
def test_02_float32(self):
# Solve
# [ 4 1 2 0] [1 6]
# [ 1 4 1 2] X = [4 2]
# [ 2 1 4 1] [1 6]
# [ 0 2 1 4] [2 1]
#
ab = array([[0.0, 0.0, 2.0, 2.0],
[-99, 1.0, 1.0, 1.0],
[4.0, 4.0, 4.0, 4.0]], dtype=float32)
b = array([[1.0, 6.0],
[4.0, 2.0],
[1.0, 6.0],
[2.0, 1.0]], dtype=float32)
x = solveh_banded(ab, b)
expected = array([[0.0, 1.0],
[1.0, 0.0],
[0.0, 1.0],
[0.0, 0.0]])
assert_array_almost_equal(x, expected)
def test_01_complex(self):
# Solve
# [ 4 -j 2 0] [2-j]
# [ j 4 -j 2] X = [4-j]
# [ 2 j 4 -j] [4+j]
# [ 0 2 j 4] [2+j]
#
ab = array([[0.0, 0.0, 2.0, 2.0],
[-99, -1.0j, -1.0j, -1.0j],
[4.0, 4.0, 4.0, 4.0]])
b = array([2-1.0j, 4.0-1j, 4+1j, 2+1j])
x = solveh_banded(ab, b)
assert_array_almost_equal(x, [0.0, 1.0, 1.0, 0.0])
def test_02_complex(self):
# Solve
# [ 4 -j 2 0] [2-j 2+4j]
# [ j 4 -j 2] X = [4-j -1-j]
# [ 2 j 4 -j] [4+j 4+2j]
# [ 0 2 j 4] [2+j j]
#
ab = array([[0.0, 0.0, 2.0, 2.0],
[-99, -1.0j, -1.0j, -1.0j],
[4.0, 4.0, 4.0, 4.0]])
b = array([[2-1j, 2+4j],
[4.0-1j, -1-1j],
[4.0+1j, 4+2j],
[2+1j, 1j]])
x = solveh_banded(ab, b)
expected = array([[0.0, 1.0j],
[1.0, 0.0],
[1.0, 1.0],
[0.0, 0.0]])
assert_array_almost_equal(x, expected)
def test_tridiag_01_upper(self):
# Solve
# [ 4 1 0] [1]
# [ 1 4 1] X = [4]
# [ 0 1 4] [1]
# with the RHS as a 1D array.
ab = array([[-99, 1.0, 1.0], [4.0, 4.0, 4.0]])
b = array([1.0, 4.0, 1.0])
x = solveh_banded(ab, b)
assert_array_almost_equal(x, [0.0, 1.0, 0.0])
def test_tridiag_02_upper(self):
# Solve
# [ 4 1 0] [1 4]
# [ 1 4 1] X = [4 2]
# [ 0 1 4] [1 4]
#
ab = array([[-99, 1.0, 1.0],
[4.0, 4.0, 4.0]])
b = array([[1.0, 4.0],
[4.0, 2.0],
[1.0, 4.0]])
x = solveh_banded(ab, b)
expected = array([[0.0, 1.0],
[1.0, 0.0],
[0.0, 1.0]])
assert_array_almost_equal(x, expected)
def test_tridiag_03_upper(self):
# Solve
# [ 4 1 0] [1]
# [ 1 4 1] X = [4]
# [ 0 1 4] [1]
# with the RHS as a 2D array with shape (3,1).
ab = array([[-99, 1.0, 1.0], [4.0, 4.0, 4.0]])
b = array([1.0, 4.0, 1.0]).reshape(-1, 1)
x = solveh_banded(ab, b)
assert_array_almost_equal(x, array([0.0, 1.0, 0.0]).reshape(-1, 1))
def test_tridiag_01_lower(self):
# Solve
# [ 4 1 0] [1]
# [ 1 4 1] X = [4]
# [ 0 1 4] [1]
#
ab = array([[4.0, 4.0, 4.0],
[1.0, 1.0, -99]])
b = array([1.0, 4.0, 1.0])
x = solveh_banded(ab, b, lower=True)
assert_array_almost_equal(x, [0.0, 1.0, 0.0])
def test_tridiag_02_lower(self):
# Solve
# [ 4 1 0] [1 4]
# [ 1 4 1] X = [4 2]
# [ 0 1 4] [1 4]
#
ab = array([[4.0, 4.0, 4.0],
[1.0, 1.0, -99]])
b = array([[1.0, 4.0],
[4.0, 2.0],
[1.0, 4.0]])
x = solveh_banded(ab, b, lower=True)
expected = array([[0.0, 1.0],
[1.0, 0.0],
[0.0, 1.0]])
assert_array_almost_equal(x, expected)
def test_tridiag_01_float32(self):
# Solve
# [ 4 1 0] [1]
# [ 1 4 1] X = [4]
# [ 0 1 4] [1]
#
ab = array([[-99, 1.0, 1.0], [4.0, 4.0, 4.0]], dtype=float32)
b = array([1.0, 4.0, 1.0], dtype=float32)
x = solveh_banded(ab, b)
assert_array_almost_equal(x, [0.0, 1.0, 0.0])
def test_tridiag_02_float32(self):
# Solve
# [ 4 1 0] [1 4]
# [ 1 4 1] X = [4 2]
# [ 0 1 4] [1 4]
#
ab = array([[-99, 1.0, 1.0],
[4.0, 4.0, 4.0]], dtype=float32)
b = array([[1.0, 4.0],
[4.0, 2.0],
[1.0, 4.0]], dtype=float32)
x = solveh_banded(ab, b)
expected = array([[0.0, 1.0],
[1.0, 0.0],
[0.0, 1.0]])
assert_array_almost_equal(x, expected)
def test_tridiag_01_complex(self):
# Solve
# [ 4 -j 0] [ -j]
# [ j 4 -j] X = [4-j]
# [ 0 j 4] [4+j]
#
ab = array([[-99, -1.0j, -1.0j], [4.0, 4.0, 4.0]])
b = array([-1.0j, 4.0-1j, 4+1j])
x = solveh_banded(ab, b)
assert_array_almost_equal(x, [0.0, 1.0, 1.0])
def test_tridiag_02_complex(self):
# Solve
# [ 4 -j 0] [ -j 4j]
# [ j 4 -j] X = [4-j -1-j]
# [ 0 j 4] [4+j 4 ]
#
ab = array([[-99, -1.0j, -1.0j],
[4.0, 4.0, 4.0]])
b = array([[-1j, 4.0j],
[4.0-1j, -1.0-1j],
[4.0+1j, 4.0]])
x = solveh_banded(ab, b)
expected = array([[0.0, 1.0j],
[1.0, 0.0],
[1.0, 1.0]])
assert_array_almost_equal(x, expected)
def test_check_finite(self):
# Solve
# [ 4 1 0] [1]
# [ 1 4 1] X = [4]
# [ 0 1 4] [1]
# with the RHS as a 1D array.
ab = array([[-99, 1.0, 1.0], [4.0, 4.0, 4.0]])
b = array([1.0, 4.0, 1.0])
x = solveh_banded(ab, b, check_finite=False)
assert_array_almost_equal(x, [0.0, 1.0, 0.0])
def test_bad_shapes(self):
ab = array([[-99, 1.0, 1.0],
[4.0, 4.0, 4.0]])
b = array([[1.0, 4.0],
[4.0, 2.0]])
assert_raises(ValueError, solveh_banded, ab, b)
assert_raises(ValueError, solveh_banded, ab, [1.0, 2.0])
assert_raises(ValueError, solveh_banded, ab, [1.0])
def test_1x1(self):
x = solveh_banded([[1]], [[1, 2, 3]])
assert_array_equal(x, [[1.0, 2.0, 3.0]])
assert_equal(x.dtype, np.dtype('f8'))
def test_native_list_arguments(self):
# Same as test_01_upper, using python's native list.
ab = [[0.0, 0.0, 2.0, 2.0],
[-99, 1.0, 1.0, 1.0],
[4.0, 4.0, 4.0, 4.0]]
b = [1.0, 4.0, 1.0, 2.0]
x = solveh_banded(ab, b)
assert_array_almost_equal(x, [0.0, 1.0, 0.0, 0.0])
class TestSolve:
def setup_method(self):
np.random.seed(1234)
def test_20Feb04_bug(self):
a = [[1, 1], [1.0, 0]] # ok
x0 = solve(a, [1, 0j])
assert_array_almost_equal(dot(a, x0), [1, 0])
# gives failure with clapack.zgesv(..,rowmajor=0)
a = [[1, 1], [1.2, 0]]
b = [1, 0j]
x0 = solve(a, b)
assert_array_almost_equal(dot(a, x0), [1, 0])
def test_simple(self):
a = [[1, 20], [-30, 4]]
for b in ([[1, 0], [0, 1]],
[1, 0],
[[2, 1], [-30, 4]]
):
x = solve(a, b)
assert_array_almost_equal(dot(a, x), b)
def test_simple_complex(self):
a = array([[5, 2], [2j, 4]], 'D')
for b in ([1j, 0],
[[1j, 1j], [0, 2]],
[1, 0j],
array([1, 0], 'D'),
):
x = solve(a, b)
assert_array_almost_equal(dot(a, x), b)
def test_simple_pos(self):
a = [[2, 3], [3, 5]]
for lower in [0, 1]:
for b in ([[1, 0], [0, 1]],
[1, 0]
):
x = solve(a, b, assume_a='pos', lower=lower)
assert_array_almost_equal(dot(a, x), b)
def test_simple_pos_complexb(self):
a = [[5, 2], [2, 4]]
for b in ([1j, 0],
[[1j, 1j], [0, 2]],
):
x = solve(a, b, assume_a='pos')
assert_array_almost_equal(dot(a, x), b)
def test_simple_sym(self):
a = [[2, 3], [3, -5]]
for lower in [0, 1]:
for b in ([[1, 0], [0, 1]],
[1, 0]
):
x = solve(a, b, assume_a='sym', lower=lower)
assert_array_almost_equal(dot(a, x), b)
def test_simple_sym_complexb(self):
a = [[5, 2], [2, -4]]
for b in ([1j, 0],
[[1j, 1j], [0, 2]]
):
x = solve(a, b, assume_a='sym')
assert_array_almost_equal(dot(a, x), b)
def test_simple_sym_complex(self):
a = [[5, 2+1j], [2+1j, -4]]
for b in ([1j, 0],
[1, 0],
[[1j, 1j], [0, 2]]
):
x = solve(a, b, assume_a='sym')
assert_array_almost_equal(dot(a, x), b)
def test_simple_her_actuallysym(self):
a = [[2, 3], [3, -5]]
for lower in [0, 1]:
for b in ([[1, 0], [0, 1]],
[1, 0],
[1j, 0],
):
x = solve(a, b, assume_a='her', lower=lower)
assert_array_almost_equal(dot(a, x), b)
def test_simple_her(self):
a = [[5, 2+1j], [2-1j, -4]]
for b in ([1j, 0],
[1, 0],
[[1j, 1j], [0, 2]]
):
x = solve(a, b, assume_a='her')
assert_array_almost_equal(dot(a, x), b)
def test_nils_20Feb04(self):
n = 2
A = random([n, n])+random([n, n])*1j
X = zeros((n, n), 'D')
Ainv = inv(A)
R = identity(n)+identity(n)*0j
for i in arange(0, n):
r = R[:, i]
X[:, i] = solve(A, r)
assert_array_almost_equal(X, Ainv)
def test_random(self):
n = 20
a = random([n, n])
for i in range(n):
a[i, i] = 20*(.1+a[i, i])
for i in range(4):
b = random([n, 3])
x = solve(a, b)
assert_array_almost_equal(dot(a, x), b)
def test_random_complex(self):
n = 20
a = random([n, n]) + 1j * random([n, n])
for i in range(n):
a[i, i] = 20*(.1+a[i, i])
for i in range(2):
b = random([n, 3])
x = solve(a, b)
assert_array_almost_equal(dot(a, x), b)
def test_random_sym(self):
n = 20
a = random([n, n])
for i in range(n):
a[i, i] = abs(20*(.1+a[i, i]))
for j in range(i):
a[i, j] = a[j, i]
for i in range(4):
b = random([n])
x = solve(a, b, assume_a="pos")
assert_array_almost_equal(dot(a, x), b)
def test_random_sym_complex(self):
n = 20
a = random([n, n])
a = a + 1j*random([n, n])
for i in range(n):
a[i, i] = abs(20*(.1+a[i, i]))
for j in range(i):
a[i, j] = conjugate(a[j, i])
b = random([n])+2j*random([n])
for i in range(2):
x = solve(a, b, assume_a="pos")
assert_array_almost_equal(dot(a, x), b)
def test_check_finite(self):
a = [[1, 20], [-30, 4]]
for b in ([[1, 0], [0, 1]], [1, 0],
[[2, 1], [-30, 4]]):
x = solve(a, b, check_finite=False)
assert_array_almost_equal(dot(a, x), b)
def test_scalar_a_and_1D_b(self):
a = 1
b = [1, 2, 3]
x = solve(a, b)
assert_array_almost_equal(x.ravel(), b)
assert_(x.shape == (3,), 'Scalar_a_1D_b test returned wrong shape')
def test_simple2(self):
a = np.array([[1.80, 2.88, 2.05, -0.89],
[525.00, -295.00, -95.00, -380.00],
[1.58, -2.69, -2.90, -1.04],
[-1.11, -0.66, -0.59, 0.80]])
b = np.array([[9.52, 18.47],
[2435.00, 225.00],
[0.77, -13.28],
[-6.22, -6.21]])
x = solve(a, b)
assert_array_almost_equal(x, np.array([[1., -1, 3, -5],
[3, 2, 4, 1]]).T)
def test_simple_complex2(self):
a = np.array([[-1.34+2.55j, 0.28+3.17j, -6.39-2.20j, 0.72-0.92j],
[-1.70-14.10j, 33.10-1.50j, -1.50+13.40j, 12.90+13.80j],
[-3.29-2.39j, -1.91+4.42j, -0.14-1.35j, 1.72+1.35j],
[2.41+0.39j, -0.56+1.47j, -0.83-0.69j, -1.96+0.67j]])
b = np.array([[26.26+51.78j, 31.32-6.70j],
[64.30-86.80j, 158.60-14.20j],
[-5.75+25.31j, -2.15+30.19j],
[1.16+2.57j, -2.56+7.55j]])
x = solve(a, b)
assert_array_almost_equal(x, np. array([[1+1.j, -1-2.j],
[2-3.j, 5+1.j],
[-4-5.j, -3+4.j],
[6.j, 2-3.j]]))
def test_hermitian(self):
# An upper triangular matrix will be used for hermitian matrix a
a = np.array([[-1.84, 0.11-0.11j, -1.78-1.18j, 3.91-1.50j],
[0, -4.63, -1.84+0.03j, 2.21+0.21j],
[0, 0, -8.87, 1.58-0.90j],
[0, 0, 0, -1.36]])
b = np.array([[2.98-10.18j, 28.68-39.89j],
[-9.58+3.88j, -24.79-8.40j],
[-0.77-16.05j, 4.23-70.02j],
[7.79+5.48j, -35.39+18.01j]])
res = np.array([[2.+1j, -8+6j],
[3.-2j, 7-2j],
[-1+2j, -1+5j],
[1.-1j, 3-4j]])
x = solve(a, b, assume_a='her')
assert_array_almost_equal(x, res)
# Also conjugate a and test for lower triangular data
x = solve(a.conj().T, b, assume_a='her', lower=True)
assert_array_almost_equal(x, res)
def test_pos_and_sym(self):
A = np.arange(1, 10).reshape(3, 3)
x = solve(np.tril(A)/9, np.ones(3), assume_a='pos')
assert_array_almost_equal(x, [9., 1.8, 1.])
x = solve(np.tril(A)/9, np.ones(3), assume_a='sym')
assert_array_almost_equal(x, [9., 1.8, 1.])
def test_singularity(self):
a = np.array([[1, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 1, 1, 0, 0, 0, 1, 0, 1],
[0, 1, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 1, 0, 0, 0],
[1, 0, 1, 1, 1, 1, 0, 0, 0],
[1, 0, 1, 1, 1, 1, 0, 0, 0],
[1, 0, 1, 1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1]])
b = np.arange(9)[:, None]
assert_raises(LinAlgError, solve, a, b)
def test_ill_condition_warning(self):
a = np.array([[1, 1], [1+1e-16, 1-1e-16]])
b = np.ones(2)
with warnings.catch_warnings():
warnings.simplefilter('error')
assert_raises(LinAlgWarning, solve, a, b)
def test_empty_rhs(self):
a = np.eye(2)
b = [[], []]
x = solve(a, b)
assert_(x.size == 0, 'Returned array is not empty')
assert_(x.shape == (2, 0), 'Returned empty array shape is wrong')
def test_multiple_rhs(self):
a = np.eye(2)
b = np.random.rand(2, 3, 4)
x = solve(a, b)
assert_array_almost_equal(x, b)
def test_transposed_keyword(self):
A = np.arange(9).reshape(3, 3) + 1
x = solve(np.tril(A)/9, np.ones(3), transposed=True)
assert_array_almost_equal(x, [1.2, 0.2, 1])
x = solve(np.tril(A)/9, np.ones(3), transposed=False)
assert_array_almost_equal(x, [9, -5.4, -1.2])
def test_transposed_notimplemented(self):
a = np.eye(3).astype(complex)
with assert_raises(NotImplementedError):
solve(a, a, transposed=True)
def test_nonsquare_a(self):
assert_raises(ValueError, solve, [1, 2], 1)
def test_size_mismatch_with_1D_b(self):
assert_array_almost_equal(solve(np.eye(3), np.ones(3)), np.ones(3))
assert_raises(ValueError, solve, np.eye(3), np.ones(4))
def test_assume_a_keyword(self):
assert_raises(ValueError, solve, 1, 1, assume_a='zxcv')
@pytest.mark.skip(reason="Failure on OS X (gh-7500), "
"crash on Windows (gh-8064)")
def test_all_type_size_routine_combinations(self):
sizes = [10, 100]
assume_as = ['gen', 'sym', 'pos', 'her']
dtypes = [np.float32, np.float64, np.complex64, np.complex128]
for size, assume_a, dtype in itertools.product(sizes, assume_as,
dtypes):
is_complex = dtype in (np.complex64, np.complex128)
if assume_a == 'her' and not is_complex:
continue
err_msg = (f"Failed for size: {size}, assume_a: {assume_a},"
f"dtype: {dtype}")
a = np.random.randn(size, size).astype(dtype)
b = np.random.randn(size).astype(dtype)
if is_complex:
a = a + (1j*np.random.randn(size, size)).astype(dtype)
if assume_a == 'sym': # Can still be complex but only symmetric
a = a + a.T
elif assume_a == 'her': # Handle hermitian matrices here instead
a = a + a.T.conj()
elif assume_a == 'pos':
a = a.conj().T.dot(a) + 0.1*np.eye(size)
tol = 1e-12 if dtype in (np.float64, np.complex128) else 1e-6
if assume_a in ['gen', 'sym', 'her']:
# We revert the tolerance from before
# 4b4a6e7c34fa4060533db38f9a819b98fa81476c
if dtype in (np.float32, np.complex64):
tol *= 10
x = solve(a, b, assume_a=assume_a)
assert_allclose(a.dot(x), b,
atol=tol * size,
rtol=tol * size,
err_msg=err_msg)
if assume_a == 'sym' and dtype not in (np.complex64,
np.complex128):
x = solve(a, b, assume_a=assume_a, transposed=True)
assert_allclose(a.dot(x), b,
atol=tol * size,
rtol=tol * size,
err_msg=err_msg)
class TestSolveTriangular:
def test_simple(self):
"""
solve_triangular on a simple 2x2 matrix.
"""
A = array([[1, 0], [1, 2]])
b = [1, 1]
sol = solve_triangular(A, b, lower=True)
assert_array_almost_equal(sol, [1, 0])
# check that it works also for non-contiguous matrices
sol = solve_triangular(A.T, b, lower=False)
assert_array_almost_equal(sol, [.5, .5])
# and that it gives the same result as trans=1
sol = solve_triangular(A, b, lower=True, trans=1)
assert_array_almost_equal(sol, [.5, .5])
b = identity(2)
sol = solve_triangular(A, b, lower=True, trans=1)
assert_array_almost_equal(sol, [[1., -.5], [0, 0.5]])
def test_simple_complex(self):
"""
solve_triangular on a simple 2x2 complex matrix
"""
A = array([[1+1j, 0], [1j, 2]])
b = identity(2)
sol = solve_triangular(A, b, lower=True, trans=1)
assert_array_almost_equal(sol, [[.5-.5j, -.25-.25j], [0, 0.5]])
# check other option combinations with complex rhs
b = np.diag([1+1j, 1+2j])
sol = solve_triangular(A, b, lower=True, trans=0)
assert_array_almost_equal(sol, [[1, 0], [-0.5j, 0.5+1j]])
sol = solve_triangular(A, b, lower=True, trans=1)
assert_array_almost_equal(sol, [[1, 0.25-0.75j], [0, 0.5+1j]])
sol = solve_triangular(A, b, lower=True, trans=2)
assert_array_almost_equal(sol, [[1j, -0.75-0.25j], [0, 0.5+1j]])
sol = solve_triangular(A.T, b, lower=False, trans=0)
assert_array_almost_equal(sol, [[1, 0.25-0.75j], [0, 0.5+1j]])
sol = solve_triangular(A.T, b, lower=False, trans=1)
assert_array_almost_equal(sol, [[1, 0], [-0.5j, 0.5+1j]])
sol = solve_triangular(A.T, b, lower=False, trans=2)
assert_array_almost_equal(sol, [[1j, 0], [-0.5, 0.5+1j]])
def test_check_finite(self):
"""
solve_triangular on a simple 2x2 matrix.
"""
A = array([[1, 0], [1, 2]])
b = [1, 1]
sol = solve_triangular(A, b, lower=True, check_finite=False)
assert_array_almost_equal(sol, [1, 0])
class TestInv:
def setup_method(self):
np.random.seed(1234)
def test_simple(self):
a = [[1, 2], [3, 4]]
a_inv = inv(a)
assert_array_almost_equal(dot(a, a_inv), np.eye(2))
a = [[1, 2, 3], [4, 5, 6], [7, 8, 10]]
a_inv = inv(a)
assert_array_almost_equal(dot(a, a_inv), np.eye(3))
def test_random(self):
n = 20
for i in range(4):
a = random([n, n])
for i in range(n):
a[i, i] = 20*(.1+a[i, i])
a_inv = inv(a)
assert_array_almost_equal(dot(a, a_inv),
identity(n))
def test_simple_complex(self):
a = [[1, 2], [3, 4j]]
a_inv = inv(a)
assert_array_almost_equal(dot(a, a_inv), [[1, 0], [0, 1]])
def test_random_complex(self):
n = 20
for i in range(4):
a = random([n, n])+2j*random([n, n])
for i in range(n):
a[i, i] = 20*(.1+a[i, i])
a_inv = inv(a)
assert_array_almost_equal(dot(a, a_inv),
identity(n))
def test_check_finite(self):
a = [[1, 2], [3, 4]]
a_inv = inv(a, check_finite=False)
assert_array_almost_equal(dot(a, a_inv), [[1, 0], [0, 1]])
class TestDet:
def setup_method(self):
self.rng = np.random.default_rng(1680305949878959)
def test_1x1_all_singleton_dims(self):
a = np.array([[1]])
deta = det(a)
assert deta.dtype.char == 'd'
assert np.isscalar(deta)
assert deta == 1.
a = np.array([[[[1]]]], dtype='f')
deta = det(a)
assert deta.dtype.char == 'd'
assert np.isscalar(deta)
assert deta == 1.
a = np.array([[[1 + 3.j]]], dtype=np.complex64)
deta = det(a)
assert deta.dtype.char == 'D'
assert np.isscalar(deta)
assert deta == 1.+3.j
def test_1by1_stacked_input_output(self):
a = self.rng.random([4, 5, 1, 1], dtype=np.float32)
deta = det(a)
assert deta.dtype.char == 'd'
assert deta.shape == (4, 5)
assert_allclose(deta, np.squeeze(a))
a = self.rng.random([4, 5, 1, 1], dtype=np.float32)*np.complex64(1.j)
deta = det(a)
assert deta.dtype.char == 'D'
assert deta.shape == (4, 5)
assert_allclose(deta, np.squeeze(a))
@pytest.mark.parametrize('shape', [[2, 2], [20, 20], [3, 2, 20, 20]])
def test_simple_det_shapes_real_complex(self, shape):
a = self.rng.uniform(-1., 1., size=shape)
d1, d2 = det(a), np.linalg.det(a)
assert_allclose(d1, d2)
b = self.rng.uniform(-1., 1., size=shape)*1j
b += self.rng.uniform(-0.5, 0.5, size=shape)
d3, d4 = det(b), np.linalg.det(b)
assert_allclose(d3, d4)
def test_for_known_det_values(self):
# Hadamard8
a = np.array([[1, 1, 1, 1, 1, 1, 1, 1],
[1, -1, 1, -1, 1, -1, 1, -1],
[1, 1, -1, -1, 1, 1, -1, -1],
[1, -1, -1, 1, 1, -1, -1, 1],
[1, 1, 1, 1, -1, -1, -1, -1],
[1, -1, 1, -1, -1, 1, -1, 1],
[1, 1, -1, -1, -1, -1, 1, 1],
[1, -1, -1, 1, -1, 1, 1, -1]])
assert_allclose(det(a), 4096.)
# consecutive number array always singular
assert_allclose(det(np.arange(25).reshape(5, 5)), 0.)
# simple anti-diagonal block array
# Upper right has det (-2+1j) and lower right has (-2-1j)
# det(a) = - (-2+1j) (-2-1j) = 5.
a = np.array([[0.+0.j, 0.+0.j, 0.-1.j, 1.-1.j],
[0.+0.j, 0.+0.j, 1.+0.j, 0.-1.j],
[0.+1.j, 1.+1.j, 0.+0.j, 0.+0.j],
[1.+0.j, 0.+1.j, 0.+0.j, 0.+0.j]], dtype=np.complex64)
assert_allclose(det(a), 5.+0.j)
# Fiedler companion complexified
# >>> a = scipy.linalg.fiedler_companion(np.arange(1, 10))
a = np.array([[-2., -3., 1., 0., 0., 0., 0., 0.],
[1., 0., 0., 0., 0., 0., 0., 0.],
[0., -4., 0., -5., 1., 0., 0., 0.],
[0., 1., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., -6., 0., -7., 1., 0.],
[0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., -8., 0., -9.],
[0., 0., 0., 0., 0., 1., 0., 0.]])*1.j
assert_allclose(det(a), 9.)
# g and G dtypes are handled differently in windows and other platforms
@pytest.mark.parametrize('typ', [x for x in np.typecodes['All'][:20]
if x not in 'gG'])
def test_sample_compatible_dtype_input(self, typ):
n = 4
a = self.rng.random([n, n]).astype(typ) # value is not important
assert isinstance(det(a), (np.float64, np.complex128))
def test_incompatible_dtype_input(self):
# Double backslashes needed for escaping pytest regex.
msg = 'cannot be cast to float\\(32, 64\\)'
for c, t in zip('SUO', ['bytes8', 'str32', 'object']):
with assert_raises(TypeError, match=msg):
det(np.array([['a', 'b']]*2, dtype=c))
with assert_raises(TypeError, match=msg):
det(np.array([[b'a', b'b']]*2, dtype='V'))
with assert_raises(TypeError, match=msg):
det(np.array([[100, 200]]*2, dtype='datetime64[s]'))
with assert_raises(TypeError, match=msg):
det(np.array([[100, 200]]*2, dtype='timedelta64[s]'))
def test_empty_edge_cases(self):
assert_allclose(det(np.empty([0, 0])), 1.)
assert_allclose(det(np.empty([0, 0, 0])), np.array([]))
assert_allclose(det(np.empty([3, 0, 0])), np.array([1., 1., 1.]))
with assert_raises(ValueError, match='Last 2 dimensions'):
det(np.empty([0, 0, 3]))
with assert_raises(ValueError, match='at least two-dimensional'):
det(np.array([]))
with assert_raises(ValueError, match='Last 2 dimensions'):
det(np.array([[]]))
with assert_raises(ValueError, match='Last 2 dimensions'):
det(np.array([[[]]]))
def test_overwrite_a(self):
# If all conditions are met then input should be overwritten;
# - dtype is one of 'fdFD'
# - C-contiguous
# - writeable
a = np.arange(9).reshape(3, 3).astype(np.float32)
ac = a.copy()
deta = det(ac, overwrite_a=True)
assert_allclose(deta, 0.)
assert not (a == ac).all()
def test_readonly_array(self):
a = np.array([[2., 0., 1.], [5., 3., -1.], [1., 1., 1.]])
a.setflags(write=False)
# overwrite_a will be overridden
assert_allclose(det(a, overwrite_a=True), 10.)
def test_simple_check_finite(self):
a = [[1, 2], [3, np.inf]]
with assert_raises(ValueError, match='array must not contain'):
det(a)
def direct_lstsq(a, b, cmplx=0):
at = transpose(a)
if cmplx:
at = conjugate(at)
a1 = dot(at, a)
b1 = dot(at, b)
return solve(a1, b1)
class TestLstsq:
lapack_drivers = ('gelsd', 'gelss', 'gelsy', None)
def test_simple_exact(self):
for dtype in REAL_DTYPES:
a = np.array([[1, 20], [-30, 4]], dtype=dtype)
for lapack_driver in TestLstsq.lapack_drivers:
for overwrite in (True, False):
for bt in (((1, 0), (0, 1)), (1, 0),
((2, 1), (-30, 4))):
# Store values in case they are overwritten
# later
a1 = a.copy()
b = np.array(bt, dtype=dtype)
b1 = b.copy()
out = lstsq(a1, b1,
lapack_driver=lapack_driver,
overwrite_a=overwrite,
overwrite_b=overwrite)
x = out[0]
r = out[2]
assert_(r == 2,
'expected efficient rank 2, got %s' % r)
assert_allclose(dot(a, x), b,
atol=25 * _eps_cast(a1.dtype),
rtol=25 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
def test_simple_overdet(self):
for dtype in REAL_DTYPES:
a = np.array([[1, 2], [4, 5], [3, 4]], dtype=dtype)
b = np.array([1, 2, 3], dtype=dtype)
for lapack_driver in TestLstsq.lapack_drivers:
for overwrite in (True, False):
# Store values in case they are overwritten later
a1 = a.copy()
b1 = b.copy()
out = lstsq(a1, b1, lapack_driver=lapack_driver,
overwrite_a=overwrite,
overwrite_b=overwrite)
x = out[0]
if lapack_driver == 'gelsy':
residuals = np.sum((b - a.dot(x))**2)
else:
residuals = out[1]
r = out[2]
assert_(r == 2, 'expected efficient rank 2, got %s' % r)
assert_allclose(abs((dot(a, x) - b)**2).sum(axis=0),
residuals,
rtol=25 * _eps_cast(a1.dtype),
atol=25 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
assert_allclose(x, (-0.428571428571429, 0.85714285714285),
rtol=25 * _eps_cast(a1.dtype),
atol=25 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
def test_simple_overdet_complex(self):
for dtype in COMPLEX_DTYPES:
a = np.array([[1+2j, 2], [4, 5], [3, 4]], dtype=dtype)
b = np.array([1, 2+4j, 3], dtype=dtype)
for lapack_driver in TestLstsq.lapack_drivers:
for overwrite in (True, False):
# Store values in case they are overwritten later
a1 = a.copy()
b1 = b.copy()
out = lstsq(a1, b1, lapack_driver=lapack_driver,
overwrite_a=overwrite,
overwrite_b=overwrite)
x = out[0]
if lapack_driver == 'gelsy':
res = b - a.dot(x)
residuals = np.sum(res * res.conj())
else:
residuals = out[1]
r = out[2]
assert_(r == 2, 'expected efficient rank 2, got %s' % r)
assert_allclose(abs((dot(a, x) - b)**2).sum(axis=0),
residuals,
rtol=25 * _eps_cast(a1.dtype),
atol=25 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
assert_allclose(
x, (-0.4831460674157303 + 0.258426966292135j,
0.921348314606741 + 0.292134831460674j),
rtol=25 * _eps_cast(a1.dtype),
atol=25 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
def test_simple_underdet(self):
for dtype in REAL_DTYPES:
a = np.array([[1, 2, 3], [4, 5, 6]], dtype=dtype)
b = np.array([1, 2], dtype=dtype)
for lapack_driver in TestLstsq.lapack_drivers:
for overwrite in (True, False):
# Store values in case they are overwritten later
a1 = a.copy()
b1 = b.copy()
out = lstsq(a1, b1, lapack_driver=lapack_driver,
overwrite_a=overwrite,
overwrite_b=overwrite)
x = out[0]
r = out[2]
assert_(r == 2, 'expected efficient rank 2, got %s' % r)
assert_allclose(x, (-0.055555555555555, 0.111111111111111,
0.277777777777777),
rtol=25 * _eps_cast(a1.dtype),
atol=25 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
def test_random_exact(self):
rng = np.random.RandomState(1234)
for dtype in REAL_DTYPES:
for n in (20, 200):
for lapack_driver in TestLstsq.lapack_drivers:
for overwrite in (True, False):
a = np.asarray(rng.random([n, n]), dtype=dtype)
for i in range(n):
a[i, i] = 20 * (0.1 + a[i, i])
for i in range(4):
b = np.asarray(rng.random([n, 3]), dtype=dtype)
# Store values in case they are overwritten later
a1 = a.copy()
b1 = b.copy()
out = lstsq(a1, b1,
lapack_driver=lapack_driver,
overwrite_a=overwrite,
overwrite_b=overwrite)
x = out[0]
r = out[2]
assert_(r == n, f'expected efficient rank {n}, '
f'got {r}')
if dtype is np.float32:
assert_allclose(
dot(a, x), b,
rtol=500 * _eps_cast(a1.dtype),
atol=500 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
else:
assert_allclose(
dot(a, x), b,
rtol=1000 * _eps_cast(a1.dtype),
atol=1000 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
@pytest.mark.skipif(IS_MUSL, reason="may segfault on Alpine, see gh-17630")
def test_random_complex_exact(self):
rng = np.random.RandomState(1234)
for dtype in COMPLEX_DTYPES:
for n in (20, 200):
for lapack_driver in TestLstsq.lapack_drivers:
for overwrite in (True, False):
a = np.asarray(rng.random([n, n]) + 1j*rng.random([n, n]),
dtype=dtype)
for i in range(n):
a[i, i] = 20 * (0.1 + a[i, i])
for i in range(2):
b = np.asarray(rng.random([n, 3]), dtype=dtype)
# Store values in case they are overwritten later
a1 = a.copy()
b1 = b.copy()
out = lstsq(a1, b1, lapack_driver=lapack_driver,
overwrite_a=overwrite,
overwrite_b=overwrite)
x = out[0]
r = out[2]
assert_(r == n, f'expected efficient rank {n}, '
f'got {r}')
if dtype is np.complex64:
assert_allclose(
dot(a, x), b,
rtol=400 * _eps_cast(a1.dtype),
atol=400 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
else:
assert_allclose(
dot(a, x), b,
rtol=1000 * _eps_cast(a1.dtype),
atol=1000 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
def test_random_overdet(self):
rng = np.random.RandomState(1234)
for dtype in REAL_DTYPES:
for (n, m) in ((20, 15), (200, 2)):
for lapack_driver in TestLstsq.lapack_drivers:
for overwrite in (True, False):
a = np.asarray(rng.random([n, m]), dtype=dtype)
for i in range(m):
a[i, i] = 20 * (0.1 + a[i, i])
for i in range(4):
b = np.asarray(rng.random([n, 3]), dtype=dtype)
# Store values in case they are overwritten later
a1 = a.copy()
b1 = b.copy()
out = lstsq(a1, b1,
lapack_driver=lapack_driver,
overwrite_a=overwrite,
overwrite_b=overwrite)
x = out[0]
r = out[2]
assert_(r == m, f'expected efficient rank {m}, '
f'got {r}')
assert_allclose(
x, direct_lstsq(a, b, cmplx=0),
rtol=25 * _eps_cast(a1.dtype),
atol=25 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
def test_random_complex_overdet(self):
rng = np.random.RandomState(1234)
for dtype in COMPLEX_DTYPES:
for (n, m) in ((20, 15), (200, 2)):
for lapack_driver in TestLstsq.lapack_drivers:
for overwrite in (True, False):
a = np.asarray(rng.random([n, m]) + 1j*rng.random([n, m]),
dtype=dtype)
for i in range(m):
a[i, i] = 20 * (0.1 + a[i, i])
for i in range(2):
b = np.asarray(rng.random([n, 3]), dtype=dtype)
# Store values in case they are overwritten
# later
a1 = a.copy()
b1 = b.copy()
out = lstsq(a1, b1,
lapack_driver=lapack_driver,
overwrite_a=overwrite,
overwrite_b=overwrite)
x = out[0]
r = out[2]
assert_(r == m, f'expected efficient rank {m}, '
f'got {r}')
assert_allclose(
x, direct_lstsq(a, b, cmplx=1),
rtol=25 * _eps_cast(a1.dtype),
atol=25 * _eps_cast(a1.dtype),
err_msg="driver: %s" % lapack_driver)
def test_check_finite(self):
with suppress_warnings() as sup:
# On (some) OSX this tests triggers a warning (gh-7538)
sup.filter(RuntimeWarning,
"internal gelsd driver lwork query error,.*"
"Falling back to 'gelss' driver.")
at = np.array(((1, 20), (-30, 4)))
for dtype, bt, lapack_driver, overwrite, check_finite in \
itertools.product(REAL_DTYPES,
(((1, 0), (0, 1)), (1, 0), ((2, 1), (-30, 4))),
TestLstsq.lapack_drivers,
(True, False),
(True, False)):
a = at.astype(dtype)
b = np.array(bt, dtype=dtype)
# Store values in case they are overwritten
# later
a1 = a.copy()
b1 = b.copy()
out = lstsq(a1, b1, lapack_driver=lapack_driver,
check_finite=check_finite, overwrite_a=overwrite,
overwrite_b=overwrite)
x = out[0]
r = out[2]
assert_(r == 2, 'expected efficient rank 2, got %s' % r)
assert_allclose(dot(a, x), b,
rtol=25 * _eps_cast(a.dtype),
atol=25 * _eps_cast(a.dtype),
err_msg="driver: %s" % lapack_driver)
def test_zero_size(self):
for a_shape, b_shape in (((0, 2), (0,)),
((0, 4), (0, 2)),
((4, 0), (4,)),
((4, 0), (4, 2))):
b = np.ones(b_shape)
x, residues, rank, s = lstsq(np.zeros(a_shape), b)
assert_equal(x, np.zeros((a_shape[1],) + b_shape[1:]))
residues_should_be = (np.empty((0,)) if a_shape[1]
else np.linalg.norm(b, axis=0)**2)
assert_equal(residues, residues_should_be)
assert_(rank == 0, 'expected rank 0')
assert_equal(s, np.empty((0,)))
class TestPinv:
def setup_method(self):
np.random.seed(1234)
def test_simple_real(self):
a = array([[1, 2, 3], [4, 5, 6], [7, 8, 10]], dtype=float)
a_pinv = pinv(a)
assert_array_almost_equal(dot(a, a_pinv), np.eye(3))
def test_simple_complex(self):
a = (array([[1, 2, 3], [4, 5, 6], [7, 8, 10]],
dtype=float) + 1j * array([[10, 8, 7], [6, 5, 4], [3, 2, 1]],
dtype=float))
a_pinv = pinv(a)
assert_array_almost_equal(dot(a, a_pinv), np.eye(3))
def test_simple_singular(self):
a = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=float)
a_pinv = pinv(a)
expected = array([[-6.38888889e-01, -1.66666667e-01, 3.05555556e-01],
[-5.55555556e-02, 1.30136518e-16, 5.55555556e-02],
[5.27777778e-01, 1.66666667e-01, -1.94444444e-01]])
assert_array_almost_equal(a_pinv, expected)
def test_simple_cols(self):
a = array([[1, 2, 3], [4, 5, 6]], dtype=float)
a_pinv = pinv(a)
expected = array([[-0.94444444, 0.44444444],
[-0.11111111, 0.11111111],
[0.72222222, -0.22222222]])
assert_array_almost_equal(a_pinv, expected)
def test_simple_rows(self):
a = array([[1, 2], [3, 4], [5, 6]], dtype=float)
a_pinv = pinv(a)
expected = array([[-1.33333333, -0.33333333, 0.66666667],
[1.08333333, 0.33333333, -0.41666667]])
assert_array_almost_equal(a_pinv, expected)
def test_check_finite(self):
a = array([[1, 2, 3], [4, 5, 6.], [7, 8, 10]])
a_pinv = pinv(a, check_finite=False)
assert_array_almost_equal(dot(a, a_pinv), np.eye(3))
def test_native_list_argument(self):
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
a_pinv = pinv(a)
expected = array([[-6.38888889e-01, -1.66666667e-01, 3.05555556e-01],
[-5.55555556e-02, 1.30136518e-16, 5.55555556e-02],
[5.27777778e-01, 1.66666667e-01, -1.94444444e-01]])
assert_array_almost_equal(a_pinv, expected)
def test_atol_rtol(self):
n = 12
# get a random ortho matrix for shuffling
q, _ = qr(np.random.rand(n, n))
a_m = np.arange(35.0).reshape(7, 5)
a = a_m.copy()
a[0, 0] = 0.001
atol = 1e-5
rtol = 0.05
# svds of a_m is ~ [116.906, 4.234, tiny, tiny, tiny]
# svds of a is ~ [116.906, 4.234, 4.62959e-04, tiny, tiny]
# Just abs cutoff such that we arrive at a_modified
a_p = pinv(a_m, atol=atol, rtol=0.)
adiff1 = a @ a_p @ a - a
adiff2 = a_m @ a_p @ a_m - a_m
# Now adiff1 should be around atol value while adiff2 should be
# relatively tiny
assert_allclose(np.linalg.norm(adiff1), 5e-4, atol=5.e-4)
assert_allclose(np.linalg.norm(adiff2), 5e-14, atol=5.e-14)
# Now do the same but remove another sv ~4.234 via rtol
a_p = pinv(a_m, atol=atol, rtol=rtol)
adiff1 = a @ a_p @ a - a
adiff2 = a_m @ a_p @ a_m - a_m
assert_allclose(np.linalg.norm(adiff1), 4.233, rtol=0.01)
assert_allclose(np.linalg.norm(adiff2), 4.233, rtol=0.01)
@pytest.mark.parametrize("cond", [1, None, _NoValue])
@pytest.mark.parametrize("rcond", [1, None, _NoValue])
def test_cond_rcond_deprecation(self, cond, rcond):
if cond is _NoValue and rcond is _NoValue:
# the defaults if cond/rcond aren't set -> no warning
pinv(np.ones((2,2)), cond=cond, rcond=rcond)
else:
# at least one of cond/rcond has a user-supplied value -> warn
with pytest.deprecated_call(match='"cond" and "rcond"'):
pinv(np.ones((2,2)), cond=cond, rcond=rcond)
def test_positional_deprecation(self):
with pytest.deprecated_call(match="use keyword arguments"):
pinv(np.ones((2,2)), 0., 1e-10)
class TestPinvSymmetric:
def setup_method(self):
np.random.seed(1234)
def test_simple_real(self):
a = array([[1, 2, 3], [4, 5, 6], [7, 8, 10]], dtype=float)
a = np.dot(a, a.T)
a_pinv = pinvh(a)
assert_array_almost_equal(np.dot(a, a_pinv), np.eye(3))
def test_nonpositive(self):
a = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=float)
a = np.dot(a, a.T)
u, s, vt = np.linalg.svd(a)
s[0] *= -1
a = np.dot(u * s, vt) # a is now symmetric non-positive and singular
a_pinv = pinv(a)
a_pinvh = pinvh(a)
assert_array_almost_equal(a_pinv, a_pinvh)
def test_simple_complex(self):
a = (array([[1, 2, 3], [4, 5, 6], [7, 8, 10]],
dtype=float) + 1j * array([[10, 8, 7], [6, 5, 4], [3, 2, 1]],
dtype=float))
a = np.dot(a, a.conj().T)
a_pinv = pinvh(a)
assert_array_almost_equal(np.dot(a, a_pinv), np.eye(3))
def test_native_list_argument(self):
a = array([[1, 2, 3], [4, 5, 6], [7, 8, 10]], dtype=float)
a = np.dot(a, a.T)
a_pinv = pinvh(a.tolist())
assert_array_almost_equal(np.dot(a, a_pinv), np.eye(3))
def test_atol_rtol(self):
n = 12
# get a random ortho matrix for shuffling
q, _ = qr(np.random.rand(n, n))
a = np.diag([4, 3, 2, 1, 0.99e-4, 0.99e-5] + [0.99e-6]*(n-6))
a = q.T @ a @ q
a_m = np.diag([4, 3, 2, 1, 0.99e-4, 0.] + [0.]*(n-6))
a_m = q.T @ a_m @ q
atol = 1e-5
rtol = (4.01e-4 - 4e-5)/4
# Just abs cutoff such that we arrive at a_modified
a_p = pinvh(a, atol=atol, rtol=0.)
adiff1 = a @ a_p @ a - a
adiff2 = a_m @ a_p @ a_m - a_m
# Now adiff1 should dance around atol value since truncation
# while adiff2 should be relatively tiny
assert_allclose(norm(adiff1), atol, rtol=0.1)
assert_allclose(norm(adiff2), 1e-12, atol=1e-11)
# Now do the same but through rtol cancelling atol value
a_p = pinvh(a, atol=atol, rtol=rtol)
adiff1 = a @ a_p @ a - a
adiff2 = a_m @ a_p @ a_m - a_m
# adiff1 and adiff2 should be elevated to ~1e-4 due to mismatch
assert_allclose(norm(adiff1), 1e-4, rtol=0.1)
assert_allclose(norm(adiff2), 1e-4, rtol=0.1)
@pytest.mark.parametrize('scale', (1e-20, 1., 1e20))
@pytest.mark.parametrize('pinv_', (pinv, pinvh))
def test_auto_rcond(scale, pinv_):
x = np.array([[1, 0], [0, 1e-10]]) * scale
expected = np.diag(1. / np.diag(x))
x_inv = pinv_(x)
assert_allclose(x_inv, expected)
class TestVectorNorms:
def test_types(self):
for dtype in np.typecodes['AllFloat']:
x = np.array([1, 2, 3], dtype=dtype)
tol = max(1e-15, np.finfo(dtype).eps.real * 20)
assert_allclose(norm(x), np.sqrt(14), rtol=tol)
assert_allclose(norm(x, 2), np.sqrt(14), rtol=tol)
for dtype in np.typecodes['Complex']:
x = np.array([1j, 2j, 3j], dtype=dtype)
tol = max(1e-15, np.finfo(dtype).eps.real * 20)
assert_allclose(norm(x), np.sqrt(14), rtol=tol)
assert_allclose(norm(x, 2), np.sqrt(14), rtol=tol)
def test_overflow(self):
# unlike numpy's norm, this one is
# safer on overflow
a = array([1e20], dtype=float32)
assert_almost_equal(norm(a), a)
def test_stable(self):
# more stable than numpy's norm
a = array([1e4] + [1]*10000, dtype=float32)
try:
# snrm in double precision; we obtain the same as for float64
# -- large atol needed due to varying blas implementations
assert_allclose(norm(a) - 1e4, 0.5, atol=1e-2)
except AssertionError:
# snrm implemented in single precision, == np.linalg.norm result
msg = ": Result should equal either 0.0 or 0.5 (depending on " \
"implementation of snrm2)."
assert_almost_equal(norm(a) - 1e4, 0.0, err_msg=msg)
def test_zero_norm(self):
assert_equal(norm([1, 0, 3], 0), 2)
assert_equal(norm([1, 2, 3], 0), 3)
def test_axis_kwd(self):
a = np.array([[[2, 1], [3, 4]]] * 2, 'd')
assert_allclose(norm(a, axis=1), [[3.60555128, 4.12310563]] * 2)
assert_allclose(norm(a, 1, axis=1), [[5.] * 2] * 2)
def test_keepdims_kwd(self):
a = np.array([[[2, 1], [3, 4]]] * 2, 'd')
b = norm(a, axis=1, keepdims=True)
assert_allclose(b, [[[3.60555128, 4.12310563]]] * 2)
assert_(b.shape == (2, 1, 2))
assert_allclose(norm(a, 1, axis=2, keepdims=True), [[[3.], [7.]]] * 2)
@pytest.mark.skipif(not HAS_ILP64, reason="64-bit BLAS required")
def test_large_vector(self):
check_free_memory(free_mb=17000)
x = np.zeros([2**31], dtype=np.float64)
x[-1] = 1
res = norm(x)
del x
assert_allclose(res, 1.0)
class TestMatrixNorms:
def test_matrix_norms(self):
# Not all of these are matrix norms in the most technical sense.
np.random.seed(1234)
for n, m in (1, 1), (1, 3), (3, 1), (4, 4), (4, 5), (5, 4):
for t in np.float32, np.float64, np.complex64, np.complex128, np.int64:
A = 10 * np.random.randn(n, m).astype(t)
if np.issubdtype(A.dtype, np.complexfloating):
A = (A + 10j * np.random.randn(n, m)).astype(t)
t_high = np.complex128
else:
t_high = np.float64
for order in (None, 'fro', 1, -1, 2, -2, np.inf, -np.inf):
actual = norm(A, ord=order)
desired = np.linalg.norm(A, ord=order)
# SciPy may return higher precision matrix norms.
# This is a consequence of using LAPACK.
if not np.allclose(actual, desired):
desired = np.linalg.norm(A.astype(t_high), ord=order)
assert_allclose(actual, desired)
def test_axis_kwd(self):
a = np.array([[[2, 1], [3, 4]]] * 2, 'd')
b = norm(a, ord=np.inf, axis=(1, 0))
c = norm(np.swapaxes(a, 0, 1), ord=np.inf, axis=(0, 1))
d = norm(a, ord=1, axis=(0, 1))
assert_allclose(b, c)
assert_allclose(c, d)
assert_allclose(b, d)
assert_(b.shape == c.shape == d.shape)
b = norm(a, ord=1, axis=(1, 0))
c = norm(np.swapaxes(a, 0, 1), ord=1, axis=(0, 1))
d = norm(a, ord=np.inf, axis=(0, 1))
assert_allclose(b, c)
assert_allclose(c, d)
assert_allclose(b, d)
assert_(b.shape == c.shape == d.shape)
def test_keepdims_kwd(self):
a = np.arange(120, dtype='d').reshape(2, 3, 4, 5)
b = norm(a, ord=np.inf, axis=(1, 0), keepdims=True)
c = norm(a, ord=1, axis=(0, 1), keepdims=True)
assert_allclose(b, c)
assert_(b.shape == c.shape)
class TestOverwrite:
def test_solve(self):
assert_no_overwrite(solve, [(3, 3), (3,)])
def test_solve_triangular(self):
assert_no_overwrite(solve_triangular, [(3, 3), (3,)])
def test_solve_banded(self):
assert_no_overwrite(lambda ab, b: solve_banded((2, 1), ab, b),
[(4, 6), (6,)])
def test_solveh_banded(self):
assert_no_overwrite(solveh_banded, [(2, 6), (6,)])
def test_inv(self):
assert_no_overwrite(inv, [(3, 3)])
def test_det(self):
assert_no_overwrite(det, [(3, 3)])
def test_lstsq(self):
assert_no_overwrite(lstsq, [(3, 2), (3,)])
def test_pinv(self):
assert_no_overwrite(pinv, [(3, 3)])
def test_pinvh(self):
assert_no_overwrite(pinvh, [(3, 3)])
class TestSolveCirculant:
def test_basic1(self):
c = np.array([1, 2, 3, 5])
b = np.array([1, -1, 1, 0])
x = solve_circulant(c, b)
y = solve(circulant(c), b)
assert_allclose(x, y)
def test_basic2(self):
# b is a 2-d matrix.
c = np.array([1, 2, -3, -5])
b = np.arange(12).reshape(4, 3)
x = solve_circulant(c, b)
y = solve(circulant(c), b)
assert_allclose(x, y)
def test_basic3(self):
# b is a 3-d matrix.
c = np.array([1, 2, -3, -5])
b = np.arange(24).reshape(4, 3, 2)
x = solve_circulant(c, b)
y = solve(circulant(c), b)
assert_allclose(x, y)
def test_complex(self):
# Complex b and c
c = np.array([1+2j, -3, 4j, 5])
b = np.arange(8).reshape(4, 2) + 0.5j
x = solve_circulant(c, b)
y = solve(circulant(c), b)
assert_allclose(x, y)
def test_random_b_and_c(self):
# Random b and c
np.random.seed(54321)
c = np.random.randn(50)
b = np.random.randn(50)
x = solve_circulant(c, b)
y = solve(circulant(c), b)
assert_allclose(x, y)
def test_singular(self):
# c gives a singular circulant matrix.
c = np.array([1, 1, 0, 0])
b = np.array([1, 2, 3, 4])
x = solve_circulant(c, b, singular='lstsq')
y, res, rnk, s = lstsq(circulant(c), b)
assert_allclose(x, y)
assert_raises(LinAlgError, solve_circulant, x, y)
def test_axis_args(self):
# Test use of caxis, baxis and outaxis.
# c has shape (2, 1, 4)
c = np.array([[[-1, 2.5, 3, 3.5]], [[1, 6, 6, 6.5]]])
# b has shape (3, 4)
b = np.array([[0, 0, 1, 1], [1, 1, 0, 0], [1, -1, 0, 0]])
x = solve_circulant(c, b, baxis=1)
assert_equal(x.shape, (4, 2, 3))
expected = np.empty_like(x)
expected[:, 0, :] = solve(circulant(c[0]), b.T)
expected[:, 1, :] = solve(circulant(c[1]), b.T)
assert_allclose(x, expected)
x = solve_circulant(c, b, baxis=1, outaxis=-1)
assert_equal(x.shape, (2, 3, 4))
assert_allclose(np.moveaxis(x, -1, 0), expected)
# np.swapaxes(c, 1, 2) has shape (2, 4, 1); b.T has shape (4, 3).
x = solve_circulant(np.swapaxes(c, 1, 2), b.T, caxis=1)
assert_equal(x.shape, (4, 2, 3))
assert_allclose(x, expected)
def test_native_list_arguments(self):
# Same as test_basic1 using python's native list.
c = [1, 2, 3, 5]
b = [1, -1, 1, 0]
x = solve_circulant(c, b)
y = solve(circulant(c), b)
assert_allclose(x, y)
class TestMatrix_Balance:
def test_string_arg(self):
assert_raises(ValueError, matrix_balance, 'Some string for fail')
def test_infnan_arg(self):
assert_raises(ValueError, matrix_balance,
np.array([[1, 2], [3, np.inf]]))
assert_raises(ValueError, matrix_balance,
np.array([[1, 2], [3, np.nan]]))
def test_scaling(self):
_, y = matrix_balance(np.array([[1000, 1], [1000, 0]]))
# Pre/post LAPACK 3.5.0 gives the same result up to an offset
# since in each case col norm is x1000 greater and
# 1000 / 32 ~= 1 * 32 hence balanced with 2 ** 5.
assert_allclose(np.diff(np.log2(np.diag(y))), [5])
def test_scaling_order(self):
A = np.array([[1, 0, 1e-4], [1, 1, 1e-2], [1e4, 1e2, 1]])
x, y = matrix_balance(A)
assert_allclose(solve(y, A).dot(y), x)
def test_separate(self):
_, (y, z) = matrix_balance(np.array([[1000, 1], [1000, 0]]),
separate=1)
assert_equal(np.diff(np.log2(y)), [5])
assert_allclose(z, np.arange(2))
def test_permutation(self):
A = block_diag(np.ones((2, 2)), np.tril(np.ones((2, 2))),
np.ones((3, 3)))
x, (y, z) = matrix_balance(A, separate=1)
assert_allclose(y, np.ones_like(y))
assert_allclose(z, np.array([0, 1, 6, 5, 4, 3, 2]))
def test_perm_and_scaling(self):
# Matrix with its diagonal removed
cases = ( # Case 0
np.array([[0., 0., 0., 0., 0.000002],
[0., 0., 0., 0., 0.],
[2., 2., 0., 0., 0.],
[2., 2., 0., 0., 0.],
[0., 0., 0.000002, 0., 0.]]),
# Case 1 user reported GH-7258
np.array([[-0.5, 0., 0., 0.],
[0., -1., 0., 0.],
[1., 0., -0.5, 0.],
[0., 1., 0., -1.]]),
# Case 2 user reported GH-7258
np.array([[-3., 0., 1., 0.],
[-1., -1., -0., 1.],
[-3., -0., -0., 0.],
[-1., -0., 1., -1.]])
)
for A in cases:
x, y = matrix_balance(A)
x, (s, p) = matrix_balance(A, separate=1)
ip = np.empty_like(p)
ip[p] = np.arange(A.shape[0])
assert_allclose(y, np.diag(s)[ip, :])
assert_allclose(solve(y, A).dot(y), x)