operator.py 2.99 KB
Newer Older
Martin Reinecke's avatar
Martin Reinecke committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from __future__ import absolute_import, division, print_function

import abc

import numpy as np

from .compat import *
from .utilities import NiftyMetaBase
from .field import Field
from .multi.multi_field import MultiField


class Linearization(object):
    def __init__(self, val, jac):
        self._val = val
        self._jac = jac

    @property
    def domain(self):
        return self._jac.domain

    @property
    def target(self):
        return self._jac.target

    @property
    def val(self):
        return self._val

    @property
    def jac(self):
        return self._jac

    def __neg__(self):
        return Linearization(-self._val, self._jac*(-1))

    def __add__(self, other):
        if isinstance(other, Linearization):
Martin Reinecke's avatar
more  
Martin Reinecke committed
39
40
            from .operators.relaxed_sum_operator import RelaxedSumOperator
            return Linearization(
Martin Reinecke's avatar
more  
Martin Reinecke committed
41
                self._val.unite(other._val),
Martin Reinecke's avatar
more  
Martin Reinecke committed
42
                RelaxedSumOperator((self._jac, other._jac)))
Martin Reinecke's avatar
Martin Reinecke committed
43
44
45
46
47
48
49
50
51
52
53
54
55
        if isinstance(other, (int, float, complex, Field, MultiField)):
            return Linearization(self._val+other, self._jac)

    def __radd__(self, other):
        return self.__add__(other)

    def __sub__(self, other):
        return self.__add__(-other)

    def __rsub__(self, other):
        return (-self).__add__(other)

    def __mul__(self, other):
Martin Reinecke's avatar
more  
Martin Reinecke committed
56
        from .sugar import makeOp
Martin Reinecke's avatar
Martin Reinecke committed
57
        if isinstance(other, Linearization):
Martin Reinecke's avatar
more  
Martin Reinecke committed
58
59
            d1 = makeOp(self._val)
            d2 = makeOp(other._val)
Martin Reinecke's avatar
Martin Reinecke committed
60
            return Linearization(self._val*other._val,
Martin Reinecke's avatar
Martin Reinecke committed
61
                                 d2*self._jac + d1*other._jac)
Martin Reinecke's avatar
Martin Reinecke committed
62
        if isinstance(other, (int, float, complex)):
Martin Reinecke's avatar
more  
Martin Reinecke committed
63
64
            # if other == 0:
            #     return ...
Martin Reinecke's avatar
Martin Reinecke committed
65
66
            return Linearization(self._val*other, self._jac*other)
        if isinstance(other, (Field, MultiField)):
Martin Reinecke's avatar
more  
Martin Reinecke committed
67
            d2 = makeOp(other)
Martin Reinecke's avatar
Martin Reinecke committed
68
69
70
71
            return Linearization(self._val*other, self._jac*d2)
        raise TypeError

    def __rmul__(self, other):
Martin Reinecke's avatar
more  
Martin Reinecke committed
72
        from .sugar import makeOp
Martin Reinecke's avatar
Martin Reinecke committed
73
74
75
        if isinstance(other, (int, float, complex)):
            return Linearization(self._val*other, self._jac*other)
        if isinstance(other, (Field, MultiField)):
Martin Reinecke's avatar
more  
Martin Reinecke committed
76
            d1 = makeOp(other)
Martin Reinecke's avatar
Martin Reinecke committed
77
78
79
80
            return Linearization(self._val*other, d1*self._jac)

    @staticmethod
    def make_var(field):
Martin Reinecke's avatar
Martin Reinecke committed
81
        from .operators.scaling_operator import ScalingOperator
Martin Reinecke's avatar
Martin Reinecke committed
82
        return Linearization(field, ScalingOperator(1., field.domain))
Martin Reinecke's avatar
more  
Martin Reinecke committed
83

Martin Reinecke's avatar
Martin Reinecke committed
84
85
    @staticmethod
    def make_const(field):
Martin Reinecke's avatar
more  
Martin Reinecke committed
86
87
        from .operators.null_operator import NullOperator
        return Linearization(field, NullOperator({}, field.domain))
Martin Reinecke's avatar
Martin Reinecke committed
88

Martin Reinecke's avatar
more  
Martin Reinecke committed
89

Martin Reinecke's avatar
Martin Reinecke committed
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
class Operator(NiftyMetaBase()):
    """Transforms values living on one domain into values living on another
    domain, and can also provide the Jacobian.
    """

    def __call__(self, x):
        """Returns transformed x

        Parameters
        ----------
        x : Linearization
            input

        Returns
        -------
        Linearization
            output
        """
        raise NotImplementedError