Beispiel #1
0
def test_real():
    C = ComplexNumbers()
    R = RealNumbers()
    Z = Integers()

    # __contains__
    assert -1 in R
    assert 1 in R
    assert 0 in R
    assert -1.0 in R
    assert 1.0 in R
    assert 0.0 in R

    assert 2j not in R
    assert 2 + 2j not in R
    assert 'a' not in R

    # contains_set
    assert not R.contains_set(C)
    assert R.contains_set(R)
    assert C.contains_set(Z)

    # __eq__
    assert R != C
    assert R == R
    assert R != Z

    # element
    assert C.element() == float(0.0)
    assert C.element(1) == float(1.0)
Beispiel #2
0
    def _call(self, vf, out):
        """Implement ``self(vf, out)``."""
        if self.domain.field == ComplexNumbers():
            out.multiply(vf[0], self._vecfield[0].conj())
        else:
            out.multiply(vf[0], self._vecfield[0])

        if self.is_weighted:
            out *= self.weights[0]

        if self.domain.size == 1:
            return

        tmp = self.range.element()
        for vfi, gi, wi in zip(vf[1:], self.vecfield[1:],
                               self.weights[1:]):

            if self.domain.field == ComplexNumbers():
                tmp.multiply(vfi, gi.conj())
            else:
                tmp.multiply(vfi, gi)

            if self.is_weighted:
                tmp *= wi
            out += tmp
Beispiel #3
0
def test_real():
    C = ComplexNumbers()
    R = RealNumbers()
    Z = Integers()

    # __contains__
    assert -1 in R
    assert 1 in R
    assert 0 in R
    assert -1.0 in R
    assert 1.0 in R
    assert 0.0 in R

    assert 2j not in R
    assert 2 + 2j not in R
    assert 'a' not in R

    # contains_set
    assert not R.contains_set(C)
    assert R.contains_set(R)
    assert C.contains_set(Z)

    # __eq__
    assert R != C
    assert R == R
    assert R != Z

    # element
    assert C.element() == float(0.0)
    assert C.element(1) == float(1.0)
Beispiel #4
0
    def default_dtype(field=None):
        """Return the default of `Fn` data type for a given field.

        Parameters
        ----------
        field : `Field`
            Set of numbers to be represented by a data type.
            Currently supported : `RealNumbers`, `ComplexNumbers`

        Returns
        -------
        dtype : `type`
            Numpy data type specifier. The returned defaults are:

            ``RealNumbers()`` : ``np.dtype('float32')``

            ``ComplexNumbers()`` : `NotImplemented`
        """
        if field is None or field == RealNumbers():
            return np.dtype('float32')
        elif field == ComplexNumbers():
            return NotImplemented
        else:
            raise ValueError('no default data type defined for field {}'
                             ''.format(field))
Beispiel #5
0
def test_integers():
    C = ComplexNumbers()
    R = RealNumbers()
    Z = Integers()

    # __contains__
    assert -1 in Z
    assert 1 in Z
    assert 0 in Z

    assert -1.0 not in Z
    assert 1.0 not in Z
    assert 0.0 not in Z
    assert 2j not in Z
    assert 2 + 2j not in Z
    assert 'a' not in Z

    # contains_set
    assert not Z.contains_set(C)
    assert not Z.contains_set(R)
    assert Z.contains_set(Z)

    # __eq__
    assert Z != C
    assert Z != R
    assert Z == Z

    # element
    assert Z.element() == int(0)
    assert Z.element(1) == int(1)
    assert Z.element(1.5) == int(1.5)
Beispiel #6
0
def test_complex():
    C = ComplexNumbers()
    R = RealNumbers()
    Z = Integers()

    # __contains__
    assert -1 in C
    assert 1 in C
    assert 0 in C
    assert -1.0 in C
    assert 1.0 in C
    assert 0.0 in C
    assert 2j in C
    assert 2 + 2j in C

    assert 'a' not in C

    # contains_set
    assert C.contains_set(C)
    assert C.contains_set(R)
    assert C.contains_set(Z)

    # __eq__
    assert C == C
    assert C != R
    assert C != Z

    # element
    assert C.element() == complex(0.0, 0.0)
    assert C.element(1) == complex(1.0, 0.0)
    assert C.element(1 + 2j) == complex(1.0, 2.0)
