ó
 ,µ[c           @   sæ   d  Z  d d l m Z d d l m Z d d l Z d d l m Z d d l	 Td d g Z
 d d	 „ Z d
 „  Z d „  Z d „  Z d d „ Z e d d „ Z e d ƒ e d ƒ d „  ƒ ƒ Z d „  Z d „  Z d „  Z d d „ Z d S(   s%   Functions for generating line graphs.iÿÿÿÿ(   t   combinations(   t   defaultdictN(   t   arbitrary_element(   t   *t
   line_grapht   inverse_line_graphc         C   s=   |  j  ƒ  r! t |  d | ƒ} n t |  d t d | ƒ} | S(   sº  Returns the line graph of the graph or digraph `G`.

    The line graph of a graph `G` has a node for each edge in `G` and an
    edge joining those nodes if the two edges in `G` share a common node. For
    directed graphs, nodes are adjacent exactly when the edges they represent
    form a directed path of length two.

    The nodes of the line graph are 2-tuples of nodes in the original graph (or
    3-tuples for multigraphs, with the key of the edge as the third element).

    For information about self-loops and more discussion, see the **Notes**
    section below.

    Parameters
    ----------
    G : graph
        A NetworkX Graph, DiGraph, MultiGraph, or MultiDigraph.
    create_using : NetworkX graph constructor, optional (default=nx.Graph)
       Graph type to create. If graph instance, then cleared before populated.

    Returns
    -------
    L : graph
        The line graph of G.

    Examples
    --------
    >>> import networkx as nx
    >>> G = nx.star_graph(3)
    >>> L = nx.line_graph(G)
    >>> print(sorted(map(sorted, L.edges())))  # makes a 3-clique, K3
    [[(0, 1), (0, 2)], [(0, 1), (0, 3)], [(0, 2), (0, 3)]]

    Notes
    -----
    Graph, node, and edge data are not propagated to the new graph. For
    undirected graphs, the nodes in G must be sortable, otherwise the
    constructed line graph may not be correct.

    *Self-loops in undirected graphs*

    For an undirected graph `G` without multiple edges, each edge can be
    written as a set `\{u, v\}`.  Its line graph `L` has the edges of `G` as
    its nodes. If `x` and `y` are two nodes in `L`, then `\{x, y\}` is an edge
    in `L` if and only if the intersection of `x` and `y` is nonempty. Thus,
    the set of all edges is determined by the set of all pairwise intersections
    of edges in `G`.

    Trivially, every edge in G would have a nonzero intersection with itself,
    and so every node in `L` should have a self-loop. This is not so
    interesting, and the original context of line graphs was with simple
    graphs, which had no self-loops or multiple edges. The line graph was also
    meant to be a simple graph and thus, self-loops in `L` are not part of the
    standard definition of a line graph. In a pairwise intersection matrix,
    this is analogous to excluding the diagonal entries from the line graph
    definition.

    Self-loops and multiple edges in `G` add nodes to `L` in a natural way, and
    do not require any fundamental changes to the definition. It might be
    argued that the self-loops we excluded before should now be included.
    However, the self-loops are still "trivial" in some sense and thus, are
    usually excluded.

    *Self-loops in directed graphs*

    For a directed graph `G` without multiple edges, each edge can be written
    as a tuple `(u, v)`. Its line graph `L` has the edges of `G` as its
    nodes. If `x` and `y` are two nodes in `L`, then `(x, y)` is an edge in `L`
    if and only if the tail of `x` matches the head of `y`, for example, if `x
    = (a, b)` and `y = (b, c)` for some vertices `a`, `b`, and `c` in `G`.

    Due to the directed nature of the edges, it is no longer the case that
    every edge in `G` should have a self-loop in `L`. Now, the only time
    self-loops arise is if a node in `G` itself has a self-loop.  So such
    self-loops are no longer "trivial" but instead, represent essential
    features of the topology of `G`. For this reason, the historical
    development of line digraphs is such that self-loops are included. When the
    graph `G` has multiple edges, once again only superficial changes are
    required to the definition.

    References
    ----------
    * Harary, Frank, and Norman, Robert Z., "Some properties of line digraphs",
      Rend. Circ. Mat. Palermo, II. Ser. 9 (1960), 161--168.
    * Hemminger, R. L.; Beineke, L. W. (1978), "Line graphs and line digraphs",
      in Beineke, L. W.; Wilson, R. J., Selected Topics in Graph Theory,
      Academic Press Inc., pp. 271--305.

    t   create_usingt	   selfloops(   t   is_directedt   _lg_directedt   _lg_undirectedt   False(   t   GR   t   L(    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyR      s    Zc         C   s%   |  j  ƒ  r d „  } n	 d „  } | S(   sÈ   Returns a function which returns a sorted node for line graphs.

    When constructing a line graph for undirected graphs, we must normalize
    the ordering of nodes as they appear in the edge.

    c         S   s&   |  | k r |  | | f S| |  | f S(   N(    (   t   ut   vt   key(    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyt   sorted_node   s    c         S   s    |  | k r |  | f S| |  f S(   N(    (   R   R   (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyR   „   s    (   t   is_multigraph(   R   R   (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyt
   _node_funcy   s    	c            s7   ˆ  j  ƒ  r! d ‡  f d † } n d ‡  f d † } | S(   sK   Returns the edges from G, handling keys for multigraphs as necessary.

    c            s   ˆ  j  |  d t ƒS(   Nt   keys(   t   edgest   True(   t   nbunch(   R   (    s7   lib/python2.7/site-packages/networkx/generators/line.pyt	   get_edgesŽ   s    c            s   ˆ  j  |  ƒ S(   N(   R   (   R   (   R   (    s7   lib/python2.7/site-packages/networkx/generators/line.pyR   ‘   s    N(   R   t   None(   R   R   (    (   R   s7   lib/python2.7/site-packages/networkx/generators/line.pyt
   _edge_func‰   s    c         C   s    |  | k r |  | f S| |  f S(   sÃ  Returns a sorted edge.

    During the construction of a line graph for undirected graphs, the data
    structure can be a multigraph even though the line graph will never have
    multiple edges between its nodes.  For this reason, we must make sure not
    to add any edge more than once.  This requires that we build up a list of
    edges to add and then remove all duplicates.  And so, we must normalize
    the representation of the edges.

    (    (   R   R   (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyt   _sorted_edge–   s    c         C   sw   t  j d | d |  j ƒ} t |  ƒ } xI | ƒ  D]> } | j | ƒ x( | | d ƒ D] } | j | | ƒ qU Wq1 W| S(   s5  Return the line graph L of the (multi)digraph G.

    Edges in G appear as nodes in L, represented as tuples of the form (u,v)
    or (u,v,key) if G is a multidigraph. A node in L corresponding to the edge
    (u,v) is connected to every node corresponding to an edge (v,w).

    Parameters
    ----------
    G : digraph
        A directed graph or directed multigraph.
    create_using : NetworkX graph constructor, optional
       Graph type to create. If graph instance, then cleared before populated.
       Default is to use the same graph class as `G`.

    i    t   defaulti   (   t   nxt   empty_grapht	   __class__R   t   add_nodet   add_edge(   R   R   R   R   t	   from_nodet   to_node(    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyR	   ¤   s    c         C   s  t  j d | d |  j ƒ} t |  ƒ } t |  ƒ } | r? d n d } t g  ƒ } x§ |  D]Ÿ } g  | | ƒ D] }	 | |	 Œ  ^ qk }
 t |
 ƒ d k r© | j |
 d ƒ n  xK t |
 ƒ D]= \ } } | j	 g  |
 | | D] } t
 | | ƒ ^ q× ƒ q¶ WqX W| j | ƒ | S(   s  Return the line graph L of the (multi)graph G.

    Edges in G appear as nodes in L, represented as sorted tuples of the form
    (u,v), or (u,v,key) if G is a multigraph. A node in L corresponding to
    the edge {u,v} is connected to every node corresponding to an edge that
    involves u or v.

    Parameters
    ----------
    G : graph
        An undirected graph or multigraph.
    selfloops : bool
        If `True`, then self-loops are included in the line graph. If `False`,
        they are excluded.
    create_using : NetworkX graph constructor, optional (default=nx.Graph)
       Graph type to create. If graph instance, then cleared before populated.

    Notes
    -----
    The standard algorithm for line graphs of undirected graphs does not
    produce self-loops.

    i    R   i   (   R   R   R   R   R   t   sett   lenR    t	   enumeratet   updateR   t   add_edges_from(   R   R   R   R   R   R   t   shiftR   R   t   xt   nodest   it   at   b(    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyR
   Â   s    %9t   directedt
   multigraphc         C   s‹  |  j  ƒ  d k s$ |  j ƒ  d k r< d } t j | ƒ ‚ n  t |  ƒ } t |  | ƒ } d „  |  j ƒ  Dƒ } x/ | D]' } x | D] } | | c d 7<q Wqt Wt | j ƒ  ƒ d k rÏ d } t j | ƒ ‚ n  t	 g  | D] } | | d k rÙ | f ^ qÙ ƒ } t j
 ƒ  } | j | ƒ | j | ƒ x] t | j ƒ  d ƒ D]F \ }	 }
 t t |	 ƒ j t |
 ƒ ƒ ƒ d k r=| j |	 |
 ƒ q=q=W| S(   s_   Returns the inverse line graph of graph G.

    If H is a graph, and G is the line graph of H, such that H = L(G).
    Then H is the inverse line graph of G.

    Not all graphs are line graphs and these do not have an inverse line graph.
    In these cases this generator returns a NetworkXError.

    Parameters
    ----------
    G : graph
        A NetworkX Graph

    Returns
    -------
    H : graph
        The inverse line graph of G.

    Raises
    ------
    NetworkXNotImplemented
        If G is directed or a multigraph

    NetworkXError
        If G is not a line graph

    Notes
    -----
    This is an implementation of the Roussopoulos algorithm.

    References
    ----------
    * Roussopolous, N, "A max {m, n} algorithm for determining the graph H from
      its line graph G", Information Processing Letters 2, (1973), 108--112.

    i    s2   G is not a line graph (has zero vertices or edges)c         S   s   i  |  ] } d  | “ q S(   i    (    (   t   .0R   (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pys
   <dictcomp>$  s   	 i   i   sE   G is not a line graph (vertex found in more than two partition cells)(   t   number_of_edgest   number_of_nodesR   t   NetworkXErrort   _select_starting_cellt   _find_partitionR+   t   maxt   valuest   tuplet   Grapht   add_nodes_fromR    R%   R$   t   intersectionR!   (   R   t   msgt   starting_cellt   Pt   P_countt   pR   t   Wt   HR-   R.   (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyR   ö   s(    '$2"'c         C   s±   | \ } } | |  k r. t  j d | ƒ ‚ n  | |  j | ƒ k r_ t  j d | | f ƒ ‚ n  g  } xE |  j | ƒ D]4 } | |  j | ƒ k ru | j | | | f ƒ qu qu W| S(   s/    Return list of all triangles containing edge es   Vertex %s not in graphs   Edge (%s, %s) not in graph(   R   R4   t	   neighborst   append(   R   t   eR   R   t   triangle_listR*   (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyt
   _triangles7  s    c         C   s  x6 | D]. } | |  j  ƒ  k r t j d | ƒ ‚ q q Wx^ t t | d ƒ ƒ D]G } | d |  j | d ƒ k rO t j d | d | d f ƒ ‚ qO qO Wt t ƒ } xG | D]? } x6 |  j | ƒ D]% } | | k rÃ | | c d 7<qÃ qÃ Wq­ Wx" | D] } | | d k r÷ t Sq÷ Wt	 S(   sí   Test whether T is an odd triangle in G

    Parameters
    ----------
    G : NetworkX Graph
    T : 3-tuple of vertices forming triangle in G

    Returns
    -------
    True is T is an odd triangle
    False otherwise

    Raises
    ------
    NetworkXError
        T is not a triangle in G

    Notes
    -----
    An odd triangle is one in which there exists another vertex in G which is
    adjacent to either exactly one or exactly all three of the vertices in the
    triangle.

    s   Vertex %s not in graphi   i    i   s   Edge (%s, %s) not in graphi   (   i   i   (
   R+   R   R4   t   listR    RD   R   t   intR   R   (   R   t   TR   RF   t   T_neighborst   tR   (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyt   _odd_triangleE  s    (c   
      C   s=  |  j  ƒ  } | g } | j t t | d ƒ ƒ ƒ t | ƒ } xù | j ƒ  d k r8| d } t | | ƒ } | d k r… | j ƒ  q@ | g t | j | ƒ ƒ } xX | D]P } xG | D]? } | | k rµ | |  j | ƒ k rµ d }	 t j	 |	 ƒ ‚ qµ qµ Wq¨ W| j
 t | ƒ ƒ | j t t | d ƒ ƒ ƒ | | 7} q@ W| S(   sj   Find a partition of the vertices of G into cells of complete graphs

    Parameters
    ----------
    G : NetworkX Graph
    starting_cell : tuple of vertices in G which form a cell

    Returns
    -------
    List of tuples of vertices of G

    Raises
    ------
    NetworkXError
        If a cell is not a complete subgraph then G is not a line graph
    i   i    iÿÿÿÿs=   G is not a line graph(partition cell not a complete subgraph)(   t   copyt   remove_edges_fromRI   R    R2   R%   t   popRD   R   R4   RE   R9   (
   R   R>   t   G_partitionR?   t   partitioned_verticesR   t   deg_ut   new_cellR   R=   (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyR6   p  s&    	
!c         C   sØ  | d k r' t t |  j ƒ  ƒ ƒ } n: | } | d |  | d k ra d } t j | | ƒ ‚ n  t |  | ƒ } t | ƒ } | d k r‘ | } nC| d k re| d } | \ } }	 }
 g  t |  | |
 f ƒ D] } | ^ qÌ } g  t |  |	 |
 f ƒ D] } | ^ qô } t | ƒ d k rLt | ƒ d k r3| } qbt |  d |	 |
 f ƒSqÔt |  d | |
 f ƒSnod } g  } x7 | D]/ } t	 |  | ƒ rx| d 7} | j
 | ƒ qxqxW| d k rÌ| d k rÌ| } n| d | k oç| k n r¿t g  ƒ } x, | D]$ } x | D] } | j | ƒ qWqÿWt | ƒ | d k r§xX | D]P } xG | D]? } | | k rQ| |  j | ƒ k rQd } t j | ƒ ‚ qQqQWqDWt | ƒ } qÔd } t j | ƒ ‚ n d } t j | ƒ ‚ | S(	   s`   Select a cell to initiate _find_partition

    Parameters
    ----------
    G : NetworkX Graph
    starting_edge: an edge to build the starting cell from

    Returns
    -------
    Tuple of vertices in G

    Raises
    ------
    NetworkXError
        If it is determined that G is not a line graph

    Notes
    -----
    If starting edge not specified then pick an arbitrary edge - doesn't
    matter which. However, this function may call itself requiring a
    specific starting edge. Note that the r, s notation for counting
    triangles is the same as in the Roussopoulos paper cited above.
    i    i   s*   starting_edge (%s, %s) is not in the Grapht   starting_edgei   sC   G is not a line graph (odd triangles do not form complete subgraph)sN   G is not a line graph (incorrect number of odd triangles around starting edge)N(   R   R   RI   R   R   R4   RH   R%   R5   RN   RE   R$   t   addRD   R9   (   R   RV   RF   R=   t   e_trianglest   rR>   RK   R-   R.   t   cR*   t   ac_edgest   bc_edgest   st   odd_trianglest   triangle_nodesR   R   (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyR5   Ÿ  sZ    	
((	
	 !(   t   __doc__t	   itertoolsR    t   collectionsR   t   networkxR   t   networkx.utilsR   t   networkx.utils.decoratorst   __all__R   R   R   R   R   R	   R   R
   t   not_implemented_forR   RH   RN   R6   R5   (    (    (    s7   lib/python2.7/site-packages/networkx/generators/line.pyt   <module>   s$   
a			4	@		+	/