diff --git a/demos/wiener_filter_hamiltonian.py b/demos/wiener_filter_hamiltonian.py index 118bc6e693812f1490483b78eac03775aa7f52e7..80d2721caa75781e3147d3b89694f850ca4fdf1d 100644 --- a/demos/wiener_filter_hamiltonian.py +++ b/demos/wiener_filter_hamiltonian.py @@ -78,17 +78,17 @@ if __name__ == "__main__": D = PropagatorOperator(S=S, N=N, R=R) def distance_measure(energy, iteration): - pass - #print (iteration, ((x-ss).norm()/ss.norm()).real) + x = energy.position + print (iteration, ((x-ss).norm()/ss.norm()).real) minimizer = SteepestDescent(convergence_tolerance=0, iteration_limit=50, callback=distance_measure) -# minimizer = VL_BFGS(convergence_tolerance=0, -# iteration_limit=50, -# callback=distance_measure, -# max_history_length=5) + minimizer = VL_BFGS(convergence_tolerance=0, + iteration_limit=50, + callback=distance_measure, + max_history_length=5) m0 = Field(s_space, val=1) diff --git a/nifty/energies/line_energy.py b/nifty/energies/line_energy.py index 6268553e98fe321904f16fa790ed5cac879a7e7e..2e82c89b1a29826552a07c82a6d4f8bb16c32615 100644 --- a/nifty/energies/line_energy.py +++ b/nifty/energies/line_energy.py @@ -4,19 +4,22 @@ from .energy import Energy class LineEnergy(Energy): - def __init__(self, position, energy, line_direction): - self.energy = energy - self.line_direction = line_direction + def __init__(self, position, energy, line_direction, zero_point=None): super(LineEnergy, self).__init__(position=position) + self.line_direction = line_direction + + if zero_point is None: + zero_point = energy.position + self._zero_point = zero_point + + position_on_line = self._zero_point + self.position*line_direction + self.energy = energy.at(position=position_on_line) def at(self, position): - if position == 0: - return self - else: - full_position = self.position + self.line_direction*position - return self.__class__(full_position, - self.energy, - self.line_direction) + return self.__class__(position, + self.energy, + self.line_direction, + zero_point=self._zero_point) @property def value(self): diff --git a/nifty/minimization/line_searching/line_search.py b/nifty/minimization/line_searching/line_search.py index b9d68a6754b278f30fca794784ddcbc325d00ec8..f65b3ea6b0eeb94d591788f7667eefbb3549b5d4 100644 --- a/nifty/minimization/line_searching/line_search.py +++ b/nifty/minimization/line_searching/line_search.py @@ -59,6 +59,5 @@ class LineSearch(object, Loggable): self.f_k_minus_1 = f_k_minus_1 @abc.abstractmethod - def perform_line_search(self, xk, pk, f_k=None, fprime_k=None, - f_k_minus_1=None): + def perform_line_search(self, energy, pk, f_k_minus_1=None): raise NotImplementedError diff --git a/nifty/minimization/line_searching/line_search_strong_wolfe.py b/nifty/minimization/line_searching/line_search_strong_wolfe.py index ac08d3d18927ec77f0e23caa0a4a1f8a9badaae8..38d268611430c3823eaab81dc402e774501eda63 100644 --- a/nifty/minimization/line_searching/line_search_strong_wolfe.py +++ b/nifty/minimization/line_searching/line_search_strong_wolfe.py @@ -54,8 +54,9 @@ class LineSearchStrongWolfe(LineSearch): # initialize the zero phis old_phi_0 = self.f_k_minus_1 - phi_0 = self.line_energy.at(0).value - phiprime_0 = self.line_energy.at(0).gradient + energy_0 = self.line_energy.at(0) + phi_0 = energy_0.value + phiprime_0 = energy_0.gradient if phiprime_0 == 0: self.logger.warn("Flat gradient in search direction.") @@ -82,11 +83,13 @@ class LineSearchStrongWolfe(LineSearch): self.logger.warn("Increment size became 0.") alpha_star = 0. phi_star = phi_0 + energy_star = energy_0 break if (phi_alpha1 > phi_0 + c1*alpha1*phiprime_0) or \ ((phi_alpha1 >= phi_alpha0) and (i > 1)): - (alpha_star, phi_star) = self._zoom(alpha0, alpha1, + (alpha_star, phi_star, energy_star) = self._zoom( + alpha0, alpha1, phi_0, phiprime_0, phi_alpha0, phiprime_alpha0, @@ -98,10 +101,12 @@ class LineSearchStrongWolfe(LineSearch): if abs(phiprime_alpha1) <= -c2*phiprime_0: alpha_star = alpha1 phi_star = phi_alpha1 + energy_star = energy_alpha1 break if phiprime_alpha1 >= 0: - (alpha_star, phi_star) = self._zoom(alpha1, alpha0, + (alpha_star, phi_star, energy_star) = self._zoom( + alpha1, alpha0, phi_0, phiprime_0, phi_alpha1, phiprime_alpha1, @@ -119,10 +124,15 @@ class LineSearchStrongWolfe(LineSearch): # max_iterations was reached alpha_star = alpha1 phi_star = phi_alpha1 + energy_star = energy_alpha1 self.logger.error("The line search algorithm did not converge.") self._last_alpha_star = alpha_star - return alpha_star, phi_star + + # extract the full energy from the line_energy + energy_star = energy_star.energy + + return alpha_star, phi_star, energy_star def _zoom(self, alpha_lo, alpha_hi, phi_0, phiprime_0, phi_lo, phiprime_lo, phi_hi, c1, c2): @@ -176,6 +186,7 @@ class LineSearchStrongWolfe(LineSearch): if abs(phiprime_alphaj) <= -c2*phiprime_0: alpha_star = alpha_j phi_star = phi_alphaj + energy_star = energy_alphaj break # If not, check the sign of the slope if phiprime_alphaj*delta_alpha >= 0: @@ -188,11 +199,12 @@ class LineSearchStrongWolfe(LineSearch): phiprime_alphaj) else: - alpha_star, phi_star = alpha_j, phi_alphaj + alpha_star, phi_star, energy_star = \ + alpha_j, phi_alphaj, energy_alphaj self.logger.error("The line search algorithm (zoom) did not " "converge.") - return alpha_star, phi_star + return alpha_star, phi_star, energy_star def _cubicmin(self, a, fa, fpa, b, fb, c, fc): """ diff --git a/nifty/minimization/quasi_newton_minimizer.py b/nifty/minimization/quasi_newton_minimizer.py index 284a8f135e65a7fa7d44c73d641f767a620b6638..c990da90503f5a5c9688af32cf87af115a4838ae 100644 --- a/nifty/minimization/quasi_newton_minimizer.py +++ b/nifty/minimization/quasi_newton_minimizer.py @@ -86,13 +86,11 @@ class QuasiNewtonMinimizer(object, Loggable): # compute the step length, which minimizes energy.value along the # search direction - step_length, step_length = self.line_searcher.perform_line_search( + step_length, f_k, new_energy = \ + self.line_searcher.perform_line_search( energy=energy, pk=descend_direction, f_k_minus_1=f_k_minus_1) - new_position = current_position + step_length * descend_direction - new_energy = energy.at(new_position) - f_k_minus_1 = energy.value energy = new_energy diff --git a/nifty/minimization/vl_bfgs.py b/nifty/minimization/vl_bfgs.py index 6310b61bbca0c44c91fd932d14a9c9072c0a81e2..1b5e139d7c96243a39d6a675188718b15ac398b3 100644 --- a/nifty/minimization/vl_bfgs.py +++ b/nifty/minimization/vl_bfgs.py @@ -20,9 +20,9 @@ class VL_BFGS(QuasiNewtonMinimizer): self.max_history_length = max_history_length - def __call__(self, x0, f, fprime, f_args=()): + def __call__(self, energy): self._information_store = None - return super(VL_BFGS, self).__call__(x0, f, fprime, f_args=()) + return super(VL_BFGS, self).__call__(energy) def _get_descend_direction(self, x, gradient): # initialize the information store if it doesn't already exist