def apply_inverse_adjoint(self, U, ind=None, mu=None, source_product=None, range_product=None, least_squares=False): from pymor.operators.constructions import FixedParameterOperator assembled_op = self.assemble(mu) if assembled_op != self and not isinstance(assembled_op, FixedParameterOperator): return assembled_op.apply_inverse_adjoint(U, ind=ind, source_product=source_product, range_product=range_product, least_squares=least_squares) elif source_product or range_product: if source_product: U = source_product.apply(U, ind=ind) ind = None # maybe there is a better implementation for source_product == None and range_product == None V = self.apply_inverse_adjoint(U, mu=mu, least_squares=least_squares) if range_product: return range_product.apply_inverse(V) else: return V else: if not self.linear: raise NotImplementedError # use generic solver for the adjoint operator from pymor.operators.constructions import AdjointOperator options = {'inverse': self.solver_options.get('inverse_adjoint') if self.solver_options else None} adjoint_op = AdjointOperator(self, with_apply_inverse=False, solver_options=options) return adjoint_op.apply_inverse(U, ind=ind, mu=mu, least_squares=least_squares)
def apply_inverse_adjoint(self, U, mu=None, least_squares=False): """Apply the inverse adjoint operator. Parameters ---------- U |VectorArray| of vectors to which the inverse adjoint operator is applied. mu The |Parameter| for which to evaluate the inverse adjoint operator. least_squares If `True`, solve the least squares problem:: v = argmin ||op^*(v) - u||_2. Since for an invertible operator the least squares solution agrees with the result of the application of the inverse operator, setting this option should, in general, have no effect on the result for those operators. However, note that when no appropriate |solver_options| are set for the operator, most operator implementations will choose a least squares solver by default which may be undesirable. Returns ------- |VectorArray| of the inverse adjoint operator evaluations. Raises ------ InversionError The operator could not be inverted. """ from pymor.operators.constructions import FixedParameterOperator if not self.linear: raise LinAlgError('Operator not linear.') assembled_op = self.assemble(mu) if assembled_op != self and not isinstance(assembled_op, FixedParameterOperator): return assembled_op.apply_inverse_adjoint( U, least_squares=least_squares) else: # use generic solver for the adjoint operator from pymor.operators.constructions import AdjointOperator options = { 'inverse': self.solver_options.get('inverse_adjoint') if self.solver_options else None } adjoint_op = AdjointOperator(self, with_apply_inverse=False, solver_options=options) return adjoint_op.apply_inverse(U, mu=mu, least_squares=least_squares)
def apply_inverse_adjoint(self, U, mu=None, least_squares=False): from pymor.operators.constructions import FixedParameterOperator if not self.linear: raise LinAlgError('Operator not linear.') assembled_op = self.assemble(mu) if assembled_op != self and not isinstance(assembled_op, FixedParameterOperator): return assembled_op.apply_inverse_adjoint(U, least_squares=least_squares) else: # use generic solver for the adjoint operator from pymor.operators.constructions import AdjointOperator options = {'inverse': self.solver_options.get('inverse_adjoint') if self.solver_options else None} adjoint_op = AdjointOperator(self, with_apply_inverse=False, solver_options=options) return adjoint_op.apply_inverse(U, mu=mu, least_squares=least_squares)
def apply_inverse_transpose(self, U, mu=None, least_squares=False): from pymor.operators.constructions import FixedParameterOperator assembled_op = self.assemble(mu) if assembled_op != self and not isinstance(assembled_op, FixedParameterOperator): return assembled_op.apply_inverse_transpose(U, least_squares=least_squares) else: if not self.linear: raise NotImplementedError # use generic solver for the transpose operator from pymor.operators.constructions import AdjointOperator options = {'inverse': self.solver_options.get('inverse_transpose') if self.solver_options else None} transpose_op = AdjointOperator(self, with_apply_inverse=False, solver_options=options) return transpose_op.apply_inverse(U, mu=mu, least_squares=least_squares)
def apply_inverse_transpose(self, U, mu=None, least_squares=False): from pymor.operators.constructions import FixedParameterOperator assembled_op = self.assemble(mu) if assembled_op != self and not isinstance(assembled_op, FixedParameterOperator): return assembled_op.apply_inverse_transpose(U, least_squares=least_squares) else: if not self.linear: raise NotImplementedError # use generic solver for the transpose operator from pymor.operators.constructions import AdjointOperator options = {'inverse': self.solver_options.get('inverse_transpose') if self.solver_options else None} transpose_op = AdjointOperator(self, with_apply_inverse=False, solver_options=options) return transpose_op.apply_inverse(U, mu=mu, least_squares=least_squares)
def test_to_matrix(): np.random.seed(0) A = np.random.randn(2, 2) B = np.random.randn(3, 3) C = np.random.randn(3, 3) X = np.bmat([[np.eye(2) + A, np.zeros((2, 3))], [np.zeros((3, 2)), B.dot(C.T)]]) C = sps.csc_matrix(C) Aop = NumpyMatrixOperator(A) Bop = NumpyMatrixOperator(B) Cop = NumpyMatrixOperator(C) Xop = BlockDiagonalOperator([ LincombOperator([IdentityOperator(NumpyVectorSpace(2)), Aop], [1, 1]), Concatenation(Bop, AdjointOperator(Cop)) ]) assert np.allclose(X, to_matrix(Xop)) assert np.allclose(X, to_matrix(Xop, format='csr').toarray()) np.random.seed(0) V = np.random.randn(10, 2) Vva = NumpyVectorArray(V.T) Vop = VectorArrayOperator(Vva) assert np.allclose(V, to_matrix(Vop)) Vop = VectorArrayOperator(Vva, transposed=True) assert np.allclose(V, to_matrix(Vop).T)
def apply_inverse_adjoint(self, U, ind=None, mu=None, source_product=None, range_product=None, least_squares=False): from pymor.operators.constructions import FixedParameterOperator assembled_op = self.assemble(mu) if assembled_op != self and not isinstance(assembled_op, FixedParameterOperator): return assembled_op.apply_inverse_adjoint( U, ind=ind, source_product=source_product, range_product=range_product, least_squares=least_squares) elif source_product or range_product: if source_product: U = source_product.apply(U, ind=ind) ind = None # maybe there is a better implementation for source_product == None and range_product == None V = self.apply_inverse_adjoint(U, mu=mu, least_squares=least_squares) if range_product: return range_product.apply_inverse(V) else: return V else: if not self.linear: raise NotImplementedError # use generic solver for the adjoint operator from pymor.operators.constructions import AdjointOperator options = { 'inverse': self.solver_options.get('inverse_adjoint') if self.solver_options else None } adjoint_op = AdjointOperator(self, with_apply_inverse=False, solver_options=options) return adjoint_op.apply_inverse(U, ind=ind, mu=mu, least_squares=least_squares)
def action_AdjointOperator(self, op): range_basis, source_basis = self.range_basis, self.source_basis if range_basis is not None: if op.source_product: range_basis = op.source_product.apply_inverse(range_basis) if source_basis is not None and op.range_product: source_basis = op.range_product.apply(source_basis) operator = project(op.operator, source_basis, range_basis) range_product = op.range_product if source_basis is None else None source_product = op.source_product if range_basis is None else None return AdjointOperator(operator, source_product=source_product, range_product=range_product, name=op.name)
def test_to_matrix_AdjointOperator(): np.random.seed(0) A = np.random.randn(2, 2) S = np.random.randn(2, 2) S = S.dot(S.T) R = np.random.randn(2, 2) R = R.dot(R.T) Aop = NumpyMatrixOperator(A) Aadj = AdjointOperator(Aop) assert_type_and_allclose(A.T, Aadj, 'dense') Aop = NumpyMatrixOperator(sps.csc_matrix(A)) Aadj = AdjointOperator(Aop) assert_type_and_allclose(A.T, Aadj, 'sparse') Aop = NumpyMatrixOperator(A) Sop = NumpyMatrixOperator(S) Rop = NumpyMatrixOperator(R) Aadj = AdjointOperator(Aop, source_product=Sop, range_product=Rop) assert_type_and_allclose(spla.solve(S, A.T.dot(R)), Aadj, 'dense') Aop = NumpyMatrixOperator(sps.csc_matrix(A)) Sop = NumpyMatrixOperator(S) Rop = NumpyMatrixOperator(R) Aadj = AdjointOperator(Aop, source_product=Sop, range_product=Rop) assert_type_and_allclose(spla.solve(S, A.T.dot(R)), Aadj, 'dense') Aop = NumpyMatrixOperator(A) Sop = NumpyMatrixOperator(S) Rop = NumpyMatrixOperator(sps.csc_matrix(R)) Aadj = AdjointOperator(Aop, source_product=Sop, range_product=Rop) assert_type_and_allclose(spla.solve(S, A.T.dot(R)), Aadj, 'dense') Aop = NumpyMatrixOperator(sps.csc_matrix(A)) Sop = NumpyMatrixOperator(sps.csc_matrix(S)) Rop = NumpyMatrixOperator(sps.csc_matrix(R)) Aadj = AdjointOperator(Aop, source_product=Sop, range_product=Rop) assert_type_and_allclose(spla.solve(S, A.T.dot(R)), Aadj, 'sparse')
def H(self): from pymor.operators.constructions import AdjointOperator return AdjointOperator(self)
def misc_operator_with_arrays_and_products_factory(n): if n == 0: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 10, 4, 3, n) op = ComponentProjection(np.random.randint(0, 100, 10), U.space) return op, _, U, V, sp, rp elif n == 1: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 0, 4, 3, n) op = ComponentProjection([], U.space) return op, _, U, V, sp, rp elif n == 2: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 3, 4, 3, n) op = ComponentProjection([3, 3, 3], U.space) return op, _, U, V, sp, rp elif n == 3: from pymor.operators.constructions import AdjointOperator op, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 20, 4, 3, n) op = AdjointOperator(op, with_apply_inverse=True) return op, _, V, U, rp, sp elif n == 4: from pymor.operators.constructions import AdjointOperator op, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 20, 4, 3, n) op = AdjointOperator(op, with_apply_inverse=False) return op, _, V, U, rp, sp elif 5 <= n <= 7: from pymor.operators.constructions import SelectionOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 30, 30, 4, 3, n) op1 = NumpyMatrixOperator(np.random.random((30, 30))) op2 = NumpyMatrixOperator(np.random.random((30, 30))) op = SelectionOperator([op0, op1, op2], ProjectionParameterFunctional('x'), [0.3, 0.6]) return op, op.parameters.parse((n - 5) / 2), V, U, rp, sp elif n == 8: from pymor.operators.block import BlockDiagonalOperator op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory( 20, 20, 4, 3, n + 1) op2, _, U2, V2, sp2, rp2 = numpy_matrix_operator_with_arrays_and_products_factory( 30, 30, 4, 3, n + 2) op = BlockDiagonalOperator([op0, op1, op2]) sp = BlockDiagonalOperator([sp0, sp1, sp2]) rp = BlockDiagonalOperator([rp0, rp1, rp2]) U = op.source.make_array([U0, U1, U2]) V = op.range.make_array([V0, V1, V2]) return op, _, U, V, sp, rp elif n == 9: from pymor.operators.block import BlockDiagonalOperator, BlockOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0a, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op0b, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op0c, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory( 20, 20, 4, 3, n + 1) op2a, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2b, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op0 = (op0a * ProjectionParameterFunctional('p', 3, 0) + op0b * ProjectionParameterFunctional('p', 3, 1) + op0c * ProjectionParameterFunctional('p', 3, 1)) op2 = (op2a * ProjectionParameterFunctional('p', 3, 0) + op2b * ProjectionParameterFunctional('q', 1)) op = BlockOperator([[op0, op2], [None, op1]]) mu = op.parameters.parse({'p': [1, 2, 3], 'q': 4}) sp = BlockDiagonalOperator([sp0, sp1]) rp = BlockDiagonalOperator([rp0, rp1]) U = op.source.make_array([U0, U1]) V = op.range.make_array([V0, V1]) return op, mu, U, V, sp, rp elif n == 10: from pymor.operators.block import BlockDiagonalOperator, BlockColumnOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory( 20, 20, 4, 3, n + 1) op2a, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2b, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2 = (op2a * ProjectionParameterFunctional('p', 3, 0) + op2b * ProjectionParameterFunctional('q', 1)) op = BlockColumnOperator([op2, op1]) mu = op.parameters.parse({'p': [1, 2, 3], 'q': 4}) sp = sp1 rp = BlockDiagonalOperator([rp0, rp1]) U = U1 V = op.range.make_array([V0, V1]) return op, mu, U, V, sp, rp elif n == 11: from pymor.operators.block import BlockDiagonalOperator, BlockRowOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory( 20, 20, 4, 3, n + 1) op2a, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2b, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2 = (op2a * ProjectionParameterFunctional('p', 3, 0) + op2b * ProjectionParameterFunctional('q', 1)) op = BlockRowOperator([op0, op2]) mu = op.parameters.parse({'p': [1, 2, 3], 'q': 4}) sp = BlockDiagonalOperator([sp0, sp1]) rp = rp0 U = op.source.make_array([U0, U1]) V = V0 return op, mu, U, V, sp, rp else: assert False
def misc_operator_with_arrays_and_products_factory(n): if n == 0: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 10, 4, 3, n) op = ComponentProjection(np.random.randint(0, 100, 10), U.space) return op, _, U, V, sp, rp elif n == 1: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 0, 4, 3, n) op = ComponentProjection([], U.space) return op, _, U, V, sp, rp elif n == 2: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 3, 4, 3, n) op = ComponentProjection([3, 3, 3], U.space) return op, _, U, V, sp, rp elif n == 3: from pymor.operators.constructions import AdjointOperator op, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 20, 4, 3, n) op = AdjointOperator(op, with_apply_inverse=True) return op, _, V, U, rp, sp elif n == 4: from pymor.operators.constructions import AdjointOperator op, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 20, 4, 3, n) op = AdjointOperator(op, with_apply_inverse=False) return op, _, V, U, rp, sp elif 5 <= n <= 7: from pymor.operators.constructions import SelectionOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(30, 30, 4, 3, n) op1 = NumpyMatrixOperator(np.random.random((30, 30))) op2 = NumpyMatrixOperator(np.random.random((30, 30))) op = SelectionOperator([op0, op1, op2], ProjectionParameterFunctional('x', ()), [0.3, 0.6]) return op, op.parse_parameter((n-5)/2), V, U, rp, sp elif n == 8: from pymor.operators.block import BlockDiagonalOperator from pymor.vectorarrays.block import BlockVectorArray op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory(10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory(20, 20, 4, 3, n+1) op2, _, U2, V2, sp2, rp2 = numpy_matrix_operator_with_arrays_and_products_factory(30, 30, 4, 3, n+2) op = BlockDiagonalOperator([op0, op1, op2]) sp = BlockDiagonalOperator([sp0, sp1, sp2]) rp = BlockDiagonalOperator([rp0, rp1, rp2]) U = BlockVectorArray([U0, U1, U2]) V = BlockVectorArray([V0, V1, V2]) return op, _, U, V, sp, rp elif n == 9: from pymor.operators.block import BlockDiagonalOperator, BlockOperator from pymor.vectorarrays.block import BlockVectorArray op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory(10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory(20, 20, 4, 3, n+1) op2, _, U2, V2, sp2, rp2 = numpy_matrix_operator_with_arrays_and_products_factory(20, 10, 4, 3, n+2) op = BlockOperator([[op0, op2], [None, op1]]) sp = BlockDiagonalOperator([sp0, sp1]) rp = BlockDiagonalOperator([rp0, rp1]) U = BlockVectorArray([U0, U1]) V = BlockVectorArray([V0, V1]) return op, None, U, V, sp, rp else: assert False