Source code for nifty8.library.adjust_variances

# 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-2021 Max-Planck-Society
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.

from ..minimization.energy_adapter import EnergyAdapter
from ..multi_field import MultiField
from ..operators.energy_operators import (InverseGammaEnergy,
                                          StandardHamiltonian)
from ..operators.scaling_operator import ScalingOperator
from ..operators.simple_linear_operators import ducktape


[docs] def make_adjust_variances_hamiltonian(a, xi, position, samples=[], scaling=None, ic_samp=None): """Creates a Hamiltonian for constant likelihood optimizations. Constructs a Hamiltonian to solve constant likelihood optimizations of the form phi = a * xi under the constraint that phi remains constant. xi is desired to be a Gaussian white Field, thus variations that are more easily represented by a should be absorbed in a. Parameters ---------- a : Operator Gives the amplitude when evaluated at position. xi : Operator Field Adapter selecting a part of position. xi is desired to be a Gaussian white Field. position : :class:`nifty8.field.Field`, :class:`nifty8.multi_field.MultiField` Contains the initial values for the operators a and xi, to be adjusted samples : :class:`nifty8.field.Field`, :class:`nifty8.multi_field.MultiField` Residual samples of position. scaling : Float Optional rescaling of the Likelihood. ic_samp : Controller Iteration Controller for Hamiltonian. Returns ------- :class:`nifty8.operators.energy_operators.StandardHamiltonian` A Hamiltonian that can be used for further minimization. """ d = a*xi d = (d.conjugate()*d).real n = len(samples) if n > 0: d_eval = 0. for i in range(n): d_eval = d_eval + d.force(position + samples[i]) d_eval = d_eval/n else: d_eval = d.force(position) x = (a.conjugate()*a).real if scaling is not None: x = ScalingOperator(x.target, scaling)(x) return StandardHamiltonian(InverseGammaEnergy(d_eval/2.)(x), ic_samp=ic_samp)
[docs] def do_adjust_variances(position, A, minimizer, xi_key='xi', samples=[]): """Adjusts the variance of xi_key to be represented by amplitude_operator. Solves a constant likelihood optimization of the form phi = A * position[xi_key] under the constraint that phi remains constant. The field indexed by xi_key is desired to be a Gaussian white Field, thus variations that are more easily represented by A will be absorbed in A. Parameters ---------- position : :class:`nifty8.field.Field`, :class:`nifty8.multi_field.MultiField` Contains the initial values for amplitude_operator and the key xi_key, to be adjusted. A : Operator Gives the amplitude when evaluated at position. minimizer : Minimizer Used to solve the optimization problem. xi_key : String Key of the Field containing undesired variations. This Field is contained in position. samples : :class:`nifty8.field.Field`, :class:`nifty8.multi_field.MultiField`, optional Residual samples of position. If samples are supplied then phi remains only approximately constant. Default: []. Returns ------- MultiField The new position after variances have been adjusted. """ xi = ducktape(None, position.domain, xi_key) ham = make_adjust_variances_hamiltonian(A, xi, position, samples=samples) # Minimize e = EnergyAdapter( position.extract(A.domain), ham, constants=[], want_metric=True) e, _ = minimizer(e) # Update position s_h_old = (A*xi).force(position) position = position.to_dict() position[xi_key] = s_h_old/A(e.position) position = MultiField.from_dict(position) return MultiField.union([position, e.position])