From feb207b26c787010a5f2bc2458508555a7c973e4 Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Sun, 4 Feb 2018 08:58:31 +0100 Subject: [PATCH 01/12] Add adjointness and inverse test --- nifty4/operators/linear_operator.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/nifty4/operators/linear_operator.py b/nifty4/operators/linear_operator.py index e923aa54..58b52dc5 100644 --- a/nifty4/operators/linear_operator.py +++ b/nifty4/operators/linear_operator.py @@ -163,3 +163,25 @@ class LinearOperator(with_metaclass( if x.domain != self._dom(mode): raise ValueError("The operator's and and field's domains " "don't match.") + + def test_adjointness(self, domain_dtype=np.float64, target_dtype=np.float64): + f1 = Field.from_random("normal", domain=self.domain, + dtype=domain_dtype) + f2 = Field.from_random("normal", domain=self.target, + dtype=target_dtype) + res1 = f1.vdot(self.adjoint_times(f2)) + res2 = self.times(f1).vdot(f2) + return (res1 - res2) / (res1 + res2) * 2 + + def test_inverse(self, dtype_domain=np.float64, dtype_target=np.float64): + foo = Field.from_random( + domain=self.target, random_type='normal', dtype=dtype_target) + bar = self.times(self.inverse_times(foo)).val + np.testing.assert_allclose(bar, Field.ones(self.target).val) + + foo = Field.from_random( + domain=self.domain, random_type='normal', dtype=dtype_domain) + bar = self.inverse_times(self.times(foo)).val + np.testing.assert_allclose(bar, Field.ones(self.domain).val) + + return True -- GitLab From 02d4686cf1f73a518d3822a59f0221c60bf4717e Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Sun, 4 Feb 2018 09:35:31 +0100 Subject: [PATCH 02/12] Change inputs and outputs --- nifty4/operators/linear_operator.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/nifty4/operators/linear_operator.py b/nifty4/operators/linear_operator.py index 58b52dc5..dcf6bab4 100644 --- a/nifty4/operators/linear_operator.py +++ b/nifty4/operators/linear_operator.py @@ -164,16 +164,19 @@ class LinearOperator(with_metaclass( raise ValueError("The operator's and and field's domains " "don't match.") - def test_adjointness(self, domain_dtype=np.float64, target_dtype=np.float64): + def test_adjointness(self, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): f1 = Field.from_random("normal", domain=self.domain, dtype=domain_dtype) f2 = Field.from_random("normal", domain=self.target, dtype=target_dtype) res1 = f1.vdot(self.adjoint_times(f2)) res2 = self.times(f1).vdot(f2) + np.testing.assert_allclose(res1, res2, atol=atol, rtol=rtol) + + # Return relative error return (res1 - res2) / (res1 + res2) * 2 - def test_inverse(self, dtype_domain=np.float64, dtype_target=np.float64): + def test_inverse(self, dtype_domain=np.float64, dtype_target=np.float64, atol=0, rtol=1e-7): foo = Field.from_random( domain=self.target, random_type='normal', dtype=dtype_target) bar = self.times(self.inverse_times(foo)).val @@ -181,7 +184,11 @@ class LinearOperator(with_metaclass( foo = Field.from_random( domain=self.domain, random_type='normal', dtype=dtype_domain) - bar = self.inverse_times(self.times(foo)).val - np.testing.assert_allclose(bar, Field.ones(self.domain).val) - return True + res1 = self.inverse_times(self.times(foo)).val + res2 = Field.ones(self.domain).val + + np.testing.assert_allclose(res1, res2, atol=atol, rtol=rtol) + + # Return relative error + return (res1 - res2) / (res1 + res2) * 2 -- GitLab From b4bf88f6a7d7be7b4cc8a64454a913e634c0c602 Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Sun, 4 Feb 2018 09:41:34 +0100 Subject: [PATCH 03/12] Fixups --- nifty4/operators/linear_operator.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/nifty4/operators/linear_operator.py b/nifty4/operators/linear_operator.py index dcf6bab4..e961e347 100644 --- a/nifty4/operators/linear_operator.py +++ b/nifty4/operators/linear_operator.py @@ -179,16 +179,15 @@ class LinearOperator(with_metaclass( def test_inverse(self, dtype_domain=np.float64, dtype_target=np.float64, atol=0, rtol=1e-7): foo = Field.from_random( domain=self.target, random_type='normal', dtype=dtype_target) - bar = self.times(self.inverse_times(foo)).val - np.testing.assert_allclose(bar, Field.ones(self.target).val) + res = self.times(self.inverse_times(foo)).val + ones = Field.ones(self.domain).val + np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) foo = Field.from_random( domain=self.domain, random_type='normal', dtype=dtype_domain) - - res1 = self.inverse_times(self.times(foo)).val - res2 = Field.ones(self.domain).val - - np.testing.assert_allclose(res1, res2, atol=atol, rtol=rtol) + res = self.inverse_times(self.times(foo)).val + ones = Field.ones(self.target).val + np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) # Return relative error - return (res1 - res2) / (res1 + res2) * 2 + return (res - ones) / (res + ones) * 2 -- GitLab From 7eee74d8474be35232c5e44661c6e715b85df9d0 Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Sun, 4 Feb 2018 14:30:28 +0100 Subject: [PATCH 04/12] Move it --- nifty4/__init__.py | 1 + nifty4/extra/__init__.py | 1 + nifty4/extra/test_helpers.py | 31 +++++++++++++++++++++++++++++ nifty4/operators/linear_operator.py | 27 ------------------------- 4 files changed, 33 insertions(+), 27 deletions(-) create mode 100644 nifty4/extra/__init__.py create mode 100644 nifty4/extra/test_helpers.py diff --git a/nifty4/__init__.py b/nifty4/__init__.py index 65f44357..55f9a9f9 100644 --- a/nifty4/__init__.py +++ b/nifty4/__init__.py @@ -53,6 +53,7 @@ from .minimization.line_energy import LineEnergy from .sugar import * from .plotting.plot import plot from . import library +from . import extra __all__ = ["Domain", "UnstructuredDomain", "StructuredDomain", "RGSpace", "LMSpace", "HPSpace", "GLSpace", "DOFSpace", "PowerSpace", "DomainTuple", diff --git a/nifty4/extra/__init__.py b/nifty4/extra/__init__.py new file mode 100644 index 00000000..42aaabe3 --- /dev/null +++ b/nifty4/extra/__init__.py @@ -0,0 +1 @@ +from .test_helpers import test_adjointness, test_inverse diff --git a/nifty4/extra/test_helpers.py b/nifty4/extra/test_helpers.py new file mode 100644 index 00000000..e71a6ba0 --- /dev/null +++ b/nifty4/extra/test_helpers.py @@ -0,0 +1,31 @@ +import numpy as np + +from ..field import Field + +__all__ = ['test_adjointness', 'test_inverse'] + + +def test_adjointness(self, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): + f1 = Field.from_random("normal", domain=self.domain, dtype=domain_dtype) + f2 = Field.from_random("normal", domain=self.target, dtype=target_dtype) + res1 = f1.vdot(self.adjoint_times(f2)) + res2 = self.times(f1).vdot(f2) + np.testing.assert_allclose(res1, res2, atol=atol, rtol=rtol) + + # Return relative error + return (res1 - res2) / (res1 + res2) * 2 + + +def test_inverse(self, dtype_domain=np.float64, dtype_target=np.float64, atol=0, rtol=1e-7): + foo = Field.from_random(domain=self.target, random_type='normal', dtype=dtype_target) + res = self.times(self.inverse_times(foo)).val + ones = Field.ones(self.domain).val + np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) + + foo = Field.from_random(domain=self.domain, random_type='normal', dtype=dtype_domain) + res = self.inverse_times(self.times(foo)).val + ones = Field.ones(self.target).val + np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) + + # Return relative error + return (res - ones) / (res + ones) * 2 diff --git a/nifty4/operators/linear_operator.py b/nifty4/operators/linear_operator.py index e961e347..edbb3b3c 100644 --- a/nifty4/operators/linear_operator.py +++ b/nifty4/operators/linear_operator.py @@ -164,30 +164,3 @@ class LinearOperator(with_metaclass( raise ValueError("The operator's and and field's domains " "don't match.") - def test_adjointness(self, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): - f1 = Field.from_random("normal", domain=self.domain, - dtype=domain_dtype) - f2 = Field.from_random("normal", domain=self.target, - dtype=target_dtype) - res1 = f1.vdot(self.adjoint_times(f2)) - res2 = self.times(f1).vdot(f2) - np.testing.assert_allclose(res1, res2, atol=atol, rtol=rtol) - - # Return relative error - return (res1 - res2) / (res1 + res2) * 2 - - def test_inverse(self, dtype_domain=np.float64, dtype_target=np.float64, atol=0, rtol=1e-7): - foo = Field.from_random( - domain=self.target, random_type='normal', dtype=dtype_target) - res = self.times(self.inverse_times(foo)).val - ones = Field.ones(self.domain).val - np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) - - foo = Field.from_random( - domain=self.domain, random_type='normal', dtype=dtype_domain) - res = self.inverse_times(self.times(foo)).val - ones = Field.ones(self.target).val - np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) - - # Return relative error - return (res - ones) / (res + ones) * 2 -- GitLab From 36f5e23e83e587881d0982243ac072dc6cfa73af Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Sun, 4 Feb 2018 14:33:27 +0100 Subject: [PATCH 05/12] Do not interfere with nosetests --- nifty4/extra/__init__.py | 2 +- nifty4/extra/{test_helpers.py => operator_tests.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename nifty4/extra/{test_helpers.py => operator_tests.py} (100%) diff --git a/nifty4/extra/__init__.py b/nifty4/extra/__init__.py index 42aaabe3..c6281d00 100644 --- a/nifty4/extra/__init__.py +++ b/nifty4/extra/__init__.py @@ -1 +1 @@ -from .test_helpers import test_adjointness, test_inverse +from .operator_tests import test_adjointness, test_inverse diff --git a/nifty4/extra/test_helpers.py b/nifty4/extra/operator_tests.py similarity index 100% rename from nifty4/extra/test_helpers.py rename to nifty4/extra/operator_tests.py -- GitLab From 652b282d0fc902f218293889ca8e53299c0638ce Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Sun, 4 Feb 2018 14:36:44 +0100 Subject: [PATCH 06/12] Fixups --- nifty4/extra/operator_tests.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/nifty4/extra/operator_tests.py b/nifty4/extra/operator_tests.py index e71a6ba0..43725987 100644 --- a/nifty4/extra/operator_tests.py +++ b/nifty4/extra/operator_tests.py @@ -5,26 +5,26 @@ from ..field import Field __all__ = ['test_adjointness', 'test_inverse'] -def test_adjointness(self, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): - f1 = Field.from_random("normal", domain=self.domain, dtype=domain_dtype) - f2 = Field.from_random("normal", domain=self.target, dtype=target_dtype) - res1 = f1.vdot(self.adjoint_times(f2)) - res2 = self.times(f1).vdot(f2) +def test_adjointness(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): + f1 = Field.from_random("normal", domain=op.domain, dtype=domain_dtype) + f2 = Field.from_random("normal", domain=op.target, dtype=target_dtype) + res1 = f1.vdot(op.adjoint_times(f2)) + res2 = op.times(f1).vdot(f2) np.testing.assert_allclose(res1, res2, atol=atol, rtol=rtol) # Return relative error return (res1 - res2) / (res1 + res2) * 2 -def test_inverse(self, dtype_domain=np.float64, dtype_target=np.float64, atol=0, rtol=1e-7): - foo = Field.from_random(domain=self.target, random_type='normal', dtype=dtype_target) - res = self.times(self.inverse_times(foo)).val - ones = Field.ones(self.domain).val +def test_inverse(op, dtype_domain=np.float64, dtype_target=np.float64, atol=0, rtol=1e-7): + foo = Field.from_random(domain=op.target, random_type='normal', dtype=dtype_target) + res = op(op.inverse_times(foo)).val + ones = Field.ones(op.domain).val np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) - foo = Field.from_random(domain=self.domain, random_type='normal', dtype=dtype_domain) - res = self.inverse_times(self.times(foo)).val - ones = Field.ones(self.target).val + foo = Field.from_random(domain=op.domain, random_type='normal', dtype=dtype_domain) + res = op.inverse_times(op(foo)).val + ones = Field.ones(op.target).val np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) # Return relative error -- GitLab From 9eaf66d302ac62fa90733d11ebafec7f80852979 Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Sun, 4 Feb 2018 14:41:11 +0100 Subject: [PATCH 07/12] More name changes --- nifty4/extra/__init__.py | 2 +- nifty4/extra/operator_tests.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nifty4/extra/__init__.py b/nifty4/extra/__init__.py index c6281d00..71ef296b 100644 --- a/nifty4/extra/__init__.py +++ b/nifty4/extra/__init__.py @@ -1 +1 @@ -from .operator_tests import test_adjointness, test_inverse +from .operator_tests import adjointness_implementation, inverse_implementation diff --git a/nifty4/extra/operator_tests.py b/nifty4/extra/operator_tests.py index 43725987..bcf6a902 100644 --- a/nifty4/extra/operator_tests.py +++ b/nifty4/extra/operator_tests.py @@ -2,10 +2,10 @@ import numpy as np from ..field import Field -__all__ = ['test_adjointness', 'test_inverse'] +__all__ = ['adjointness_implementation', 'inverse_implemenation'] -def test_adjointness(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): +def adjointness_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): f1 = Field.from_random("normal", domain=op.domain, dtype=domain_dtype) f2 = Field.from_random("normal", domain=op.target, dtype=target_dtype) res1 = f1.vdot(op.adjoint_times(f2)) @@ -16,7 +16,7 @@ def test_adjointness(op, domain_dtype=np.float64, target_dtype=np.float64, atol= return (res1 - res2) / (res1 + res2) * 2 -def test_inverse(op, dtype_domain=np.float64, dtype_target=np.float64, atol=0, rtol=1e-7): +def inverse_implementation(op, dtype_domain=np.float64, dtype_target=np.float64, atol=0, rtol=1e-7): foo = Field.from_random(domain=op.target, random_type='normal', dtype=dtype_target) res = op(op.inverse_times(foo)).val ones = Field.ones(op.domain).val -- GitLab From aaa7ad45f65df4a0a1f607eccd9f10aab7b22af7 Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Sun, 4 Feb 2018 14:46:34 +0100 Subject: [PATCH 08/12] One more name changing --- nifty4/extra/__init__.py | 2 +- nifty4/extra/operator_tests.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nifty4/extra/__init__.py b/nifty4/extra/__init__.py index 71ef296b..47c53152 100644 --- a/nifty4/extra/__init__.py +++ b/nifty4/extra/__init__.py @@ -1 +1 @@ -from .operator_tests import adjointness_implementation, inverse_implementation +from .operator_tests import adjoint_implementation, inverse_implementation diff --git a/nifty4/extra/operator_tests.py b/nifty4/extra/operator_tests.py index bcf6a902..7bc653b6 100644 --- a/nifty4/extra/operator_tests.py +++ b/nifty4/extra/operator_tests.py @@ -2,10 +2,10 @@ import numpy as np from ..field import Field -__all__ = ['adjointness_implementation', 'inverse_implemenation'] +__all__ = ['adjoint_implementation', 'inverse_implemenation'] -def adjointness_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): +def adjoint_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): f1 = Field.from_random("normal", domain=op.domain, dtype=domain_dtype) f2 = Field.from_random("normal", domain=op.target, dtype=target_dtype) res1 = f1.vdot(op.adjoint_times(f2)) -- GitLab From 12ddc569ed9297f2ee8d2c21378026236b58001a Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Sun, 4 Feb 2018 15:09:18 +0100 Subject: [PATCH 09/12] More name changes --- nifty4/extra/operator_tests.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/nifty4/extra/operator_tests.py b/nifty4/extra/operator_tests.py index 7bc653b6..6a445423 100644 --- a/nifty4/extra/operator_tests.py +++ b/nifty4/extra/operator_tests.py @@ -16,16 +16,14 @@ def adjoint_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, return (res1 - res2) / (res1 + res2) * 2 -def inverse_implementation(op, dtype_domain=np.float64, dtype_target=np.float64, atol=0, rtol=1e-7): - foo = Field.from_random(domain=op.target, random_type='normal', dtype=dtype_target) +def inverse_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): + foo = Field.from_random(domain=op.target, random_type='normal', dtype=target_dtype) res = op(op.inverse_times(foo)).val - ones = Field.ones(op.domain).val - np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) + np.testing.assert_allclose(res, foo.val, atol=atol, rtol=rtol) - foo = Field.from_random(domain=op.domain, random_type='normal', dtype=dtype_domain) + foo = Field.from_random(domain=op.domain, random_type='normal', dtype=domain_dtype) res = op.inverse_times(op(foo)).val - ones = Field.ones(op.target).val - np.testing.assert_allclose(res, ones, atol=atol, rtol=rtol) + np.testing.assert_allclose(res, foo.val, atol=atol, rtol=rtol) # Return relative error - return (res - ones) / (res + ones) * 2 + return (res - foo.val) / (res + foo.val) * 2 -- GitLab From c772ce4bf5a34ee5181681fbaa6acd96750df03d Mon Sep 17 00:00:00 2001 From: Philipp Arras Date: Mon, 5 Feb 2018 11:21:17 +0100 Subject: [PATCH 10/12] Add test for full implementation --- nifty4/extra/__init__.py | 2 +- nifty4/extra/operator_tests.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/nifty4/extra/__init__.py b/nifty4/extra/__init__.py index 47c53152..90d0b7f2 100644 --- a/nifty4/extra/__init__.py +++ b/nifty4/extra/__init__.py @@ -1 +1 @@ -from .operator_tests import adjoint_implementation, inverse_implementation +from .operator_tests import adjoint_implementation, inverse_implementation, full_implementation diff --git a/nifty4/extra/operator_tests.py b/nifty4/extra/operator_tests.py index 6a445423..d3490a07 100644 --- a/nifty4/extra/operator_tests.py +++ b/nifty4/extra/operator_tests.py @@ -2,7 +2,7 @@ import numpy as np from ..field import Field -__all__ = ['adjoint_implementation', 'inverse_implemenation'] +__all__ = ['adjoint_implementation', 'inverse_implemenation', 'full_implementation'] def adjoint_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): @@ -27,3 +27,11 @@ def inverse_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, # Return relative error return (res - foo.val) / (res + foo.val) * 2 + + +def full_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): + res1 = inverse_implementation(op, domain_dtype, target_dtype, atol, rtol) + res2 = adjoint_implementation(op, domain_dtype, target_dtype, atol, rtol) + res3 = adjoint_implementation(op.inverse, target_dtype, domain_dtype, atol, rtol) + + return res1, res2, res3 -- GitLab From 9b1b7166849704f1be4207ed4213ca167791c75e Mon Sep 17 00:00:00 2001 From: Martin Reinecke Date: Mon, 5 Feb 2018 11:29:02 +0100 Subject: [PATCH 11/12] fix typo --- nifty4/operators/linear_operator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nifty4/operators/linear_operator.py b/nifty4/operators/linear_operator.py index e923aa54..ec692d24 100644 --- a/nifty4/operators/linear_operator.py +++ b/nifty4/operators/linear_operator.py @@ -161,5 +161,4 @@ class LinearOperator(with_metaclass( self._check_mode(mode) if x.domain != self._dom(mode): - raise ValueError("The operator's and and field's domains " - "don't match.") + raise ValueError("The operator's and field's domains don't match.") -- GitLab From 22e1116eb60d504c116bda63a6d623dafd2f7569 Mon Sep 17 00:00:00 2001 From: Martin Reinecke Date: Mon, 5 Feb 2018 12:16:59 +0100 Subject: [PATCH 12/12] use new functionality in tests --- nifty4/extra/__init__.py | 2 +- nifty4/extra/operator_tests.py | 72 ++++++++++++++++++++--------- test/test_energies/test_map.py | 2 - test/test_operators/test_adjoint.py | 39 ++++++---------- 4 files changed, 65 insertions(+), 50 deletions(-) diff --git a/nifty4/extra/__init__.py b/nifty4/extra/__init__.py index 90d0b7f2..d0214b80 100644 --- a/nifty4/extra/__init__.py +++ b/nifty4/extra/__init__.py @@ -1 +1 @@ -from .operator_tests import adjoint_implementation, inverse_implementation, full_implementation +from .operator_tests import consistency_check diff --git a/nifty4/extra/operator_tests.py b/nifty4/extra/operator_tests.py index d3490a07..48ee48d6 100644 --- a/nifty4/extra/operator_tests.py +++ b/nifty4/extra/operator_tests.py @@ -1,37 +1,65 @@ -import numpy as np +# 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 . +# +# Copyright(C) 2013-2018 Max-Planck-Society +# +# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik +# and financially supported by the Studienstiftung des deutschen Volkes. +import numpy as np from ..field import Field +from .. import dobj -__all__ = ['adjoint_implementation', 'inverse_implemenation', 'full_implementation'] +__all__ = ["consistency_check"] -def adjoint_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): - f1 = Field.from_random("normal", domain=op.domain, dtype=domain_dtype) - f2 = Field.from_random("normal", domain=op.target, dtype=target_dtype) +def adjoint_implementation(op, domain_dtype, target_dtype, atol, rtol): + needed_cap = op.TIMES | op.ADJOINT_TIMES + if (op.capability & needed_cap) != needed_cap: + return + f1 = Field.from_random("normal", op.domain, dtype=domain_dtype) + f2 = Field.from_random("normal", op.target, dtype=target_dtype) res1 = f1.vdot(op.adjoint_times(f2)) res2 = op.times(f1).vdot(f2) np.testing.assert_allclose(res1, res2, atol=atol, rtol=rtol) - # Return relative error - return (res1 - res2) / (res1 + res2) * 2 - -def inverse_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): - foo = Field.from_random(domain=op.target, random_type='normal', dtype=target_dtype) - res = op(op.inverse_times(foo)).val - np.testing.assert_allclose(res, foo.val, atol=atol, rtol=rtol) +def inverse_implementation(op, domain_dtype, target_dtype, atol, rtol): + needed_cap = op.TIMES | op.INVERSE_TIMES + if (op.capability & needed_cap) != needed_cap: + return + foo = Field.from_random("normal", op.target, dtype=target_dtype) + res = op(op.inverse_times(foo)) + np.testing.assert_allclose(dobj.to_global_data(res.val), + dobj.to_global_data(foo.val), + atol=atol, rtol=rtol) - foo = Field.from_random(domain=op.domain, random_type='normal', dtype=domain_dtype) - res = op.inverse_times(op(foo)).val - np.testing.assert_allclose(res, foo.val, atol=atol, rtol=rtol) + foo = Field.from_random("normal", op.domain, dtype=domain_dtype) + res = op.inverse_times(op(foo)) + np.testing.assert_allclose(dobj.to_global_data(res.val), + dobj.to_global_data(foo.val), + atol=atol, rtol=rtol) - # Return relative error - return (res - foo.val) / (res + foo.val) * 2 +def full_implementation(op, domain_dtype, target_dtype, atol, rtol): + adjoint_implementation(op, domain_dtype, target_dtype, atol, rtol) + inverse_implementation(op, domain_dtype, target_dtype, atol, rtol) -def full_implementation(op, domain_dtype=np.float64, target_dtype=np.float64, atol=0, rtol=1e-7): - res1 = inverse_implementation(op, domain_dtype, target_dtype, atol, rtol) - res2 = adjoint_implementation(op, domain_dtype, target_dtype, atol, rtol) - res3 = adjoint_implementation(op.inverse, target_dtype, domain_dtype, atol, rtol) - return res1, res2, res3 +def consistency_check(op, domain_dtype=np.float64, target_dtype=np.float64, + atol=0, rtol=1e-7): + full_implementation(op, domain_dtype, target_dtype, atol, rtol) + full_implementation(op.adjoint, target_dtype, domain_dtype, atol, rtol) + full_implementation(op.inverse, target_dtype, domain_dtype, atol, rtol) + full_implementation(op.adjoint.inverse, domain_dtype, target_dtype, atol, + rtol) diff --git a/test/test_energies/test_map.py b/test/test_energies/test_map.py index bac03da2..bbce2de8 100644 --- a/test/test_energies/test_map.py +++ b/test/test_energies/test_map.py @@ -259,8 +259,6 @@ class Curvature_Tests(unittest.TestCase): a = (gradient1 - gradient0) / eps b = energy0.curvature(direction) - print(a.vdot(a)) - print(b.vdot(b)) tol = 1e-7 assert_allclose(ift.dobj.to_global_data(a.val), ift.dobj.to_global_data(b.val), rtol=tol, atol=tol) diff --git a/test/test_operators/test_adjoint.py b/test/test_operators/test_adjoint.py index 9472dbce..0579f857 100644 --- a/test/test_operators/test_adjoint.py +++ b/test/test_operators/test_adjoint.py @@ -11,7 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -# Copyright(C) 2013-2017 Max-Planck-Society +# Copyright(C) 2013-2018 Max-Planck-Society # # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik # and financially supported by the Studienstiftung des deutschen Volkes. @@ -21,23 +21,6 @@ import nifty4 as ift import numpy as np from itertools import product from test.common import expand -from numpy.testing import assert_allclose - - -def _check_adjointness(op, dtype=np.float64): - f1 = ift.Field.from_random("normal", domain=op.domain, dtype=dtype) - f2 = ift.Field.from_random("normal", domain=op.target, dtype=dtype) - cap = op.capability - if ((cap & ift.LinearOperator.TIMES) and - (cap & ift.LinearOperator.ADJOINT_TIMES)): - assert_allclose(f1.vdot(op.adjoint_times(f2)), - op.times(f1).vdot(f2), - rtol=1e-8) - if ((cap & ift.LinearOperator.INVERSE_TIMES) and - (cap & ift.LinearOperator.INVERSE_ADJOINT_TIMES)): - assert_allclose(f1.vdot(op.inverse_times(f2)), - op.inverse_adjoint_times(f1).vdot(f2), - rtol=1e-8) _h_RG_spaces = [ift.RGSpace(7, distances=0.2, harmonic=True), @@ -49,29 +32,35 @@ _p_RG_spaces = [ift.RGSpace(19, distances=0.7), _p_spaces = _p_RG_spaces + [ift.HPSpace(17), ift.GLSpace(8, 13)] -class Adjointness_Tests(unittest.TestCase): +class Consistency_Tests(unittest.TestCase): @expand(product(_h_spaces, [np.float64, np.complex128])) def testPPO(self, sp, dtype): op = ift.PowerProjectionOperator(sp) - _check_adjointness(op, dtype) + ift.extra.consistency_check(op, dtype, dtype) ps = ift.PowerSpace( sp, ift.PowerSpace.useful_binbounds(sp, logarithmic=False, nbin=3)) op = ift.PowerProjectionOperator(sp, ps) - _check_adjointness(op, dtype) + ift.extra.consistency_check(op, dtype, dtype) ps = ift.PowerSpace( sp, ift.PowerSpace.useful_binbounds(sp, logarithmic=True, nbin=3)) op = ift.PowerProjectionOperator(sp, ps) - _check_adjointness(op, dtype) + ift.extra.consistency_check(op, dtype, dtype) @expand(product(_h_RG_spaces+_p_RG_spaces, [np.float64, np.complex128])) def testFFT(self, sp, dtype): op = ift.FFTOperator(sp) - _check_adjointness(op, dtype) + ift.extra.consistency_check(op, dtype, dtype) op = ift.FFTOperator(sp.get_default_codomain()) - _check_adjointness(op, dtype) + ift.extra.consistency_check(op, dtype, dtype) @expand(product(_h_spaces, [np.float64, np.complex128])) def testHarmonic(self, sp, dtype): op = ift.HarmonicTransformOperator(sp) - _check_adjointness(op, dtype) + ift.extra.consistency_check(op, dtype, dtype) + + @expand(product(_h_spaces+_p_spaces, [np.float64, np.complex128])) + def testDiagonal(self, sp, dtype): + op = ift.DiagonalOperator(ift.Field.from_random("normal", sp, + dtype=dtype)) + ift.extra.consistency_check(op, dtype, dtype) -- GitLab