<commit_before># -*- coding: utf-8 -*-

import itertools

import scipy
import numpy as np
import scipy.linalg
import scipy.optimize

from base import Minimizer
from linesearch import WolfeLineSearch


class Bfgs(Minimizer):

    def __init__(self, wrt, f, fprime, initial_inv_hessian=None,
                 line_search=None, args=None, logfunc=None):
        super(Bfgs, self).__init__(wrt, args=args, logfunc=logfunc)
        self.f = f
        self.fprime = fprime
        if initial_inv_hessian is not None:
            self.inv_hessian = initial_inv_hessian
        else:
            self.inv_hessian = np.eye(wrt.size)

        if line_search is not None:
            self.line_search = line_search
        else:
            self.line_search = WolfeLineSearch(wrt, self.f, self.fprime)

    def __iter__(self):
        args, kwargs = self.args.next()
        grad = self.fprime(self.wrt, *args, **kwargs)
        grad_m1 = scipy.zeros(grad.shape)

        # TODO: Following lines should be cleaned up.
        if self.inv_hessian is None:
            self.inv_hessian = scipy.eye(grad.shape[0])

        for i, (next_args, next_kwargs) in enumerate(self.args):
            # If the gradient is exactly zero, we stop. Otherwise, the
            # updates will lead to NaN errors because the direction will
            # be zero.
            if (grad == 0.0).all():
                self.logfunc({'message': 'gradient is 0'})
                break

            if i == 0:
                direction = -grad
            else:
                H = self.inv_hessian
                grad_diff = grad - grad_m1
                ys = np.inner(grad_diff, step)
                ss = np.inner(step, step)
                yy = np.inner(grad_diff, grad_diff)
                Hy = np.dot(H, grad_diff)
                yHy = np.inner(grad_diff, Hy)
                H += (ys + yHy)*np.outer(step, step)/ys**2 - (np.outer(Hy, step) + np.outer(step, Hy))/ys
                direction = -np.dot(H, grad)

            steplength = self.line_search.search(direction, None, args, kwargs)
            if steplength == 0:
                self.logfunc({'message': 'converged - steplength is 0'})
                break
            step = steplength * direction
            self.wrt += step

            # Prepare everything for the next loop.
            args, kwargs = next_args, next_kwargs
            # TODO: not all line searches have .grad!
            grad_m1[:], grad[:] = grad, self.line_search.grad

            yield {
                'steplength': steplength,
                'n_iter': i,
                'args': args,
                'kwargs': kwargs,
            }

<commit_msg>removed stopping criterion for bfgs<commit_after># -*- coding: utf-8 -*-

import itertools

import scipy
import numpy as np
import scipy.linalg
import scipy.optimize

from base import Minimizer
from linesearch import WolfeLineSearch


class Bfgs(Minimizer):

    def __init__(self, wrt, f, fprime, initial_inv_hessian=None,
                 line_search=None, args=None, logfunc=None):
        super(Bfgs, self).__init__(wrt, args=args, logfunc=logfunc)
        self.f = f
        self.fprime = fprime
        if initial_inv_hessian is not None:
            self.inv_hessian = initial_inv_hessian
        else:
            self.inv_hessian = np.eye(wrt.size)

        if line_search is not None:
            self.line_search = line_search
        else:
            self.line_search = WolfeLineSearch(wrt, self.f, self.fprime)

    def __iter__(self):
        args, kwargs = self.args.next()
        grad = self.fprime(self.wrt, *args, **kwargs)
        grad_m1 = scipy.zeros(grad.shape)

        # TODO: Following lines should be cleaned up.
        if self.inv_hessian is None:
            self.inv_hessian = scipy.eye(grad.shape[0])

        for i, (next_args, next_kwargs) in enumerate(self.args):
            if i == 0:
                direction = -grad
            else:
                H = self.inv_hessian
                grad_diff = grad - grad_m1
                ys = np.inner(grad_diff, step)
                ss = np.inner(step, step)
                yy = np.inner(grad_diff, grad_diff)
                Hy = np.dot(H, grad_diff)
                yHy = np.inner(grad_diff, Hy)
                H += (ys + yHy)*np.outer(step, step)/ys**2 - (np.outer(Hy, step) + np.outer(step, Hy))/ys
                direction = -np.dot(H, grad)

            if (direction == 0.0).all():
                self.logfunc({'message': 'direction is 0 -- need to bail out.'})
                break

            steplength = self.line_search.search(direction, None, args, kwargs)

            if steplength != 0:
                step = steplength * direction
                self.wrt += step
            else:
                self.logfunc({'message': 'step length is 0.'})

            # Prepare everything for the next loop.
            args, kwargs = next_args, next_kwargs
            # TODO: not all line searches have .grad!
            grad_m1[:], grad[:] = grad, self.line_search.grad

            yield {
                'steplength': steplength,
                'n_iter': i,
                'args': args,
                'kwargs': kwargs,
            }


{'fraction_non_alphanumeric': 0.10305123776626367, 'fraction_numerical': 0.004605641911341394, 'mean_word_length': 1.672820512820513, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4351273', 'n_tokens_mistral': 1651, 'n_tokens_neox': 1558, 'n_words': 406}