docs: 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