Run the minimization.

        Returns
        -------
        K : (N,N) ndarray
            the optimal rate matrix

def run(self):
        """Run the minimization.

        Returns
        -------
        K : (N,N) ndarray
            the optimal rate matrix
        """
        if self.verbose:
            self.selftest()
        self.count = 0
        if self.verbose:
            logging.info('initial value of the objective function is %f'
                         % self.function(self.initial))
        theta0 = self.initial
        theta, f, d = fmin_l_bfgs_b(self.function_and_gradient, theta0, fprime=None, args=(),
                                    approx_grad=False, bounds=self.bounds, factr=self.tol,
                                    pgtol=1.0E-11, disp=0, maxiter=self.maxiter, maxfun=self.maxiter, maxls=100)
        if self.verbose:
            logging.info('l_bfgs_b says: '+str(d))
            logging.info('objective function value reached: %f' % f)
        if d['warnflag'] != 0:
            raise_or_warn(str(d), on_error=self.on_error, warning=NotConvergedWarning, exception=NotConvergedError)

        K = np.zeros((self.N, self.N))
        K[self.I, self.J] = theta / self.pi[self.I]
        K[self.J, self.I] = theta / self.pi[self.J]
        np.fill_diagonal(K, -np.sum(K, axis=1))
        self.K = K
        return K