docs: def locally_linear_embedding(geom, n_components, reg=1e-3,
                              eigen_solver='auto',  random_state=None,
                              solver_kwds=None):
      """
      Perform a Locally Linear Embedding analysis on the data.
  
      Parameters
      ----------
      geom : a Geometry object from megaman.geometry.geometry
      n_components : integer
          number of coordinates for the manifold.
      reg : float
          regularization constant, multiplies the trace of the local covariance
          matrix of the distances.
      eigen_solver : {'auto', 'dense', 'arpack', 'lobpcg', or 'amg'}
          'auto' :
              algorithm will attempt to choose the best method for input data
          'dense' :
              use standard dense matrix operations for the eigenvalue decomposition.
              For this method, M must be an array or matrix type.  This method should be avoided for large problems.
          'arpack' :
              use arnoldi iteration in shift-invert mode. For this method,
              M may be a dense matrix, sparse matrix, or general linear operator.
              Warning: ARPACK can be unstable for some problems.  It is best to
              try several random seeds in order to check results.
          'lobpcg' :
              Locally Optimal Block Preconditioned Conjugate Gradient Method.
              A preconditioned eigensolver for large symmetric positive definite
              (SPD) generalized eigenproblems.
          'amg' :
              AMG requires pyamg to be installed. It can be faster on very large,
              sparse problems, but may also lead to instabilities.
      random_state : numpy.RandomState or int, optional
          The generator or seed used to determine the starting vector for arpack
          iterations.  Defaults to numpy.random.
      solver_kwds : any additional keyword arguments to pass to the selected eigen_solver
  
      Returns
      -------
      Y : array-like, shape [n_samples, n_components]
          Embedding vectors.
      squared_error : float
          Reconstruction error for the embedding vectors. Equivalent to
          ``norm(Y - W Y, 'fro')**2``, where W are the reconstruction weights.
  
      References
      ----------
  
      .. [1] Roweis, S. & Saul, L. Nonlinear dimensionality reduction
          by locally linear embedding.  Science 290:2323 (2000).
      """
      if geom.X is None:
          raise ValueError("Must pass data matrix X to Geometry")
      if geom.adjacency_matrix is None:
          geom.compute_adjacency_matrix()
      W = barycenter_graph(geom.adjacency_matrix, geom.X, reg=reg)
      # we'll compute M = (I-W)'(I-W)
      # depending on the solver, we'll do this differently
      eigen_solver, solver_kwds = check_eigen_solver(eigen_solver, solver_kwds,
                                                     size=W.shape[0],
                                                     nvec=n_components + 1)
      if eigen_solver != 'dense':
          M = eye(*W.shape, format=W.format) - W
          M = (M.T * M).tocsr()
      else:
          M = (W.T * W - W.T - W).toarray()
          M.flat[::M.shape[0] + 1] += 1  # W = W - I = W - I
      return null_space(M, n_components, k_skip=1, eigen_solver=eigen_solver,
                        random_state=random_state)