Commit fc68b05e authored by Martin Reinecke's avatar Martin Reinecke

curvature -> metric

parent a890fda5
...@@ -108,7 +108,7 @@ For a quick start, you can browse through the [informal ...@@ -108,7 +108,7 @@ For a quick start, you can browse through the [informal
introduction](http://ift.pages.mpcdf.de/NIFTy/code.html) or introduction](http://ift.pages.mpcdf.de/NIFTy/code.html) or
dive into NIFTy by running one of the demonstrations, e.g.: dive into NIFTy by running one of the demonstrations, e.g.:
python demos/wiener_filter_via_curvature.py python demos/getting_started_1.py
### Acknowledgement ### Acknowledgement
......
...@@ -74,7 +74,7 @@ if __name__ == '__main__': ...@@ -74,7 +74,7 @@ if __name__ == '__main__':
N_samples = 20 N_samples = 20
for i in range(5): for i in range(5):
H = H.at(position) H = H.at(position)
samples = [H.curvature.draw_sample(from_inverse=True) samples = [H.metric.draw_sample(from_inverse=True)
for _ in range(N_samples)] for _ in range(N_samples)]
KL = ift.SampledKullbachLeiblerDivergence(H, samples) KL = ift.SampledKullbachLeiblerDivergence(H, samples)
......
...@@ -306,16 +306,16 @@ Energy functionals ...@@ -306,16 +306,16 @@ Energy functionals
In NIFTy5 such functions are represented by objects of type :class:`Energy`. In NIFTy5 such functions are represented by objects of type :class:`Energy`.
These hold the prescription how to calculate the function's These hold the prescription how to calculate the function's
:attr:`~Energy.value`, :attr:`~Energy.gradient` and :attr:`~Energy.value`, :attr:`~Energy.gradient` and
(optionally) :attr:`~Energy.curvature` at any given :attr:`~Energy.position` (optionally) :attr:`~Energy.metric` at any given :attr:`~Energy.position`
in parameter space. in parameter space.
Function values are floating-point scalars, gradients have the form of fields Function values are floating-point scalars, gradients have the form of fields
living on the energy's position domain, and curvatures are represented by living on the energy's position domain, and metrics are represented by
linear operator objects. linear operator objects.
Energies are classes that typically have to be provided by the user when Energies are classes that typically have to be provided by the user when
tackling new IFT problems. tackling new IFT problems.
Some examples of concrete energy classes delivered with NIFTy5 are Some examples of concrete energy classes delivered with NIFTy5 are
:class:`QuadraticEnergy` (with position-independent curvature, mainly used with :class:`QuadraticEnergy` (with position-independent metric, mainly used with
conjugate gradient minimization) and :class:`~nifty5.library.WienerFilterEnergy`. conjugate gradient minimization) and :class:`~nifty5.library.WienerFilterEnergy`.
...@@ -367,7 +367,7 @@ This family of algorithms is encapsulated in NIFTy's :class:`DescentMinimizer` ...@@ -367,7 +367,7 @@ This family of algorithms is encapsulated in NIFTy's :class:`DescentMinimizer`
class, which currently has three concrete implementations: class, which currently has three concrete implementations:
:class:`SteepestDescent`, :class:`VL_BFGS`, and :class:`RelaxedNewton`. :class:`SteepestDescent`, :class:`VL_BFGS`, and :class:`RelaxedNewton`.
Of these algorithms, only :class:`RelaxedNewton` requires the energy object to Of these algorithms, only :class:`RelaxedNewton` requires the energy object to
provide a :attr:`~Energy.curvature` property, the others only need energy provide a :attr:`~Energy.metric` property, the others only need energy
values and gradients. values and gradients.
The flexibility of NIFTy's design allows using externally provided The flexibility of NIFTy's design allows using externally provided
......
...@@ -49,13 +49,13 @@ class Hamiltonian(Energy): ...@@ -49,13 +49,13 @@ class Hamiltonian(Energy):
@property @property
@memo @memo
def curvature(self): def metric(self):
prior_curv = self._prior.curvature prior_mtr = self._prior.metric
if self._ic_samp is None: if self._ic_samp is None:
return self._lh.curvature + prior_curv return self._lh.metric + prior_mtr
else: else:
return SamplingEnabler(self._lh.curvature, prior_curv.inverse, return SamplingEnabler(self._lh.metric, prior_mtr.inverse,
self._ic_samp, prior_curv.inverse) self._ic_samp, prior_mtr.inverse)
def __str__(self): def __str__(self):
res = 'Likelihood:\t{:.2E}\n'.format(self._lh.value) res = 'Likelihood:\t{:.2E}\n'.format(self._lh.value)
......
...@@ -33,6 +33,6 @@ class SampledKullbachLeiblerDivergence(Energy): ...@@ -33,6 +33,6 @@ class SampledKullbachLeiblerDivergence(Energy):
@property @property
@memo @memo
def curvature(self): def metric(self):
return (my_sum(map(lambda v: v.curvature, self._energy_list)) * return (my_sum(map(lambda v: v.metric, self._energy_list)) *
(1./len(self._energy_list))) (1./len(self._energy_list)))
...@@ -22,7 +22,7 @@ from ..minimization.energy import Energy ...@@ -22,7 +22,7 @@ from ..minimization.energy import Energy
from ..models.model import Model from ..models.model import Model
__all__ = ["check_value_gradient_consistency", __all__ = ["check_value_gradient_consistency",
"check_value_gradient_curvature_consistency"] "check_value_gradient_metric_consistency"]
def _get_acceptable_model(M): def _get_acceptable_model(M):
...@@ -100,9 +100,9 @@ def check_value_gradient_consistency(E, tol=1e-8, ntries=100): ...@@ -100,9 +100,9 @@ def check_value_gradient_consistency(E, tol=1e-8, ntries=100):
E = Enext E = Enext
def check_value_gradient_curvature_consistency(E, tol=1e-8, ntries=100): def check_value_gradient_metric_consistency(E, tol=1e-8, ntries=100):
if isinstance(E, Model): if isinstance(E, Model):
raise ValueError('Models have no curvature, thus it cannot be tested.') raise ValueError('Models have no metric, thus it cannot be tested.')
for _ in range(ntries): for _ in range(ntries):
E2 = _get_acceptable_energy(E) E2 = _get_acceptable_energy(E)
val = E.value val = E.value
...@@ -112,7 +112,7 @@ def check_value_gradient_curvature_consistency(E, tol=1e-8, ntries=100): ...@@ -112,7 +112,7 @@ def check_value_gradient_curvature_consistency(E, tol=1e-8, ntries=100):
for i in range(50): for i in range(50):
Emid = E.at(E.position + 0.5*dir) Emid = E.at(E.position + 0.5*dir)
dirder = Emid.gradient.vdot(dir)/dirnorm dirder = Emid.gradient.vdot(dir)/dirnorm
dgrad = Emid.curvature(dir)/dirnorm dgrad = Emid.metric(dir)/dirnorm
xtol = tol*Emid.gradient_norm xtol = tol*Emid.gradient_norm
if abs((E2.value-val)/dirnorm - dirder) < xtol and \ if abs((E2.value-val)/dirnorm - dirder) < xtol and \
(abs((E2.gradient-E.gradient)/dirnorm-dgrad) < xtol).all(): (abs((E2.gradient-E.gradient)/dirnorm-dgrad) < xtol).all():
...@@ -121,5 +121,5 @@ def check_value_gradient_curvature_consistency(E, tol=1e-8, ntries=100): ...@@ -121,5 +121,5 @@ def check_value_gradient_curvature_consistency(E, tol=1e-8, ntries=100):
dirnorm *= 0.5 dirnorm *= 0.5
E2 = Emid E2 = Emid
else: else:
raise ValueError("gradient, value and curvature seem inconsistent") raise ValueError("gradient, value and metric seem inconsistent")
E = Enext E = Enext
...@@ -62,7 +62,7 @@ class GaussianEnergy(Energy): ...@@ -62,7 +62,7 @@ class GaussianEnergy(Energy):
@property @property
@memo @memo
def curvature(self): def metric(self):
if self._cov is None: if self._cov is None:
return SandwichOperator.make(self._inp.jacobian, None) return SandwichOperator.make(self._inp.jacobian, None)
return SandwichOperator.make(self._inp.jacobian, self._cov.inverse) return SandwichOperator.make(self._inp.jacobian, self._cov.inverse)
...@@ -44,7 +44,7 @@ class PoissonianEnergy(Energy): ...@@ -44,7 +44,7 @@ class PoissonianEnergy(Energy):
# metric = makeOp(d/lamb_val/lamb_val) # metric = makeOp(d/lamb_val/lamb_val)
metric = makeOp(1./lamb_val) metric = makeOp(1./lamb_val)
self._curvature = SandwichOperator.make(self._lamb.jacobian, metric) self._metric = SandwichOperator.make(self._lamb.jacobian, metric)
def at(self, position): def at(self, position):
return self.__class__(self._lamb.at(position), self._d) return self.__class__(self._lamb.at(position), self._d)
...@@ -58,5 +58,5 @@ class PoissonianEnergy(Energy): ...@@ -58,5 +58,5 @@ class PoissonianEnergy(Energy):
return self._gradient return self._gradient
@property @property
def curvature(self): def metric(self):
return self._curvature return self._metric
...@@ -47,7 +47,7 @@ class ConjugateGradient(Minimizer): ...@@ -47,7 +47,7 @@ class ConjugateGradient(Minimizer):
Parameters Parameters
---------- ----------
energy : Energy object at the starting point of the iteration. energy : Energy object at the starting point of the iteration.
Its curvature operator must be independent of position, otherwise Its metric operator must be independent of position, otherwise
linear conjugate gradient minimization will fail. linear conjugate gradient minimization will fail.
preconditioner : Operator *optional* preconditioner : Operator *optional*
This operator can be provided which transforms the variables of the This operator can be provided which transforms the variables of the
...@@ -73,7 +73,7 @@ class ConjugateGradient(Minimizer): ...@@ -73,7 +73,7 @@ class ConjugateGradient(Minimizer):
return energy, controller.CONVERGED return energy, controller.CONVERGED
while True: while True:
q = energy.curvature(d) q = energy.metric(d)
ddotq = d.vdot(q).real ddotq = d.vdot(q).real
if ddotq == 0.: if ddotq == 0.:
logger.error("Error: ConjugateGradient: ddotq==0.") logger.error("Error: ConjugateGradient: ddotq==0.")
......
...@@ -51,7 +51,7 @@ class DescentMinimizer(Minimizer): ...@@ -51,7 +51,7 @@ class DescentMinimizer(Minimizer):
Parameters Parameters
---------- ----------
energy : Energy energy : Energy
Energy object which provides value, gradient and curvature at a Energy object which provides value, gradient and metric at a
specific position in parameter space. specific position in parameter space.
Returns Returns
......
...@@ -25,7 +25,7 @@ class Energy(NiftyMetaBase()): ...@@ -25,7 +25,7 @@ class Energy(NiftyMetaBase()):
""" Provides the functional used by minimization schemes. """ Provides the functional used by minimization schemes.
The Energy object is an implementation of a scalar function including its The Energy object is an implementation of a scalar function including its
gradient and curvature at some position. gradient and metric at some position.
Parameters Parameters
---------- ----------
...@@ -35,11 +35,11 @@ class Energy(NiftyMetaBase()): ...@@ -35,11 +35,11 @@ class Energy(NiftyMetaBase()):
Notes Notes
----- -----
An instance of the Energy class is defined at a certain location. If one An instance of the Energy class is defined at a certain location. If one
is interested in the value, gradient or curvature of the abstract energy is interested in the value, gradient or metric of the abstract energy
functional one has to 'jump' to the new position using the `at` method. functional one has to 'jump' to the new position using the `at` method.
This method returns a new energy instance residing at the new position. By This method returns a new energy instance residing at the new position. By
this approach, intermediate results from computing e.g. the gradient can this approach, intermediate results from computing e.g. the gradient can
safely be reused for e.g. the value or the curvature. safely be reused for e.g. the value or the metric.
Memorizing the evaluations of some quantities (using the memo decorator) Memorizing the evaluations of some quantities (using the memo decorator)
minimizes the computational effort for multiple calls. minimizes the computational effort for multiple calls.
...@@ -75,7 +75,7 @@ class Energy(NiftyMetaBase()): ...@@ -75,7 +75,7 @@ class Energy(NiftyMetaBase()):
Field : selected location in parameter space. Field : selected location in parameter space.
The Field location in parameter space where value, gradient and The Field location in parameter space where value, gradient and
curvature are evaluated. metric are evaluated.
""" """
return self._position return self._position
...@@ -104,11 +104,11 @@ class Energy(NiftyMetaBase()): ...@@ -104,11 +104,11 @@ class Energy(NiftyMetaBase()):
return self.gradient.norm() return self.gradient.norm()
@property @property
def curvature(self): def metric(self):
""" """
LinearOperator : implicitly defined curvature. LinearOperator : implicitly defined metric.
A positive semi-definite operator or function describing the A positive semi-definite operator or function describing the
curvature of the potential at the given `position`. metric of the potential at the given `position`.
""" """
raise NotImplementedError raise NotImplementedError
...@@ -132,7 +132,7 @@ class Energy(NiftyMetaBase()): ...@@ -132,7 +132,7 @@ class Energy(NiftyMetaBase()):
from .iteration_controller import IterationController from .iteration_controller import IterationController
if not isinstance(controller, IterationController): if not isinstance(controller, IterationController):
raise TypeError raise TypeError
return CurvatureInversionEnabler(self, controller, preconditioner) return MetricInversionEnabler(self, controller, preconditioner)
def __mul__(self, factor): def __mul__(self, factor):
from .energy_sum import EnergySum from .energy_sum import EnergySum
...@@ -160,9 +160,9 @@ class Energy(NiftyMetaBase()): ...@@ -160,9 +160,9 @@ class Energy(NiftyMetaBase()):
return EnergySum.make([self], [-1.]) return EnergySum.make([self], [-1.])
class CurvatureInversionEnabler(Energy): class MetricInversionEnabler(Energy):
def __init__(self, ene, controller, preconditioner): def __init__(self, ene, controller, preconditioner):
super(CurvatureInversionEnabler, self).__init__(ene.position) super(MetricInversionEnabler, self).__init__(ene.position)
self._energy = ene self._energy = ene
self._controller = controller self._controller = controller
self._preconditioner = preconditioner self._preconditioner = preconditioner
...@@ -170,7 +170,7 @@ class CurvatureInversionEnabler(Energy): ...@@ -170,7 +170,7 @@ class CurvatureInversionEnabler(Energy):
def at(self, position): def at(self, position):
if self._position.isSubsetOf(position): if self._position.isSubsetOf(position):
return self return self
return CurvatureInversionEnabler( return MetricInversionEnabler(
self._energy.at(position), self._controller, self._preconditioner) self._energy.at(position), self._controller, self._preconditioner)
@property @property
...@@ -186,16 +186,16 @@ class CurvatureInversionEnabler(Energy): ...@@ -186,16 +186,16 @@ class CurvatureInversionEnabler(Energy):
return self._energy.gradient return self._energy.gradient
@property @property
def curvature(self): def metric(self):
from ..operators.linear_operator import LinearOperator from ..operators.linear_operator import LinearOperator
from ..operators.inversion_enabler import InversionEnabler from ..operators.inversion_enabler import InversionEnabler
curv = self._energy.curvature curv = self._energy.metric
if self._preconditioner is None: if self._preconditioner is None:
precond = None precond = None
elif isinstance(self._preconditioner, LinearOperator): elif isinstance(self._preconditioner, LinearOperator):
precond = self._preconditioner precond = self._preconditioner
elif isinstance(self._preconditioner, Energy): elif isinstance(self._preconditioner, Energy):
precond = self._preconditioner.at(self.position).curvature precond = self._preconditioner.at(self.position).metric
return InversionEnabler(curv, self._controller, precond) return InversionEnabler(curv, self._controller, precond)
def longest_step(self, dir): def longest_step(self, dir):
......
...@@ -67,6 +67,6 @@ class EnergySum(Energy): ...@@ -67,6 +67,6 @@ class EnergySum(Energy):
@property @property
@memo @memo
def curvature(self): def metric(self):
return my_lincomb(map(lambda v: v.curvature, self._energies), return my_lincomb(map(lambda v: v.metric, self._energies),
self._factors) self._factors)
...@@ -21,7 +21,7 @@ from .energy import Energy ...@@ -21,7 +21,7 @@ from .energy import Energy
class QuadraticEnergy(Energy): class QuadraticEnergy(Energy):
"""The Energy for a quadratic form. """The Energy for a quadratic form.
The most important aspect of this energy is that its curvature must be The most important aspect of this energy is that its metric must be
position-independent. position-independent.
""" """
...@@ -74,5 +74,5 @@ class QuadraticEnergy(Energy): ...@@ -74,5 +74,5 @@ class QuadraticEnergy(Energy):
return self._grad return self._grad
@property @property
def curvature(self): def metric(self):
return self._A return self._A
...@@ -24,7 +24,7 @@ class RelaxedNewton(DescentMinimizer): ...@@ -24,7 +24,7 @@ class RelaxedNewton(DescentMinimizer):
""" Calculates the descent direction according to a Newton scheme. """ Calculates the descent direction according to a Newton scheme.
The descent direction is determined by weighting the gradient at the The descent direction is determined by weighting the gradient at the
current parameter position with the inverse local curvature. current parameter position with the inverse local metric.
""" """
def __init__(self, controller, line_searcher=None): def __init__(self, controller, line_searcher=None):
if line_searcher is None: if line_searcher is None:
...@@ -34,4 +34,4 @@ class RelaxedNewton(DescentMinimizer): ...@@ -34,4 +34,4 @@ class RelaxedNewton(DescentMinimizer):
line_searcher=line_searcher) line_searcher=line_searcher)
def get_descent_direction(self, energy): def get_descent_direction(self, energy):
return -energy.curvature.inverse_times(energy.gradient) return -energy.metric.inverse_times(energy.gradient)
...@@ -56,7 +56,7 @@ class _MinHelper(object): ...@@ -56,7 +56,7 @@ class _MinHelper(object):
def hessp(self, x, p): def hessp(self, x, p):
self._update(x) self._update(x)
res = self._energy.curvature(_toField(p, self._domain)) res = self._energy.metric(_toField(p, self._domain))
return _toFlatNdarray(res) return _toFlatNdarray(res)
......
...@@ -32,9 +32,9 @@ class SamplingEnabler(EndomorphicOperator): ...@@ -32,9 +32,9 @@ class SamplingEnabler(EndomorphicOperator):
Parameters Parameters
---------- ----------
likelihood : :class:`EndomorphicOperator` likelihood : :class:`EndomorphicOperator`
Curvature of the likelihood Metric of the likelihood
prior : :class:`EndomorphicOperator` prior : :class:`EndomorphicOperator`
Inverse curvature of the prior Inverse metric of the prior
iteration_controller : :class:`IterationController` iteration_controller : :class:`IterationController`
The iteration controller to use for the iterative numerical inversion The iteration controller to use for the iterative numerical inversion
done by a :class:`ConjugateGradient` object. done by a :class:`ConjugateGradient` object.
......
...@@ -59,7 +59,7 @@ class Energy_Tests(unittest.TestCase): ...@@ -59,7 +59,7 @@ class Energy_Tests(unittest.TestCase):
S = ift.create_power_operator(hspace, power_spectrum=_flat_PS) S = ift.create_power_operator(hspace, power_spectrum=_flat_PS)
energy = ift.WienerFilterEnergy( energy = ift.WienerFilterEnergy(
position=s0, d=d, R=R, N=N, S=S, iteration_controller=IC) position=s0, d=d, R=R, N=N, S=S, iteration_controller=IC)
ift.extra.check_value_gradient_curvature_consistency( ift.extra.check_value_gradient_metric_consistency(
energy, ntries=10) energy, ntries=10)
@expand(product([ift.GLSpace(15), @expand(product([ift.GLSpace(15),
...@@ -94,7 +94,7 @@ class Energy_Tests(unittest.TestCase): ...@@ -94,7 +94,7 @@ class Energy_Tests(unittest.TestCase):
energy = ift.GaussianEnergy(d_model, d, N) energy = ift.GaussianEnergy(d_model, d, N)
if isinstance(nonlinearity(), ift.Linear): if isinstance(nonlinearity(), ift.Linear):
ift.extra.check_value_gradient_curvature_consistency( ift.extra.check_value_gradient_metric_consistency(
energy, ntries=10) energy, ntries=10)
else: else:
ift.extra.check_value_gradient_consistency( ift.extra.check_value_gradient_consistency(
......
...@@ -94,7 +94,7 @@ class Test_Minimizers(unittest.TestCase): ...@@ -94,7 +94,7 @@ class Test_Minimizers(unittest.TestCase):
return out return out
@property @property
def curvature(self): def metric(self):
class RBCurv(ift.EndomorphicOperator): class RBCurv(ift.EndomorphicOperator):
def __init__(self, loc): def __init__(self, loc):
self._loc = loc.to_global_data().copy() self._loc = loc.to_global_data().copy()
...@@ -150,7 +150,7 @@ class Test_Minimizers(unittest.TestCase): ...@@ -150,7 +150,7 @@ class Test_Minimizers(unittest.TestCase):
return ift.Field(self.position.domain, val=2*x*np.exp(-(x**2))) return ift.Field(self.position.domain, val=2*x*np.exp(-(x**2)))
@property @property
def curvature(self): def metric(self):
x = self.position.to_global_data()[0] x = self.position.to_global_data()[0]
v = (2 - 4*x*x)*np.exp(-x**2) v = (2 - 4*x*x)*np.exp(-x**2)
return ift.DiagonalOperator( return ift.DiagonalOperator(
...@@ -188,7 +188,7 @@ class Test_Minimizers(unittest.TestCase): ...@@ -188,7 +188,7 @@ class Test_Minimizers(unittest.TestCase):
return ift.Field(self.position.domain, val=np.sinh(x)) return ift.Field(self.position.domain, val=np.sinh(x))
@property @property
def curvature(self): def metric(self):
x = self.position.to_global_data()[0] x = self.position.to_global_data()[0]
v = np.cosh(x) v = np.cosh(x)
return ift.DiagonalOperator( return ift.DiagonalOperator(
......
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