'Finds the K-neighbors of a point.
Returns indices of and distances to the neighbors of each point.
Parameters
X : array-like, shape (n_query, n_features),                 or (n_query, n_indexed) if metric == \'precomputed\'
The query point or points.
If not provided, neighbors of each indexed point are returned.
In this case, the query point is not considered its own neighbor.
n_neighbors : int
Number of neighbors to get (default is the value
passed to the constructor).
return_distance : boolean, optional. Defaults to True.
If False, distances will not be returned
Returns
dist : array
Array representing the lengths to points, only present if
return_distance=True
ind : array
Indices of the nearest points in the population matrix.
Examples
In the following example, we construct a NeighborsClassifier
class from an array representing our data set and ask who\'s
the closest point to [1,1,1]
>>> samples = [[0., 0., 0.], [0., .5, 0.], [1., 1., .5]]
>>> from sklearn.neighbors import NearestNeighbors
>>> neigh = NearestNeighbors(n_neighbors=1)
>>> neigh.fit(samples) # doctest: +ELLIPSIS
NearestNeighbors(algorithm=\'auto\', leaf_size=30, ...)
>>> print(neigh.kneighbors([[1., 1., 1.]])) # doctest: +ELLIPSIS
(array([[ 0.5]]), array([[2]]...))
As you can see, it returns [[0.5]], and [[2]], which means that the
element is at distance 0.5 and is the third element of samples
(indexes start at 0). You can also query for multiple points:
>>> X = [[0., 1., 0.], [1., 0., 1.]]
>>> neigh.kneighbors(X, return_distance=False) # doctest: +ELLIPSIS
array([[1],
[2]]...)'

def kneighbors(self, X=None, n_neighbors=None, return_distance=True):

    if (self._fit_method is None):
        raise NotFittedError('Must    fit    neighbors    before    querying.')
    if (n_neighbors is None):
        n_neighbors = self.n_neighbors
    if (X is not None):
        query_is_train = False
        X = check_array(X, accept_sparse='csr')
    else:
        query_is_train = True
        X = self._fit_X
        n_neighbors += 1
    train_size = self._fit_X.shape[0]
    if (n_neighbors > train_size):
        raise ValueError(('Expected    n_neighbors    <=    n_samples,        but    n_samples    =    %d,    n_neighbors    =    %d' % (train_size, n_neighbors)))
    (n_samples, _) = X.shape
    sample_range = np.arange(n_samples)[:, None]
    n_jobs = _get_n_jobs(self.n_jobs)
    if (self._fit_method == 'brute'):
        if (self.effective_metric_ == 'euclidean'):
            dist = pairwise_distances(X, self._fit_X, 'euclidean', n_jobs=n_jobs, squared=True)
        else:
            dist = pairwise_distances(X, self._fit_X, self.effective_metric_, n_jobs=n_jobs, **self.effective_metric_params_)
        neigh_ind = np.argpartition(dist, (n_neighbors - 1), axis=1)
        neigh_ind = neigh_ind[:, :n_neighbors]
        neigh_ind = neigh_ind[(sample_range, np.argsort(dist[(sample_range, neigh_ind)]))]
        if return_distance:
            if (self.effective_metric_ == 'euclidean'):
                result = (np.sqrt(dist[(sample_range, neigh_ind)]), neigh_ind)
            else:
                result = (dist[(sample_range, neigh_ind)], neigh_ind)
        else:
            result = neigh_ind
    elif (self._fit_method in ['ball_tree', 'kd_tree']):
        if issparse(X):
            raise ValueError(("%s    does    not    work    with    sparse    matrices.    Densify    the    data,    or    set    algorithm='brute'" % self._fit_method))
        result = Parallel(n_jobs, backend='threading')((delayed(self._tree.query, check_pickle=False)(X[s], n_neighbors, return_distance) for s in gen_even_slices(X.shape[0], n_jobs)))
        if return_distance:
            (dist, neigh_ind) = tuple(zip(*result))
            result = (np.vstack(dist), np.vstack(neigh_ind))
        else:
            result = np.vstack(result)
    else:
        raise ValueError('internal:    _fit_method    not    recognized')
    if (not query_is_train):
        return result
    else:
        if return_distance:
            (dist, neigh_ind) = result
        else:
            neigh_ind = result
        sample_mask = (neigh_ind != sample_range)
        dup_gr_nbrs = np.all(sample_mask, axis=1)
        sample_mask[:, 0][dup_gr_nbrs] = False
        neigh_ind = np.reshape(neigh_ind[sample_mask], (n_samples, (n_neighbors - 1)))
        if return_distance:
            dist = np.reshape(dist[sample_mask], (n_samples, (n_neighbors - 1)))
            return (dist, neigh_ind)
        return neigh_ind
