U
    Af                     @   sN   d Z ddlZddlZddlmZ ddgZejeddd	dZdddZ	dS )z/Functions for computing eigenvector centrality.    N)not_implemented_foreigenvector_centralityeigenvector_centrality_numpyZ
multigraphd   ư>c           
         s:  t | dkrtd|dkr,dd | D }tdd | D rLtdt| fd	d| D |  }t	|D ]}
 D ]F}| | D ]8}|r| | | |d
nd
}	|  | |	 7  < qqtj  pd
  fdd D tfddD || k r~  S q~t|dS )u  Compute the eigenvector centrality for the graph `G`.

    Eigenvector centrality computes the centrality for a node based on the
    centrality of its neighbors. The eigenvector centrality for node $i$ is
    the $i$-th element of the vector $x$ defined by the equation

    .. math::

        Ax = \lambda x

    where $A$ is the adjacency matrix of the graph `G` with eigenvalue
    $\lambda$. By virtue of the Perron–Frobenius theorem, there is a unique
    solution $x$, all of whose entries are positive, if $\lambda$ is the
    largest eigenvalue of the adjacency matrix $A$ ([2]_).

    Parameters
    ----------
    G : graph
      A networkx graph

    max_iter : integer, optional (default=100)
      Maximum number of iterations in power method.

    tol : float, optional (default=1.0e-6)
      Error tolerance used to check convergence in power method iteration.

    nstart : dictionary, optional (default=None)
      Starting value of eigenvector iteration for each node.

    weight : None or string, optional (default=None)
      If None, all edge weights are considered equal.
      Otherwise holds the name of the edge attribute used as weight.
      In this measure the weight is interpreted as the connection strength.

    Returns
    -------
    nodes : dictionary
       Dictionary of nodes with eigenvector centrality as the value.

    Examples
    --------
    >>> G = nx.path_graph(4)
    >>> centrality = nx.eigenvector_centrality(G)
    >>> sorted((v, f"{c:0.2f}") for v, c in centrality.items())
    [(0, '0.37'), (1, '0.60'), (2, '0.60'), (3, '0.37')]

    Raises
    ------
    NetworkXPointlessConcept
        If the graph `G` is the null graph.

    NetworkXError
        If each value in `nstart` is zero.

    PowerIterationFailedConvergence
        If the algorithm fails to converge to the specified tolerance
        within the specified number of iterations of the power iteration
        method.

    See Also
    --------
    eigenvector_centrality_numpy
    pagerank
    hits

    Notes
    -----
    The measure was introduced by [1]_ and is discussed in [2]_.

    The power iteration method is used to compute the eigenvector and
    convergence is **not** guaranteed. Our method stops after ``max_iter``
    iterations or when the change in the computed vector between two
    iterations is smaller than an error tolerance of
    ``G.number_of_nodes() * tol``. This implementation uses ($A + I$)
    rather than the adjacency matrix $A$ because it shifts the spectrum
    to enable discerning the correct eigenvector even for networks with
    multiple dominant eigenvalues.

    For directed graphs this is "left" eigenvector centrality which corresponds
    to the in-edges in the graph. For out-edges eigenvector centrality
    first reverse the graph with ``G.reverse()``.

    References
    ----------
    .. [1] Phillip Bonacich.
       "Power and Centrality: A Family of Measures."
       *American Journal of Sociology* 92(5):1170–1182, 1986
       <http://www.leonidzhukov.net/hse/2014/socialnetworks/papers/Bonacich-Centrality.pdf>
    .. [2] Mark E. J. Newman.
       *Networks: An Introduction.*
       Oxford University Press, USA, 2010, pp. 169.

    r   ,cannot compute centrality for the null graphNc                 S   s   i | ]
}|d qS )    .0vr	   r	   N/tmp/pip-unpacked-wheel-0wvcsx6h/networkx/algorithms/centrality/eigenvector.py
<dictcomp>p   s      z*eigenvector_centrality.<locals>.<dictcomp>c                 s   s   | ]}|d kV  qdS )r   Nr	   r
   r	   r	   r   	<genexpr>q   s     z)eigenvector_centrality.<locals>.<genexpr>z*initial vector cannot have all zero valuesc                    s   i | ]\}}||  qS r	   r	   r   kr   )