Beispiel #7
0
def test_complex():
    C = ComplexNumbers()
    R = RealNumbers()
    Z = Integers()

    # __contains__
    assert -1 in C
    assert 1 in C
    assert 0 in C
    assert -1.0 in C
    assert 1.0 in C
    assert 0.0 in C
    assert 2j in C
    assert 2 + 2j in C

    assert 'a' not in C

    # contains_set
    assert C.contains_set(C)
    assert C.contains_set(R)
    assert C.contains_set(Z)

    # __eq__
    assert C == C
    assert C != R
    assert C != Z

    # element
    assert C.element() == complex(0.0, 0.0)
    assert C.element(1) == complex(1.0, 0.0)
    assert C.element(1 + 2j) == complex(1.0, 2.0)
Beispiel #8
0
    def __init__(self, shape, dtype):
        """Initialize a new instance.

        Parameters
        ----------
        shape : nonnegative int or sequence of nonnegative ints
            Number of entries of type ``dtype`` per axis in this space. A
            single integer results in a space with rank 1, i.e., 1 axis.
        dtype :
            Data type of elements in this space. Can be provided
            in any way the `numpy.dtype` constructor understands, e.g.
            as built-in type or as a string.
            For a data type with a ``dtype.shape``, these extra dimensions
            are added *to the left* of ``shape``.
        """
        # Handle shape and dtype, taking care also of dtypes with shape
        try:
            shape, shape_in = tuple(safe_int_conv(s) for s in shape), shape
        except TypeError:
            shape, shape_in = (safe_int_conv(shape), ), shape
        if any(s < 0 for s in shape):
            raise ValueError('`shape` must have only nonnegative entries, got '
                             '{}'.format(shape_in))
        dtype = np.dtype(dtype)

        # We choose this order in contrast to Numpy, since we usually want
        # to represent discretizations of vector- or tensor-valued functions,
        # i.e., if dtype.shape == (3,) we expect f[0] to have shape `shape`.
        self.__shape = dtype.shape + shape
        self.__dtype = dtype.base

        if is_real_dtype(self.dtype):
            # real includes non-floating-point like integers
            field = RealNumbers()
            self.__real_dtype = self.dtype
            self.__real_space = self
            self.__complex_dtype = TYPE_MAP_R2C.get(self.dtype, None)
            self.__complex_space = None  # Set in first call of astype
        elif is_complex_floating_dtype(self.dtype):
            field = ComplexNumbers()
            self.__real_dtype = TYPE_MAP_C2R[self.dtype]
            self.__real_space = None  # Set in first call of astype
            self.__complex_dtype = self.dtype
            self.__complex_space = self
        else:
            field = None

        LinearSpace.__init__(self, field)
Beispiel #9
0
    def derivative(self, vf):
        """Derivative of the point-wise norm operator at ``vf``.

        The derivative at ``F`` of the point-wise norm operator ``N``
        with finite exponent ``p`` and weights ``w`` is the pointwise
        inner product with the vector field

            ``x --> N(F)(x)^(1-p) * [ F_j(x) * |F_j(x)|^(p-2) ]_j``.

        Note that this is not well-defined for ``F = 0``. If ``p < 2``,
        any zero component will result in a singularity.

        Parameters
        ----------
        vf : domain `element-like`
            Vector field ``F`` at which to evaluate the derivative

        Returns
        -------
        deriv : `PointwiseInner`
            Derivative operator at the given point ``vf``

        Raises
        ------
        NotImplementedError
            * if the vector field space is complex, since the derivative
              is not linear in that case
            * if the exponent is ``inf``
        """
        if self.domain.field == ComplexNumbers():
            raise NotImplementedError('operator not Frechet-differentiable '
                                      'on a complex space')

        if self.exponent == float('inf'):
            raise NotImplementedError('operator not Frechet-differentiable '
                                      'for exponent = inf')

        vf = self.domain.element(vf)
        vf_pwnorm_fac = self(vf)
        vf_pwnorm_fac **= (self.exponent - 1)

        inner_vf = vf.copy()

        for gi in inner_vf:
            gi /= vf_pwnorm_fac * gi ** (self.exponent - 2)

        return PointwiseInner(self.domain, inner_vf, weight=self.weights)
