Commit d013a4c9 authored by Martin Reinecke's avatar Martin Reinecke
Browse files

Merge branch 'NIFTy_5' into mr_docs

parents fbde69fd 972e8bc7
...@@ -10,6 +10,7 @@ setup.cfg ...@@ -10,6 +10,7 @@ setup.cfg
.document .document
.svn/ .svn/
*.csv *.csv
.pytest_cache/
# from https://github.com/github/gitignore/blob/master/Python.gitignore # from https://github.com/github/gitignore/blob/master/Python.gitignore
......
...@@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y \ ...@@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y \
# Documentation build dependencies # Documentation build dependencies
python3-sphinx python3-sphinx-rtd-theme python3-numpydoc \ python3-sphinx python3-sphinx-rtd-theme python3-numpydoc \
# Testing dependencies # Testing dependencies
python3-coverage python3-parameterized python3-pytest python3-pytest-cov \ python3-coverage python3-pytest python3-pytest-cov \
# Optional NIFTy dependencies # Optional NIFTy dependencies
openmpi-bin libopenmpi-dev python3-mpi4py \ openmpi-bin libopenmpi-dev python3-mpi4py \
# Packages needed for NIFTy # Packages needed for NIFTy
......
...@@ -15,20 +15,12 @@ ...@@ -15,20 +15,12 @@
# #
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
from builtins import str import pytest
import numpy as np
from parameterized import parameterized
np.seterr(all='raise', under='ignore') def list2fixture(lst):
@pytest.fixture(params=lst)
def myfixture(request):
return request.param
return myfixture
def _custom_name_func(testcase_func, param_num, param):
return "{}_{}".format(
testcase_func.__name__,
parameterized.to_safe_name("_".join(str(x) for x in param.args)),
)
def expand(*args, **kwargs):
return parameterized.expand(*args, func=_custom_name_func, **kwargs)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright(C) 2013-2019 Max-Planck-Society
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
import unittest
from itertools import product
from test.common import expand
import nifty5 as ift
import numpy as np
class Energy_Tests(unittest.TestCase):
def make_operator(self, **kwargs):
np.random.seed(kwargs['seed'])
S = ift.ScalingOperator(1., kwargs['space'])
s = S.draw_sample()
return ift.MultiField.from_dict({kwargs['space_key']: s})
@expand(product(
[ift.GLSpace(15),
ift.RGSpace(64, distances=.789),
ift.RGSpace([32, 32], distances=.789)],
[4, 78, 23]
))
def testGaussian(self, space, seed):
op = self.make_operator(
space_key='s1', space=space, seed=seed)['s1']
energy = ift.GaussianEnergy(domain=space)
ift.extra.check_value_gradient_consistency(energy, op)
# @expand(product(
# [ift.GLSpace(15),
# ift.RGSpace(64, distances=.789),
# ift.RGSpace([32, 32], distances=.789)],
# [4, 78, 23]
# ))
# def testQuadratic(self, type1, space, seed):
# np.random.seed(seed)
# S = ift.ScalingOperator(1., space)
# s = [S.draw_sample() for _ in range(3)]
# energy = ift.QuadraticEnergy(s[0], ift.makeOp(s[1]), s[2])
# ift.extra.check_value_gradient_consistency(energy)
@expand(
product([
ift.GLSpace(15),
ift.RGSpace(64, distances=.789),
ift.RGSpace([32, 32], distances=.789)
], [4, 78, 23]))
def testInverseGammaLikelihood(self, space, seed):
op = self.make_operator(space_key='s1', space=space, seed=seed)['s1']
op = op.exp()
d = np.random.normal(10, size=space.shape)**2
d = ift.Field.from_global_data(space, d)
energy = ift.InverseGammaLikelihood(d)
ift.extra.check_value_gradient_consistency(energy, op, tol=1e-7)
@expand(product(
[ift.GLSpace(15),
ift.RGSpace(64, distances=.789),
ift.RGSpace([32, 32], distances=.789)],
[4, 78, 23]
))
def testPoissonian(self, space, seed):
op = self.make_operator(
space_key='s1', space=space, seed=seed)['s1']
op = op.exp()
d = np.random.poisson(120, size=space.shape)
d = ift.Field.from_global_data(space, d)
energy = ift.PoissonianEnergy(d)
ift.extra.check_value_gradient_consistency(energy, op, tol=1e-7)
@expand(product(
[ift.GLSpace(15),
ift.RGSpace(64, distances=.789),
ift.RGSpace([32, 32], distances=.789)],
[4, 78, 23]
))
def testHamiltonian_and_KL(self, space, seed):
op = self.make_operator(
space_key='s1', space=space, seed=seed)['s1']
op = op.exp()
lh = ift.GaussianEnergy(domain=space)
hamiltonian = ift.Hamiltonian(lh)
ift.extra.check_value_gradient_consistency(hamiltonian, op)
S = ift.ScalingOperator(1., space)
samps = [S.draw_sample() for i in range(3)]
kl = ift.SampledKullbachLeiblerDivergence(hamiltonian, samps)
ift.extra.check_value_gradient_consistency(kl, op)
@expand(product(
[ift.GLSpace(15),
ift.RGSpace(64, distances=.789),
ift.RGSpace([32, 32], distances=.789)],
[4, 78, 23]
))
def testBernoulli(self, space, seed):
op = self.make_operator(
space_key='s1', space=space, seed=seed)['s1']
op = op.sigmoid()
d = np.random.binomial(1, 0.1, size=space.shape)
d = ift.Field.from_global_data(space, d)
energy = ift.BernoulliEnergy(d)
ift.extra.check_value_gradient_consistency(energy, op, tol=1e-6)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright(C) 2013-2019 Max-Planck-Society
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
import numpy as np
import pytest
import nifty5 as ift
from itertools import product
# Currently it is not possible to parametrize fixtures. But this will
# hopefully be fixed in the future.
# https://docs.pytest.org/en/latest/proposals/parametrize_with_fixtures.html
SPACES = [
ift.GLSpace(15),
ift.RGSpace(64, distances=.789),
ift.RGSpace([32, 32], distances=.789)
]
SEEDS = [4, 78, 23]
PARAMS = product(SEEDS, SPACES)
@pytest.fixture(params=PARAMS)
def field(request):
np.random.seed(request.param[0])
S = ift.ScalingOperator(1., request.param[1])
s = S.draw_sample()
return ift.MultiField.from_dict({'s1': s})['s1']
def test_gaussian(field):
energy = ift.GaussianEnergy(domain=field.domain)
ift.extra.check_value_gradient_consistency(energy, field)
def test_inverse_gamma(field):
field = field.exp()
space = field.domain
d = np.random.normal(10, size=space.shape)**2
d = ift.Field.from_global_data(space, d)
energy = ift.InverseGammaLikelihood(d)
ift.extra.check_value_gradient_consistency(energy, field, tol=1e-7)
def testPoissonian(field):
field = field.exp()
space = field.domain
d = np.random.poisson(120, size=space.shape)
d = ift.Field.from_global_data(space, d)
energy = ift.PoissonianEnergy(d)
ift.extra.check_value_gradient_consistency(energy, field, tol=1e-7)
def test_hamiltonian_and_KL(field):
field = field.exp()
space = field.domain
lh = ift.GaussianEnergy(domain=space)
hamiltonian = ift.Hamiltonian(lh)
ift.extra.check_value_gradient_consistency(hamiltonian, field)
S = ift.ScalingOperator(1., space)
samps = [S.draw_sample() for i in range(3)]
kl = ift.SampledKullbachLeiblerDivergence(hamiltonian, samps)
ift.extra.check_value_gradient_consistency(kl, field)
def test_bernoulli(field):
field = field.sigmoid()
space = field.domain
d = np.random.binomial(1, 0.1, size=space.shape)
d = ift.Field.from_global_data(space, d)
energy = ift.BernoulliEnergy(d)
ift.extra.check_value_gradient_consistency(energy, field, tol=1e-6)
This diff is collapsed.
...@@ -15,61 +15,67 @@ ...@@ -15,61 +15,67 @@
# #
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
import unittest import numpy as np
from itertools import product import pytest
from test.common import expand
import nifty5 as ift import nifty5 as ift
import numpy as np
def _flat_PS(k): def _flat_PS(k):
return np.ones_like(k) return np.ones_like(k)
class Energy_Tests(unittest.TestCase): pmp = pytest.mark.parametrize
@expand(product([ift.GLSpace(15),
ift.RGSpace(64, distances=.789),
ift.RGSpace([32, 32], distances=.789)],
["tanh", "exp", ""],
[1, 1e-2, 1e2],
[4, 78, 23]))
def testGaussianEnergy(self, space, nonlinearity, noise, seed):
np.random.seed(seed)
dim = len(space.shape)
hspace = space.get_default_codomain()
ht = ift.HarmonicTransformOperator(hspace, target=space)
binbounds = ift.PowerSpace.useful_binbounds(hspace, logarithmic=False)
pspace = ift.PowerSpace(hspace, binbounds=binbounds)
Dist = ift.PowerDistributor(target=hspace, power_space=pspace)
xi0 = ift.Field.from_random(domain=hspace, random_type='normal')
xi0_var = ift.Linearization.make_var(xi0)
def pspec(k): return 1 / (1 + k**2)**dim
pspec = ift.PS_field(pspace, pspec)
A = Dist(ift.sqrt(pspec))
N = ift.ScalingOperator(noise, space)
n = N.draw_sample()
s = ht(ift.makeOp(A)(xi0_var))
R = ift.ScalingOperator(10., space)
def d_model(): @pmp('space', [
if nonlinearity == "": ift.GLSpace(15),
return R(ht(ift.makeOp(A))) ift.RGSpace(64, distances=.789),
else: ift.RGSpace([32, 32], distances=.789)
tmp = ht(ift.makeOp(A)) ])
nonlin = getattr(tmp, nonlinearity)() @pmp('nonlinearity', ["tanh", "exp", ""])
return R(nonlin) @pmp('noise', [1, 1e-2, 1e2])
@pmp('seed', [4, 78, 23])
def test_gaussian_energy(space, nonlinearity, noise, seed):
np.random.seed(seed)
dim = len(space.shape)
hspace = space.get_default_codomain()
ht = ift.HarmonicTransformOperator(hspace, target=space)
binbounds = ift.PowerSpace.useful_binbounds(hspace, logarithmic=False)
pspace = ift.PowerSpace(hspace, binbounds=binbounds)
Dist = ift.PowerDistributor(target=hspace, power_space=pspace)
xi0 = ift.Field.from_random(domain=hspace, random_type='normal')
# FIXME Needed?
xi0_var = ift.Linearization.make_var(xi0)
d = d_model()(xi0) + n def pspec(k):
return 1/(1 + k**2)**dim
if noise == 1: pspec = ift.PS_field(pspace, pspec)
N = None A = Dist(ift.sqrt(pspec))
N = ift.ScalingOperator(noise, space)
n = N.draw_sample()
# FIXME Needed?
s = ht(ift.makeOp(A)(xi0_var))
R = ift.ScalingOperator(10., space)
energy = ift.GaussianEnergy(d, N)(d_model()) def d_model():
if nonlinearity == "": if nonlinearity == "":
ift.extra.check_value_gradient_metric_consistency( return R(ht(ift.makeOp(A)))
energy, xi0, ntries=10)
else: else:
ift.extra.check_value_gradient_consistency( tmp = ht(ift.makeOp(A))
energy, xi0, ntries=10, tol=5e-8) nonlin = getattr(tmp, nonlinearity)()
return R(nonlin)
d = d_model()(xi0) + n
if noise == 1:
N = None
energy = ift.GaussianEnergy(d, N)(d_model())
if nonlinearity == "":
ift.extra.check_value_gradient_metric_consistency(
energy, xi0, ntries=10)
else:
ift.extra.check_value_gradient_consistency(
energy, xi0, ntries=10, tol=5e-8)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright(C) 2013-2019 Max-Planck-Society
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
import unittest
from itertools import product
from test.common import expand
import nifty5 as ift
import numpy as np
from unittest import SkipTest
from numpy.testing import assert_allclose, assert_equal
IC = ift.GradientNormController(tol_abs_gradnorm=1e-5, iteration_limit=1000)
spaces = [ift.RGSpace([1024], distances=0.123), ift.HPSpace(32)]
minimizers = ['ift.VL_BFGS(IC)',
'ift.NonlinearCG(IC, "Polak-Ribiere")',
# 'ift.NonlinearCG(IC, "Hestenes-Stiefel"),
'ift.NonlinearCG(IC, "Fletcher-Reeves")',
'ift.NonlinearCG(IC, "5.49")',
'ift.L_BFGS_B(ftol=1e-10, gtol=1e-5, maxiter=1000)',
'ift.L_BFGS(IC)',
'ift.NewtonCG(IC)']
newton_minimizers = ['ift.RelaxedNewton(IC)']
quadratic_only_minimizers = ['ift.ConjugateGradient(IC)',
'ift.ScipyCG(tol=1e-5, maxiter=300)']
slow_minimizers = ['ift.SteepestDescent(IC)']
class Test_Minimizers(unittest.TestCase):
@expand(product(minimizers + newton_minimizers +
quadratic_only_minimizers + slow_minimizers, spaces))
def test_quadratic_minimization(self, minimizer, space):
np.random.seed(42)
starting_point = ift.Field.from_random('normal', domain=space)*10
covariance_diagonal = ift.Field.from_random(
'uniform', domain=space) + 0.5
covariance = ift.DiagonalOperator(covariance_diagonal)
required_result = ift.full(space, 1.)
try:
minimizer = eval(minimizer)
energy = ift.QuadraticEnergy(A=covariance, b=required_result,
position=starting_point)
(energy, convergence) = minimizer(energy)
except NotImplementedError:
raise SkipTest
assert_equal(convergence, IC.CONVERGED)
assert_allclose(energy.position.local_data,
1./covariance_diagonal.local_data,
rtol=1e-3, atol=1e-3)
@expand(product(minimizers+newton_minimizers))
def test_rosenbrock(self, minimizer):
try:
from scipy.optimize import rosen, rosen_der, rosen_hess_prod
except ImportError:
raise SkipTest
np.random.seed(42)
space = ift.DomainTuple.make(ift.UnstructuredDomain((2,)))
starting_point = ift.Field.from_random('normal', domain=space)*10
class RBEnergy(ift.Energy):
def __init__(self, position):
super(RBEnergy, self).__init__(position)
@property
def value(self):
return rosen(self._position.to_global_data_rw())
@property
def gradient(self):
inp = self._position.to_global_data_rw()
out = ift.Field.from_global_data(space, rosen_der(inp))
return out
@property
def metric(self):
class RBCurv(ift.EndomorphicOperator):
def __init__(self, loc):
self._loc = loc.to_global_data_rw()
self._capability = self.TIMES
self._domain = space
def apply(self, x, mode):
self._check_input(x, mode)
inp = x.to_global_data_rw()
out = ift.Field.from_global_data(
space, rosen_hess_prod(self._loc.copy(), inp))
return out
t1 = ift.GradientNormController(tol_abs_gradnorm=1e-5,
iteration_limit=1000)
return ift.InversionEnabler(RBCurv(self._position), t1)
def apply_metric(self, x):
inp = x.to_global_data_rw()
pos = self._position.to_global_data_rw()
return ift.Field.from_global_data(
space, rosen_hess_prod(pos, inp))
try:
minimizer = eval(minimizer)
energy = RBEnergy(position=starting_point)
(energy, convergence) = minimizer(energy)
except NotImplementedError:
raise SkipTest
assert_equal(convergence, IC.CONVERGED)
assert_allclose(energy.position.local_data, 1.,
rtol=1e-3, atol=1e-3)
@expand(product(minimizers+slow_minimizers))
def test_gauss(self, minimizer):
space = ift.UnstructuredDomain((1,))
starting_point = ift.Field.full(space, 3.)
class ExpEnergy(ift.Energy):
def __init__(self, position):
super(ExpEnergy, self).__init__(position)
@property
def value(self):
x = self.position.to_global_data()[0]
return -np.exp(-(x**2))
@property
def gradient(self):
x = self.position.to_global_data()[0]
return ift.Field.full(self.position.domain,
2*x*np.exp(-(x**2)))
def apply_metric(self, x):
p = self.position.to_global_data()[0]
v = (2 - 4*p*p)*np.exp(-p**2)
return ift.DiagonalOperator(
ift.Field.full(self.position.domain, v))(x)
try:
minimizer = eval(minimizer)
energy = ExpEnergy(position=starting_point)
(energy, convergence) = minimizer(energy)
except NotImplementedError:
raise SkipTest
assert_equal(convergence, IC.CONVERGED)
assert_allclose(energy.position.local_data, 0.,
atol=1e-3)
@expand(product(minimizers+newton_minimizers+slow_minimizers))
def test_cosh(self, minimizer):
space = ift.UnstructuredDomain((1,))
starting_point = ift.Field.full(space, 3.)
class CoshEnergy(ift.Energy):
def __init__(self, position):
super(CoshEnergy, self).__init__(position)
@property
def value(self):
x = self.position.to_global_data()[0]
return np.cosh(x)
@property
def gradient(self):
x = self.position.to_global_data()[0]
return ift.Field.full(self.position.domain, np.sinh(x))
@property
def metric(self):
x = self.position.to_global_data()[0]
v = np.cosh(x)
return ift.DiagonalOperator(
ift.Field.full(self.position.domain, v))
def apply_metric(self, x):
p = self.position.to_global_data()[0]
v = np.cosh(p)
return ift.DiagonalOperator(
ift.Field.full(self.position.domain, v))(x)
try:
minimizer = eval(minimizer)
energy = CoshEnergy(position=starting_point)
(energy, convergence) = minimizer(energy)
except NotImplementedError:
raise SkipTest
assert_equal(convergence, IC.CONVERGED)
assert_allclose(energy.position.local_data, 0., atol=1e-3)