nstart_sumr	   r   r   v   s      r   c                    s   i | ]\}}||  qS r	   r	   r   )normr	   r   r      s      c                 3   s"   | ]}t  | |  V  qd S )N)abs)r   n)xxlastr	   r   r      s     )lennxNetworkXPointlessConceptallvaluesZNetworkXErrorsumitemsZnumber_of_nodesrangecopygetmathhypotZPowerIterationFailedConvergence)
Gmax_itertolZnstartweightZnnodes_r   Znbrwr	   )r   r   r   r   r   r   
   s.    `
 
2   c                 C   s   ddl }ddl}ddl}t| dkr.tdtj| t| |td}|j	j
j|jdd||d\}}	|	 j}
||
 |j
|
 }tt| |
| S )uQ	  Compute the eigenvector centrality for the graph G.

    Eigenvector centrality computes the centrality for a node based on the
    centrality of its neighbors. The eigenvector centrality for node $i$ is

    .. math::

        Ax = \lambda x

    where $A$ is the adjacency matrix of the graph G with eigenvalue $\lambda$.
    By virtue of the Perron–Frobenius theorem, there is a unique and positive
    solution if $\lambda$ is the largest eigenvalue associated with the
    eigenvector of the adjacency matrix $A$ ([2]_).

    Parameters
    ----------
    G : graph
      A networkx graph

    weight : None or string, optional (default=None)
      The name of the edge attribute used as weight.
      If None, all edge weights are considered equal.
      In this measure the weight is interpreted as the connection strength.
    max_iter : integer, optional (default=100)
      Maximum number of iterations in power method.

    tol : float, optional (default=1.0e-6)
       Relative accuracy for eigenvalues (stopping criterion).
       The default value of 0 implies machine precision.

    Returns
    -------
    nodes : dictionary
       Dictionary of nodes with eigenvector centrality as the value.

    Examples
    --------
    >>> G = nx.path_graph(4)
    >>> centrality = nx.eigenvector_centrality_numpy(G)
    >>> print([f"{node} {centrality[node]:0.2f}" for node in centrality])
    ['0 0.37', '1 0.60', '2 0.60', '3 0.37']

    See Also
    --------
    eigenvector_centrality
    pagerank
    hits

    Notes
    -----
    The measure was introduced by [1]_.

    This algorithm uses the SciPy sparse eigenvalue solver (ARPACK) to
    find the largest eigenvalue/eigenvector pair.

    For directed graphs this is "left" eigenvector centrality which corresponds
    to the in-edges in the graph. For out-edges eigenvector centrality
    first reverse the graph with ``G.reverse()``.

    Raises
    ------
    NetworkXPointlessConcept
        If the graph ``G`` is the null graph.

    References
    ----------
    .. [1] Phillip Bonacich:
       Power and Centrality: A Family of Measures.
       American Journal of Sociology 92(5):1170–1182, 1986
       http://www.leonidzhukov.net/hse/2014/socialnetworks/papers/Bonacich-Centrality.pdf
    .. [2] Mark E. J. Newman:
       Networks: An Introduction.
       Oxford University Press, USA, 2010, pp. 169.
    r   Nr   )Znodelistr'   Zdtyper   ZLR)r   whichmaxiterr&   )ZnumpyscipyZscipy.sparse.linalgr   r   r   Zto_scipy_sparse_arraylistfloatsparseZlinalgZeigsTflattenrealsignr   r   dictzip)r$   r'   r%   r&   npspr-   Mr(   Zeigenvectorlargestr   r	   r	   r   r      s$    K    

)r   r   NN)Nr*   r   )
__doc__r"   Znetworkxr   Znetworkx.utilsr   __all__	_dispatchr   r   r	   r	   r	   r   <module>   s    