Beispiel #10
0
    def __str__(self):
        """Return ``str(self)``."""
        inner_str = '{}'.format(self.domain)
        dtype_str = dtype_repr(self.out_dtype)

        if self.field == RealNumbers():
            if self.out_dtype == np.dtype('float64'):
                pass
            else:
                inner_str += ', out_dtype={}'.format(dtype_str)

        elif self.field == ComplexNumbers():
            if self.out_dtype == np.dtype('complex128'):
                inner_str += ', field={!r}'.format(self.field)
            else:
                inner_str += ', out_dtype={}'.format(dtype_str)

        else:  # different field, name explicitly
            inner_str += ', field={!r}'.format(self.field)
            inner_str += ', out_dtype={}'.format(dtype_str)

        return '{}({})'.format(self.__class__.__name__, inner_str)
Beispiel #11
0
    def __init__(self, size, dtype):
        """Initialize a new instance.

        Parameters
        ----------
        size : `int`
            The number of dimensions of the space
        dtype : `object`
            The data type of the storage array. Can be provided in any
            way the `numpy.dtype` function understands, most notably
            as built-in type, as one of NumPy's internal datatype
            objects or as string.
            Only scalar data types (numbers) are allowed.
        """
        NtuplesBase.__init__(self, size, dtype)

        if not is_scalar_dtype(self.dtype):
            raise TypeError('{!r} is not a scalar data type'.format(dtype))

        if is_real_dtype(self.dtype):
            field = RealNumbers()
            self._is_real = True
            self._real_dtype = self.dtype
            self._real_space = self
            self._complex_dtype = _TYPE_MAP_R2C.get(self.dtype, None)
            self._complex_space = None  # Set in first call of astype
        else:
            field = ComplexNumbers()
            self._is_real = False
            self._real_dtype = _TYPE_MAP_C2R[self.dtype]
            self._real_space = None  # Set in first call of astype
            self._complex_dtype = self.dtype
            self._complex_space = self

        self._is_floating = is_floating_dtype(self.dtype)
        LinearSpace.__init__(self, field)
Beispiel #12
0
    def __init__(self, domain, field=None, out_dtype=None):
        """Initialize a new instance.

        Parameters
        ----------
        domain : `Set`
            The domain of the functions
        field : `Field`, optional
            The range of the functions, usually the `RealNumbers` or
            `ComplexNumbers`. If not given, the field is either inferred
            from ``out_dtype``, or, if the latter is also `None`, set
            to ``RealNumbers()``.
        out_dtype : optional
            Data type of the return value of a function in this space.
            Can be given in any way `numpy.dtype` understands, e.g. as
            string ('float64') or data type (`float`).
            By default, 'float64' is used for real and 'complex128'
            for complex spaces.
        """
        if not isinstance(domain, Set):
            raise TypeError('`domain` {!r} not a Set instance'.format(domain))

        if field is not None and not isinstance(field, Field):
            raise TypeError('`field` {!r} not a `Field` instance'
                            ''.format(field))

        # Data type: check if consistent with field, take default for None
        dtype, dtype_in = np.dtype(out_dtype), out_dtype

        # Default for both None
        if field is None and out_dtype is None:
            field = RealNumbers()
            out_dtype = np.dtype('float64')

        # field None, dtype given -> infer field
        elif field is None:
            if is_real_dtype(dtype):
                field = RealNumbers()
            elif is_complex_floating_dtype(dtype):
                field = ComplexNumbers()
            else:
                raise ValueError('{} is not a scalar data type'
                                 ''.format(dtype_in))

        # field given -> infer dtype if not given, else check consistency
        elif field == RealNumbers():
            if out_dtype is None:
                out_dtype = np.dtype('float64')
            elif not is_real_dtype(dtype):
                raise ValueError('{} is not a real data type'
                                 ''.format(dtype_in))
        elif field == ComplexNumbers():
            if out_dtype is None:
                out_dtype = np.dtype('complex128')
            elif not is_complex_floating_dtype(dtype):
                raise ValueError('{} is not a complex data type'
                                 ''.format(dtype_in))

        # Else: keep out_dtype=None, which results in lazy dtype determination

        LinearSpace.__init__(self, field)
        FunctionSet.__init__(self, domain, field, out_dtype)

        # Init cache attributes for real / complex variants
        if self.field == RealNumbers():
            self._real_out_dtype = self.out_dtype
            self._real_space = self
            self._complex_out_dtype = _TYPE_MAP_R2C.get(self.out_dtype,
                                                        np.dtype(object))
            self._complex_space = None
        elif self.field == ComplexNumbers():
            self._real_out_dtype = _TYPE_MAP_C2R[self.out_dtype]
            self._real_space = None
            self._complex_out_dtype = self.out_dtype
            self._complex_space = self
        else:
            self._real_out_dtype = None
            self._real_space = None
            self._complex_out_dtype = None
            self._complex_space = None
