U
    àd¨i¾  ã                   @   s@   d Z ddlZddlmZ ddlmZ ddœdd„Zddd„ZdS )zy
Graph utilities and algorithms

Graphs are represented with their adjacency matrices, preferably using
sparse matrices.
é    N)Úsparseé   )Úpairwise_distances)Úcutoffc                C   s„   t  | ¡r|  ¡ } n
t  | ¡} i }d}|g}|r€|}tƒ }|D ]$}||kr>|||< | | j| ¡ q>|dk	rv||krvq€|d7 }q,|S )aA  Return the length of the shortest path from source to all reachable nodes.

    Parameters
    ----------
    graph : {sparse matrix, ndarray} of shape (n_nodes, n_nodes)
        Adjacency matrix of the graph. Sparse matrix of format LIL is
        preferred.

    source : int
       Start node for path.

    cutoff : int, default=None
        Depth to stop the search - only paths of length <= cutoff are returned.

    Returns
    -------
    paths : dict
        Reachable end nodes mapped to length of path from source,
        i.e. `{end: path_length}`.

    Examples
    --------
    >>> from sklearn.utils.graph import single_source_shortest_path_length
    >>> import numpy as np
    >>> graph = np.array([[ 0, 1, 0, 0],
    ...                   [ 1, 0, 1, 0],
    ...                   [ 0, 1, 0, 0],
    ...                   [ 0, 0, 0, 0]])
    >>> single_source_shortest_path_length(graph, 0)
    {0: 0, 1: 1, 2: 2}
    >>> graph = np.ones((6, 6))
    >>> sorted(single_source_shortest_path_length(graph, 2).items())
    [(0, 1), (1, 1), (2, 0), (3, 1), (4, 1), (5, 1)]
    r   Né   )r   ÚissparseZtolilZ
lil_matrixÚsetÚupdateZrows)ÚgraphÚsourcer   ÚseenÚlevelZ
next_levelZ
this_levelÚv© r   ú7/tmp/pip-unpacked-wheel-vgbd3m5j/sklearn/utils/graph.pyÚ"single_source_shortest_path_length   s"    #



r   ÚdistanceÚ	euclideanc                 K   s4  |dkrt  | ¡rtdƒ‚t|ƒD ]
}t ||k¡}| | }	t|ƒD ]æ}
t ||
k¡}| | }|dkrz| t ||¡ }nt|	|fd|i|—Ž}t |j	dd|j
¡\}}|dkrÜd||| || f< d||| || f< qF|dkr |||f ||| || f< |||f ||| || f< qFtd	| ƒ‚qFq"|S )
a   Add connections to sparse graph to connect unconnected components.

    For each pair of unconnected components, compute all pairwise distances
    from one component to the other, and add a connection on the closest pair
    of samples. This is a hacky way to get a graph with a single connected
    component, which is necessary for example to compute a shortest path
    between all pairs of samples in the graph.

    Parameters
    ----------
    X : array of shape (n_samples, n_features) or (n_samples, n_samples)
        Features to compute the pairwise distances. If `metric =
        "precomputed"`, X is the matrix of pairwise distances.

    graph : sparse matrix of shape (n_samples, n_samples)
        Graph of connection between samples.

    n_connected_components : int
        Number of connected components, as computed by
        `scipy.sparse.csgraph.connected_components`.

    component_labels : array of shape (n_samples)
        Labels of connected components, as computed by
        `scipy.sparse.csgraph.connected_components`.

    mode : {'connectivity', 'distance'}, default='distance'
        Type of graph matrix: 'connectivity' corresponds to the connectivity
        matrix with ones and zeros, and 'distance' corresponds to the distances
        between neighbors according to the given metric.

    metric : str
        Metric used in `sklearn.metrics.pairwise.pairwise_distances`.

    kwargs : kwargs
        Keyword arguments passed to
        `sklearn.metrics.pairwise.pairwise_distances`.

    Returns
    -------
    graph : sparse matrix of shape (n_samples, n_samples)
        Graph of connection between samples, with a single connected component.
    ZprecomputedzŒ_fix_connected_components with metric='precomputed' requires the full distance matrix in X, and does not work with a sparse neighbors graph.ÚmetricN)ZaxisZconnectivityr   r   z?Unknown mode=%r, should be one of ['connectivity', 'distance'].)r   r   ÚRuntimeErrorÚrangeÚnpZflatnonzeroZix_r   Zunravel_indexZargminÚshapeÚ
ValueError)ÚXr
   Zn_connected_componentsZcomponent_labelsÚmoder   ÚkwargsÚiZidx_iÚXiÚjZidx_jZXjÚDÚiiZjjr   r   r   Ú_fix_connected_componentsM   s4    3ÿ
ÿÿr"   )r   r   )	Ú__doc__Znumpyr   Zscipyr   Zmetrics.pairwiser   r   r"   r   r   r   r   Ú<module>   s   <  ú