Exemple #1
0
class NumpyListVectorArrayMatrixOperator(NumpyMatrixOperator):
    """Variant of |NumpyMatrixOperator| using |ListVectorArray| instead of |NumpyVectorArray|."""

    def __init__(self, matrix, functional=False, vector=False, solver_options=None, name=None):
        assert not (functional and vector)
        super().__init__(matrix, solver_options=solver_options, name=name)
        if not vector:
            self.source = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[1]))
        if not functional:
            self.range = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[0]))
        self.functional = functional
        self.vector = vector

    def apply(self, U, ind=None, mu=None):
        assert U in self.source
        assert U.check_ind(ind)

        if self.vector:
            V = super().apply(U, ind=ind, mu=mu)
            return ListVectorArray([NumpyVector(v, copy=False) for v in V.data],
                                   subtype=self.range.subtype)

        if ind is None:
            vectors = U._list
        elif isinstance(ind, Number):
            vectors = [U._list[ind]]
        else:
            vectors = (U._list[i] for i in ind)
        V = [self._matrix.dot(v._array) for v in vectors]

        if self.functional:
            return NumpyVectorArray(V) if len(V) > 0 else self.range.empty()
        else:
            return ListVectorArray([NumpyVector(v, copy=False) for v in V], subtype=self.range.subtype)

    def apply_adjoint(self, U, ind=None, mu=None, source_product=None, range_product=None):
        raise NotImplementedError

    def apply_inverse(self, V, ind=None, mu=None, least_squares=False):
        assert V in self.range
        assert V.check_ind(ind)
        assert not self.functional and not self.vector

        if V.dim == 0:
            if self.source.dim == 0 and least_squares:
                return ListVectorArray([NumpyVector(np.zeros(0), copy=False) for _ in range(V.len_ind(ind))],
                                       subtype=self.source.subtype)
            else:
                raise InversionError

        options = (self.solver_options.get('inverse') if self.solver_options else
                   'least_squares' if least_squares else
                   None)

        if options and not least_squares:
            solver_type = options if isinstance(options, str) else options['type']
            if solver_type.startswith('least_squares'):
                self.logger.warn('Least squares solver selected but "least_squares == False"')

        if ind is None:
            vectors = V._list
        elif isinstance(ind, Number):
            vectors = [V._list[ind]]
        else:
            vectors = (V._list[i] for i in ind)

        try:
            return ListVectorArray([NumpyVector(_apply_inverse(self._matrix, v._array.reshape((1, -1)),
                                                               options=options).ravel(),
                                                copy=False)
                                    for v in vectors],
                                   subtype=self.source.subtype)
        except InversionError as e:
            if least_squares and options:
                solver_type = options if isinstance(options, str) else options['type']
                if not solver_type.startswith('least_squares'):
                    msg = str(e) \
                        + '\nNote: linear solver was selected for solving least squares problem (maybe not invertible?)'
                    raise InversionError(msg)
            raise e

    def as_vector(self, mu=None):
        if self.source.dim != 1 and self.range.dim != 1:
            raise TypeError('This operator does not represent a vector or linear functional.')
        return ListVectorArray([NumpyVector(self._matrix.ravel(), copy=True)])

    def assemble_lincomb(self, operators, coefficients, solver_options=None, name=None):
        lincomb = super().assemble_lincomb(operators, coefficients)
        if lincomb is None:
            return None
        else:
            return NumpyListVectorArrayMatrixOperator(lincomb._matrix, solver_options=solver_options, name=name)