Beispiel #13
0
    def __init__(self, vfspace, vecfield, weight=None):
        """Initialize a new instance.

        Parameters
        ----------
        vfspace : `ProductSpace`
            Space of vector fields on which the operator acts.
            It has to be a product space of identical spaces, i.e. a
            power space.
        vecfield : domain `element-like`
            Vector field with which to calculate the point-wise inner
            product of an input vector field
        weight : `array-like` or `float`, optional
            Weighting array or constant for the norm. If an array is
            given, its length must be equal to ``domain.size``, and
            all entries must be positive. A provided constant must be
            positive.
            By default, the weights are is taken from
            ``domain.weighting``. Note that this excludes unusual
            weightings with custom inner product, norm or dist.

        Examples
        --------
        We make a tiny vector field space in 2D and create the
        point-wise inner product operator with a fixed vector field.
        The operator maps a vector field to a scalar function:

        >>> import odl
        >>> spc = odl.uniform_discr([-1, -1], [1, 1], (1, 2))
        >>> vfspace = odl.ProductSpace(spc, 2)
        >>> fixed_vf = np.array([[[0, 1]],
        ...                      [[1, -1]]])
        >>> pw_inner = PointwiseInner(vfspace, fixed_vf)
        >>> pw_inner.range == spc
        True

        Now we can calculate the inner product in each point:

        >>> x = vfspace.element([[[1, -4]],
        ...                      [[0, 3]]])
        >>> print(pw_inner(x))
        [[0.0, -7.0]]
        """
        if not isinstance(vfspace, ProductSpace):
            raise TypeError('`vfsoace` {!r} is not a ProductSpace '
                            'instance'.format(vfspace))
        super().__init__(domain=vfspace, range=vfspace[0], linear=True)

        # Bail out if the space is complex but we cannot take the complex
        # conjugate.
        if (self.domain.field == ComplexNumbers() and
                not hasattr(self.base_space.element_type, 'conj')):
            raise NotImplementedError(
                'base space element type {!r} does not implement conj() '
                'method required for complex inner products'
                ''.format(self.base_space.element_type))

        self._vecfield = self.domain.element(vecfield)

        # Handle weighting, including sanity checks
        if weight is None:
            if hasattr(self.domain.weighting, 'vector'):
                self._weights = self.domain.weighting.vector
            elif hasattr(self.domain.weighting, 'const'):
                self._weights = (self.domain.weighting.const *
                                 np.ones(len(self.domain)))
            else:
                raise ValueError('weighting scheme {!r} of the domain does '
                                 'not define a weighting vector or constant'
                                 ''.format(self.domain.weighting))
        elif np.isscalar(weight):
            if weight <= 0:
                raise ValueError('weighting constant must be positive, got '
                                 '{}'.format(weight))
            self._weights = float(weight) * np.ones(self.domain.size)
        else:
            self._weights = np.asarray(weight, dtype='float64')
            if (not np.all(self.weights > 0) or
                    not np.all(np.isfinite(self.weights))):
                raise ValueError('weighting array {} contains invalid '
                                 'entries'.format(weight))
        self._is_weighted = not np.array_equiv(self.weights, 1.0)