def test_pseudo_inverse(): "Tests of the pseudo-inverse" # Numerical version of the pseudo-inverse: pinv_num = core.wrap_array_func(numpy.linalg.pinv) ########## # Full rank rectangular matrix: m = unumpy.matrix([[ufloat((10, 1)), -3.1], [0, ufloat((3, 0))], [1, -3.1]]) # Numerical and package (analytical) pseudo-inverses: they must be # the same: rcond = 1e-8 # Test of the second argument to pinv() m_pinv_num = pinv_num(m, rcond) m_pinv_package = core._pinv(m, rcond) assert matrices_close(m_pinv_num, m_pinv_package) ########## # Example with a non-full rank rectangular matrix: vector = [ufloat((10, 1)), -3.1, 11] m = unumpy.matrix([vector, vector]) m_pinv_num = pinv_num(m, rcond) m_pinv_package = core._pinv(m, rcond) assert matrices_close(m_pinv_num, m_pinv_package) ########## # Example with a non-full-rank square matrix: m = unumpy.matrix([[ufloat((10, 1)), 0], [3, 0]]) m_pinv_num = pinv_num(m, rcond) m_pinv_package = core._pinv(m, rcond) assert matrices_close(m_pinv_num, m_pinv_package)
def test_inverse(): "Tests of the matrix inverse" m = unumpy.matrix([[ufloat((10, 1)), -3.1], [0, ufloat((3, 0))]]) m_nominal_values = unumpy.nominal_values(m) # "Regular" inverse matrix, when uncertainties are not taken # into account: m_no_uncert_inv = m_nominal_values.I # The matrix inversion should not yield numbers with uncertainties: assert m_no_uncert_inv.dtype == numpy.dtype(float) # Inverse with uncertainties: m_inv_uncert = m.I # AffineScalarFunc elements # The inverse contains uncertainties: it must support custom # operations on matrices with uncertainties: assert isinstance(m_inv_uncert, unumpy.matrix) assert type(m_inv_uncert[0, 0]) == uncertainties.AffineScalarFunc # Checks of the numerical values: the diagonal elements of the # inverse should be the inverses of the diagonal elements of # m (because we started with a triangular matrix): assert _numbers_close(1/m_nominal_values[0, 0], m_inv_uncert[0, 0].nominal_value), "Wrong value" assert _numbers_close(1/m_nominal_values[1, 1], m_inv_uncert[1, 1].nominal_value), "Wrong value" #################### # Checks of the covariances between elements: x = ufloat((10, 1)) m = unumpy.matrix([[x, x], [0, 3+2*x]]) m_inverse = m.I # Check of the properties of the inverse: m_double_inverse = m_inverse.I # The initial matrix should be recovered, including its # derivatives, which define covariances: assert _numbers_close(m_double_inverse[0, 0].nominal_value, m[0, 0].nominal_value) assert _numbers_close(m_double_inverse[0, 0].std_dev(), m[0, 0].std_dev()) assert matrices_close(m_double_inverse, m) # Partial test: assert _derivatives_close(m_double_inverse[0, 0], m[0, 0]) assert _derivatives_close(m_double_inverse[1, 1], m[1, 1]) #################### # Tests of covariances during the inversion: # There are correlations if both the next two derivatives are # not zero: assert m_inverse[0, 0].derivatives[x] assert m_inverse[0, 1].derivatives[x] # Correlations between m and m_inverse should create a perfect # inversion: assert matrices_close(m * m_inverse, numpy.eye(m.shape[0]))