Exemple #2
0
class NumpyListVectorArrayMatrixOperator(NumpyMatrixOperator):
    """Variant of |NumpyMatrixOperator| using |ListVectorArray| instead of |NumpyVectorArray|."""

    def __init__(self, matrix, functional=False, vector=False, solver_options=None, name=None):
        assert not (functional and vector)
        super(NumpyListVectorArrayMatrixOperator, self).__init__(matrix, solver_options=solver_options, name=name)
        if not vector:
            self.source = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[1]))
        if not functional:
            self.range = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[0]))
        self.functional = functional
        self.vector = vector

    def apply(self, U, ind=None, mu=None):
        assert U in self.source
        assert U.check_ind(ind)

        if self.vector:
            V = super(NumpyListVectorArrayMatrixOperator, self).apply(U, ind=ind, mu=mu)
            return ListVectorArray([NumpyVector(v, copy=False) for v in V.data], subtype=self.range.subtype)

        if ind is None:
            vectors = U._list
        elif isinstance(ind, Number):
            vectors = [U._list[ind]]
        else:
            vectors = (U._list[i] for i in ind)
        V = [self._matrix.dot(v._array) for v in vectors]

        if self.functional:
            return NumpyVectorArray(V) if len(V) > 0 else self.range.empty()
        else:
            return ListVectorArray([NumpyVector(v, copy=False) for v in V], subtype=self.range.subtype)

    def apply_adjoint(self, U, ind=None, mu=None, source_product=None, range_product=None):
        raise NotImplementedError

    def apply_inverse(self, V, ind=None, mu=None, least_squares=False):
        assert V in self.range
        assert V.check_ind(ind)
        assert not self.functional and not self.vector

        if V.dim == 0:
            if self.source.dim == 0 and least_squares:
                return ListVectorArray(
                    [NumpyVector(np.zeros(0), copy=False) for _ in range(V.len_ind(ind))], subtype=self.source.subtype
                )
            else:
                raise InversionError

        options = (
            self.solver_options.get("inverse") if self.solver_options else "least_squares" if least_squares else None
        )

        if options and not least_squares:
            solver_type = options if isinstance(options, str) else options["type"]
            if solver_type.startswith("least_squares"):
                self.logger.warn('Least squares solver selected but "least_squares == False"')

        if ind is None:
            vectors = V._list
        elif isinstance(ind, Number):
            vectors = [V._list[ind]]
        else:
            vectors = (V._list[i] for i in ind)

        try:
            return ListVectorArray(
                [
                    NumpyVector(
                        _apply_inverse(self._matrix, v._array.reshape((1, -1)), options=options).ravel(), copy=False
                    )
                    for v in vectors
                ],
                subtype=self.source.subtype,
            )
        except InversionError as e:
            if least_squares and options:
                solver_type = options if isinstance(options, str) else options["type"]
                if not solver_type.startswith("least_squares"):
                    msg = (
                        str(e)
                        + "\nNote: linear solver was selected for solving least squares problem (maybe not invertible?)"
                    )
                    raise InversionError(msg)
            raise e

    def as_vector(self, mu=None):
        if self.source.dim != 1 and self.range.dim != 1:
            raise TypeError("This operator does not represent a vector or linear functional.")
        return ListVectorArray([NumpyVector(self._matrix.ravel(), copy=True)])

    def assemble_lincomb(self, operators, coefficients, solver_options=None, name=None):
        lincomb = super(NumpyListVectorArrayMatrixOperator, self).assemble_lincomb(operators, coefficients)
        if lincomb is None:
            return None
        else:
            return NumpyListVectorArrayMatrixOperator(lincomb._matrix, solver_options=solver_options, name=name)
Exemple #3
0
class NumpyListVectorArrayMatrixOperator(NumpyMatrixOperator):
    """Variant of |NumpyMatrixOperator| using |ListVectorArray| instead of |NumpyVectorArray|."""

    def __init__(self, matrix, functional=False, vector=False, name=None):
        assert not (functional and vector)
        super(NumpyListVectorArrayMatrixOperator, self).__init__(matrix, name)
        if not vector:
            self.source = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[1]))
        if not functional:
            self.range = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[0]))
        self.functional = functional
        self.vector = vector

    def apply(self, U, ind=None, mu=None):
        assert U in self.source
        assert U.check_ind(ind)

        if self.vector:
            V = super(NumpyListVectorArrayMatrixOperator, self).apply(U, ind=ind, mu=mu)
            return ListVectorArray([NumpyVector(v, copy=False) for v in V.data],
                                   subtype=self.range.subtype)

        if ind is None:
            vectors = U._list
        elif isinstance(ind, Number):
            vectors = [U._list[ind]]
        else:
            vectors = (U._list[i] for i in ind)
        V = [self._matrix.dot(v._array) for v in vectors]

        if self.functional:
            return NumpyVectorArray(V) if len(V) > 0 else self.range.empty()
        else:
            return ListVectorArray([NumpyVector(v, copy=False) for v in V], subtype=self.range.subtype)

    def apply_adjoint(self, U, ind=None, mu=None, source_product=None, range_product=None):
        raise NotImplementedError

    def apply_inverse(self, U, ind=None, mu=None, options=None):
        assert U in self.range
        assert U.check_ind(ind)
        assert not self.functional and not self.vector

        if U.dim == 0:
            if (self.source.dim == 0
                    or isinstance(options, str) and options.startswith('least_squares')
                    or isinstance(options, dict) and options['type'].startswith('least_squares')):
                return ListVectorArray([NumpyVector(np.zeros(0), copy=False) for _ in range(U.len_ind(ind))],
                                       subtype=self.source.subtype)
            else:
                raise InversionError

        if ind is None:
            vectors = U._list
        elif isinstance(ind, Number):
            vectors = [U._list[ind]]
        else:
            vectors = (U._list[i] for i in ind)

        return ListVectorArray([NumpyVector(_apply_inverse(self._matrix, v._array, options=options), copy=False)
                                for v in vectors],
                               subtype=self.source.subtype)

    def as_vector(self, mu=None):
        if self.source.dim != 1 and self.range.dim != 1:
            raise TypeError('This operator does not represent a vector or linear functional.')
        return ListVectorArray([NumpyVector(self._matrix.ravel(), copy=True)])

    def assemble_lincomb(self, operators, coefficients, name=None):
        lincomb = super(NumpyListVectorArrayMatrixOperator, self).assemble_lincomb(operators, coefficients)
        if lincomb is None:
            return None
        else:
            return NumpyListVectorArrayMatrixOperator(lincomb._matrix, name=name)