def test_linear_operator_addition(dom_eq_ran): """Check call and adjoint of a sum of linear operators.""" if dom_eq_ran: mat1 = np.random.rand(3, 3) mat2 = np.random.rand(3, 3) else: mat1 = np.random.rand(4, 3) mat2 = np.random.rand(4, 3) op1 = MatrixOperator(mat1) op2 = MatrixOperator(mat2) xarr, x = noise_elements(op1.domain) yarr, y = noise_elements(op1.range) # Explicit instantiation sum_op = OperatorSum(op1, op2) assert sum_op.is_linear assert sum_op.adjoint.is_linear check_call(sum_op, x, np.dot(mat1, xarr) + np.dot(mat2, xarr)) check_call(sum_op.adjoint, y, np.dot(mat1.T, yarr) + np.dot(mat2.T, yarr)) # Using operator overloading check_call(op1 + op2, x, np.dot(mat1, xarr) + np.dot(mat2, xarr)) check_call((op1 + op2).adjoint, y, np.dot(mat1.T, yarr) + np.dot(mat2.T, yarr))
def test_linear_operator_scaling(dom_eq_ran): """Check call and adjoint of a scaled linear operator.""" if dom_eq_ran: mat = np.random.rand(3, 3) else: mat = np.random.rand(4, 3) op = MatrixOperator(mat) xarr, x = noise_elements(op.domain) yarr, y = noise_elements(op.range) # Test a range of scalars (scalar multiplication could implement # optimizations for (-1, 0, 1). scalars = [-1.432, -1, 0, 1, 3.14] for scalar in scalars: # Explicit instantiation scaled_op = OperatorRightScalarMult(op, scalar) assert scaled_op.is_linear assert scaled_op.adjoint.is_linear check_call(scaled_op, x, scalar * np.dot(mat, xarr)) check_call(scaled_op.adjoint, y, scalar * np.dot(mat.T, yarr)) # Using operator overloading check_call(scalar * op, x, scalar * np.dot(mat, xarr)) check_call(op * scalar, x, scalar * np.dot(mat, xarr)) check_call((scalar * op).adjoint, y, scalar * np.dot(mat.T, yarr)) check_call((op * scalar).adjoint, y, scalar * np.dot(mat.T, yarr))
def test_linear_scale(): A = np.random.rand(4, 3) x = np.random.rand(3) y = np.random.rand(4) Aop = MatrixOperator(A) xvec = Aop.domain.element(x) yvec = Aop.range.element(y) # Test a range of scalars (scalar multiplication could implement # optimizations for (-1, 0, 1). scalars = [-1.432, -1, 0, 1, 3.14] for scale in scalars: C = OperatorRightScalarMult(Aop, scale) assert C.is_linear assert C.adjoint.is_linear assert all_almost_equal(C(xvec), scale * np.dot(A, x)) assert all_almost_equal(C.adjoint(yvec), scale * np.dot(A.T, y)) # Using operator overloading assert all_almost_equal((scale * Aop)(xvec), scale * np.dot(A, x)) assert all_almost_equal((Aop * scale)(xvec), np.dot(A, scale * x)) assert all_almost_equal((scale * Aop).adjoint(yvec), scale * np.dot(A.T, y)) assert all_almost_equal((Aop * scale).adjoint(yvec), np.dot(A.T, scale * y))
def test_linear_adjoint(): A = np.random.rand(4, 3) x = np.random.rand(4) out = np.random.rand(3) Aop = MatrixOperator(A) xvec = Aop.range.element(x) outvec = Aop.domain.element() # Using in-place adjoint Aop.adjoint(xvec, outvec) np.dot(A.T, x, out) assert all_almost_equal(out, outvec) # Using out-of-place method assert all_almost_equal(Aop.adjoint(xvec), np.dot(A.T, x))
def test_linear_composition(): A = np.random.rand(5, 4) B = np.random.rand(4, 3) x = np.random.rand(3) y = np.random.rand(5) Aop = MatrixOperator(A) Bop = MatrixOperator(B) xvec = Bop.domain.element(x) yvec = Aop.range.element(y) C = OperatorComp(Aop, Bop) assert C.is_linear assert C.adjoint.is_linear assert all_almost_equal(C(xvec), np.dot(A, np.dot(B, x))) assert all_almost_equal(C.adjoint(yvec), np.dot(B.T, np.dot(A.T, y)))
def test_linear_operator_adjoint(dom_eq_ran): """Check adjoint of a linear operator against NumPy.""" if dom_eq_ran: mat = np.random.rand(3, 3) else: mat = np.random.rand(4, 3) op = MatrixOperator(mat) xarr, x = noise_elements(op.range) check_call(op.adjoint, x, np.dot(mat.T, xarr))
def test_linear_operator_call(dom_eq_ran): """Check call of a linear operator against NumPy, and ``is_linear``.""" if dom_eq_ran: mat = np.random.rand(3, 3) else: mat = np.random.rand(4, 3) op = MatrixOperator(mat) assert op.is_linear xarr, x = noise_elements(op.domain) check_call(op, x, np.dot(mat, xarr))
def test_linear_operator_composition(dom_eq_ran): """Check call and adjoint of linear operator composition.""" if dom_eq_ran: mat1 = np.random.rand(3, 3) mat2 = np.random.rand(3, 3) else: mat1 = np.random.rand(4, 3) mat2 = np.random.rand(3, 4) op1 = MatrixOperator(mat1) op2 = MatrixOperator(mat2) xarr, x = noise_elements(op2.domain) yarr, y = noise_elements(op1.range) # Explicit instantiation comp_op = OperatorComp(op1, op2) assert comp_op.is_linear assert comp_op.adjoint.is_linear check_call(comp_op, x, np.dot(mat1, np.dot(mat2, xarr))) check_call(comp_op.adjoint, y, np.dot(mat2.T, np.dot(mat1.T, yarr))) # Using operator overloading check_call(op1 * op2, x, np.dot(mat1, np.dot(mat2, xarr))) check_call((op1 * op2).adjoint, y, np.dot(mat2.T, np.dot(mat1.T, yarr)))
def test_linear_addition(): A = np.random.rand(4, 3) B = np.random.rand(4, 3) x = np.random.rand(3) y = np.random.rand(4) Aop = MatrixOperator(A) Bop = MatrixOperator(B) xvec = Aop.domain.element(x) yvec = Aop.range.element(y) # Explicit instantiation C = OperatorSum(Aop, Bop) assert C.is_linear assert C.adjoint.is_linear assert all_almost_equal(C(xvec), np.dot(A, x) + np.dot(B, x)) assert all_almost_equal(C.adjoint(yvec), np.dot(A.T, y) + np.dot(B.T, y)) # Using operator overloading assert all_almost_equal((Aop + Bop)(xvec), np.dot(A, x) + np.dot(B, x)) assert all_almost_equal((Aop + Bop).adjoint(yvec), np.dot(A.T, y) + np.dot(B.T, y))
def test_linear_op_nonsquare(): # Verify that the multiply op does indeed work as expected A = np.random.rand(4, 3) x = np.random.rand(3) out = np.random.rand(4) Aop = MatrixOperator(A) xvec = Aop.domain.element(x) outvec = Aop.range.element() # Using out parameter Aop(xvec, outvec) np.dot(A, x, out) assert all_almost_equal(out, outvec) # Using return value assert all_almost_equal(Aop(xvec), np.dot(A, x))
def test_linear_left_vector_mult(dom_eq_ran): """Check call and adjoint of vector x linear operator.""" if dom_eq_ran: mat = np.random.rand(3, 3) else: mat = np.random.rand(4, 3) op = MatrixOperator(mat) xarr, x = noise_elements(op.domain) (yarr, mul_arr), (y, mul) = noise_elements(op.range, n=2) # Explicit instantiation lmult_op = OperatorLeftVectorMult(op, mul) assert lmult_op.is_linear assert lmult_op.adjoint.is_linear check_call(lmult_op, x, mul_arr * np.dot(mat, xarr)) check_call(lmult_op.adjoint, y, np.dot(mat.T, mul_arr * yarr)) # Using operator overloading check_call(mul * op, x, mul_arr * np.dot(mat, xarr)) check_call((mul * op).adjoint, y, np.dot(mat.T, mul_arr * yarr))
def test_linear_right_vector_mult(dom_eq_ran): """Check call and adjoint of linear operator x vector.""" if dom_eq_ran: mat = np.random.rand(3, 3) else: mat = np.random.rand(4, 3) op = MatrixOperator(mat) (xarr, mul_arr), (x, mul) = noise_elements(op.domain, n=2) yarr, y = noise_elements(op.range) # Explicit instantiation rmult_op = OperatorRightVectorMult(op, mul) assert rmult_op.is_linear assert rmult_op.adjoint.is_linear check_call(rmult_op, x, np.dot(mat, mul_arr * xarr)) check_call(rmult_op.adjoint, y, mul_arr * np.dot(mat.T, yarr)) # Using operator overloading check_call(op * mul, x, np.dot(mat, mul_arr * xarr)) check_call((op * mul).adjoint, y, mul_arr * np.dot(mat.T, yarr))
def test_linear_right_vector_mult(): A = np.random.rand(4, 3) Aop = MatrixOperator(A) vec = Aop.domain.element([1, 2, 3]) x = Aop.domain.element([4, 5, 6]) y = Aop.range.element([5, 6, 7, 8]) # Test a range of scalars (scalar multiplication could implement # optimizations for (-1, 0, 1). C = OperatorRightVectorMult(Aop, vec) assert C.is_linear assert C.adjoint.is_linear assert all_almost_equal(C(x), np.dot(A, vec * x)) assert all_almost_equal(C.adjoint(y), vec * np.dot(A.T, y)) assert all_almost_equal(C.adjoint.adjoint(x), C(x)) # Using operator overloading assert all_almost_equal((Aop * vec)(x), np.dot(A, vec * x)) assert all_almost_equal((Aop * vec).adjoint(y), vec * np.dot(A.T, y))
def test_type_errors(): r3 = odl.rn(3) r4 = odl.rn(4) op = MatrixOperator(np.random.rand(3, 3)) r3_elem1 = r3.zero() r3_elem2 = r3.zero() r4_elem1 = r4.zero() r4_elem2 = r4.zero() # Verify that correct usage works op(r3_elem1, r3_elem2) op.adjoint(r3_elem1, r3_elem2) # Test that erroneous usage raises with pytest.raises(OpDomainError): op(r4_elem1) with pytest.raises(OpDomainError): op.adjoint(r4_elem1) with pytest.raises(OpRangeError): op(r3_elem1, r4_elem1) with pytest.raises(OpRangeError): op.adjoint(r3_elem1, r4_elem1) with pytest.raises(OpDomainError): op(r4_elem1, r3_elem1) with pytest.raises(OpDomainError): op.adjoint(r4_elem1, r3_elem1) with pytest.raises(OpDomainError): op(r4_elem1, r4_elem2) with pytest.raises(OpDomainError): op.adjoint(r4_elem1, r4_elem2)