Commit 42150f8f authored by Martin Reinecke's avatar Martin Reinecke
Browse files

Merge branch 'model_documentation' into 'NIFTy_5'

Model documentation

See merge request ift/nifty-dev!8
parents d940e72f f4164d98
...@@ -21,9 +21,9 @@ from ..sugar import makeOp ...@@ -21,9 +21,9 @@ from ..sugar import makeOp
from .model import Model from .model import Model
def _joint_position(op1, op2): def _joint_position(model1, model2):
a = op1.position._val a = model1.position._val
b = op2.position._val b = model2.position._val
# Note: In python >3.5 one could do {**a, **b} # Note: In python >3.5 one could do {**a, **b}
ab = a.copy() ab = a.copy()
ab.update(b) ab.update(b)
...@@ -31,57 +31,78 @@ def _joint_position(op1, op2): ...@@ -31,57 +31,78 @@ def _joint_position(op1, op2):
class ScalarMul(Model): class ScalarMul(Model):
def __init__(self, factor, op): """Class representing a model multiplied by a scalar factor."""
# TODO op -> model def __init__(self, factor, model):
super(ScalarMul, self).__init__(op.position) super(ScalarMul, self).__init__(model.position)
# TODO -> floating # TODO -> floating
if not isinstance(factor, (float, int)): if not isinstance(factor, (float, int)):
raise TypeError raise TypeError
self._op = op self._model = model
self._factor = factor self._factor = factor
self._value = self._factor * self._op.value self._value = self._factor * self._model.value
self._gradient = self._factor * self._op.gradient self._gradient = self._factor * self._model.gradient
def at(self, position): def at(self, position):
return self.__class__(self._factor, self._op.at(position)) return self.__class__(self._factor, self._model.at(position))
class Add(Model): class Add(Model):
def __init__(self, position, op1, op2): """Class representing the sum of two models."""
def __init__(self, position, model1, model2):
super(Add, self).__init__(position) super(Add, self).__init__(position)
self._op1 = op1.at(position) self._model1 = model1.at(position)
self._op2 = op2.at(position) self._model2 = model2.at(position)
self._value = self._op1.value + self._op2.value self._value = self._model1.value + self._model2.value
self._gradient = self._op1.gradient + self._op2.gradient self._gradient = self._model1.gradient + self._model2.gradient
@staticmethod @staticmethod
def make(op1, op2): def make(model1, model2):
position = _joint_position(op1, op2) """Build the sum of two models.
return Add(position, op1, op2)
Parameters
----------
model1: Model
First model.
model2: Model
Second model
"""
position = _joint_position(model1, model2)
return Add(position, model1, model2)
def at(self, position): def at(self, position):
return self.__class__(position, self._op1, self._op2) return self.__class__(position, self._model1, self._model2)
class Mul(Model): class Mul(Model):
def __init__(self, position, op1, op2): """Class representing the pointwise product of two models."""
def __init__(self, position, model1, model2):
super(Mul, self).__init__(position) super(Mul, self).__init__(position)
self._op1 = op1.at(position) self._model1 = model1.at(position)
self._op2 = op2.at(position) self._model2 = model2.at(position)
self._value = self._op1.value * self._op2.value self._value = self._model1.value * self._model2.value
self._gradient = (makeOp(self._op1.value) * self._op2.gradient + self._gradient = (makeOp(self._model1.value) * self._model2.gradient +
makeOp(self._op2.value) * self._op1.gradient) makeOp(self._model2.value) * self._model1.gradient)
@staticmethod @staticmethod
def make(op1, op2): def make(model1, model2):
position = _joint_position(op1, op2) """Build the pointwise product of two models.
return Mul(position, op1, op2)
Parameters
----------
model1: Model
First model.
model2: Model
Second model
"""
position = _joint_position(model1, model2)
return Mul(position, model1, model2)
def at(self, position): def at(self, position):
return self.__class__(position, self._op1, self._op2) return self.__class__(position, self._model1, self._model2)
...@@ -15,11 +15,25 @@ ...@@ -15,11 +15,25 @@
# #
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik
# and financially supported by the Studienstiftung des deutschen Volkes. # and financially supported by the Studienstiftung des deutschen Volkes.
from .model import Model from .model import Model
class Constant(Model): class Constant(Model):
"""A sky model with a constant (multi-)field as value.
Parameters
----------
position : Field or MultiField
The current position in parameter space.
constant : Field
The value of the model.
Note
----
Since there is no model-function associated:
- Position has no influence on value.
- There is no gradient.
"""
# TODO Remove position # TODO Remove position
def __init__(self, position, constant): def __init__(self, position, constant):
super(Constant, self).__init__(position) super(Constant, self).__init__(position)
......
...@@ -21,8 +21,20 @@ from .model import Model ...@@ -21,8 +21,20 @@ from .model import Model
class LinearModel(Model): class LinearModel(Model):
def __init__(self, inp, lin_op): def __init__(self, inp, lin_op):
""" """Computes lin_op(inp) where lin_op is a Linear Operator
Computes lin_op(inp) where lin_op is a Linear Operator
Parameters
----------
inp : Model
lin_op : LinearOperator
linear function to be applied to model
Returns
-------
Model with linear Operator applied:
- Model.value = LinOp (inp.value) [key-wise]
- Gradient = LinOp * inp.gradient
""" """
from ..operators.linear_operator import LinearOperator from ..operators.linear_operator import LinearOperator
super(LinearModel, self).__init__(inp.position) super(LinearModel, self).__init__(inp.position)
......
...@@ -26,6 +26,15 @@ class LocalModel(Model): ...@@ -26,6 +26,15 @@ class LocalModel(Model):
def __init__(self, inp, nonlinearity): def __init__(self, inp, nonlinearity):
""" """
Computes nonlinearity(inp) Computes nonlinearity(inp)
- LocalModel.value = nonlinearity(value) (pointwise)
- LocalModel.gradient = Outer Product of gradients
Parameters
----------
inp : Model
The model for which the nonlinarity will be applied.
nonlinearity: Function
The nonlinearity to be applied to model.
""" """
super(LocalModel, self).__init__(inp.position) super(LocalModel, self).__init__(inp.position)
self._inp = inp self._inp = inp
......
...@@ -24,22 +24,66 @@ from ..utilities import NiftyMetaBase ...@@ -24,22 +24,66 @@ from ..utilities import NiftyMetaBase
class Model(NiftyMetaBase()): class Model(NiftyMetaBase()):
"""
The Model object is an implementation of a * which knows:
- position in parameterspace. (Field, MulitField)
- value according to its modelfunction A. A(position)
- gradient of the modelfunction at the current position.
Parameters
----------
position : Field, MulitField
The input parameter of the model
Notes
-----
An instance of the model class knows its position, value and gradient.
One can 'jump' to a new position, with the help of the 'at' method, whereby
one automatically gets the value and gradient of the model. The 'at' method
creates a new instance of the class.
"""
def __init__(self, position): def __init__(self, position):
self._position = position self._position = position
def at(self, position): def at(self, position):
""" Returns a new Model object, initialized at `position`.
Parameters
----------
position : Field or MultiField
Location in parameter space for the new Model object.
Returns
-------
Model
Model object at new position.
"""
raise NotImplementedError raise NotImplementedError
@property @property
def position(self): def position(self):
"""
Field or MultiField: selected location in parameter space.
The location in parameter space where value and gradient are
evaluated.
"""
return self._position return self._position
@property @property
def value(self): def value(self):
"""
Field or MultiField: value of the model.
The value of the model at given `position`.
"""
return self._value return self._value
@property @property
def gradient(self): def gradient(self):
"""
LinearOperator : The derivative of the model at given `position`.
"""
return self._gradient return self._gradient
def __getitem__(self, key): def __getitem__(self, key):
......
...@@ -23,6 +23,7 @@ from .model import Model ...@@ -23,6 +23,7 @@ from .model import Model
class MultiModel(Model): class MultiModel(Model):
""" """
def __init__(self, model, key): def __init__(self, model, key):
# TODO Rewrite it such that it takes a dictionary as input. Just like MultiFields. # TODO Rewrite it such that it takes a dictionary as input. Just like MultiFields.
super(MultiModel, self).__init__(model.position) super(MultiModel, self).__init__(model.position)
......
...@@ -21,8 +21,12 @@ from .model import Model ...@@ -21,8 +21,12 @@ from .model import Model
class Variable(Model): class Variable(Model):
""" """Changes (Multi-)Field to be a Variable model.
Returns the MultiField.
Parameters
----------
position : Field or MultiField
The current position in parameter space.
""" """
def __init__(self, position): def __init__(self, position):
super(Variable, self).__init__(position) super(Variable, self).__init__(position)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment