
    \MhD                     .   d Z ddlmZ ddlmZ ddlmZ ddlZddl	m
Z
 ddlmZ dd	gZ ej        d
          dd            ZddZddZ ed           ed           ej        d
          d                                     Zd Zd Zd ZddZdS )z%Functions for generating line graphs.    )defaultdict)partial)combinationsN)arbitrary_element)not_implemented_for
line_graphinverse_line_graphT)returns_graphc                 v    |                                  rt          | |          }nt          | d|          }|S )a  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
    --------
    >>> 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)]]

    Edge attributes from `G` are not copied over as node attributes in `L`, but
    attributes can be copied manually:

    >>> G = nx.path_graph(4)
    >>> G.add_edges_from((u, v, {"tot": u + v}) for u, v in G.edges)
    >>> G.edges(data=True)
    EdgeDataView([(0, 1, {'tot': 1}), (1, 2, {'tot': 3}), (2, 3, {'tot': 5})])
    >>> H = nx.line_graph(G)
    >>> H.add_nodes_from((node, G.edges[node]) for node in H)
    >>> H.nodes(data=True)
    NodeDataView({(0, 1): {'tot': 1}, (2, 3): {'tot': 5}, (1, 2): {'tot': 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.

    )create_usingF)	selfloopsr   )is_directed_lg_directed_lg_undirected)Gr   Ls      X/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/networkx/generators/line.pyr   r      sC    L 	}} J6661LIIIH    c                 8   t          j        d|| j                  }|                                 rt	          | j        d          n| j        } |            D ]A}|                    |            ||d                   D ]}|                    ||           B|S )a6  Returns 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`.

    r   defaultTkeys   )nxempty_graph	__class__is_multigraphr   edgesadd_nodeadd_edge)r   r   r   	get_edges	from_nodeto_nodes         r   r   r   {   s      	q,<<<A 01/@/@Md++++agIY[[ + +		

9 y1.. 	+ 	+GJJy'****	+ Hr   Fc                 L  
 t          j        d|| j                  }|                                 rt	          | j        d          n| j        }|rdnd}d t          |           D             fdt                      }| D ]}fd ||          D             }t          |          dk    r|	                    |d                    t          |          D ]2\  }	
|
                    
fd	||	|z   d
         D                        3|                    |           |S )a  Returns 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.

    r   r   Tr   r   c                     i | ]\  }}||	S  r'   ).0ins      r   
<dictcomp>z"_lg_undirected.<locals>.<dictcomp>   s    00041a!Q000r   c                 <    | d                  | d                  fS )Nr   r   r'   )edge
node_indexs    r   edge_key_functionz)_lg_undirected.<locals>.edge_key_function   s     $q'"JtAw$777r   c           	      |    g | ]8}t          t          |d d         j                            |dd          z   9S )N   key)tuplesortedget)r(   xr.   s     r   
<listcomp>z"_lg_undirected.<locals>.<listcomp>   sE    XXXavae88899AabbEAXXXr   c                 P    g | ]"}t          t          |f                     #S )r2   )r4   r5   )r(   bar/   s     r   r8   z"_lg_undirected.<locals>.<listcomp>   sC        &!Q->???@@  r   N)r   r   r   r   r   r   	enumeratesetlenr    updateadd_edges_from)r   r   r   r   r"   shiftr   unodesr)   r;   r/   r.   s             @@@r   r   r      s   0 	q,<<<A 01/@/@Md++++agI !AAE 109Q<<000J8 8 8 8 8 EEE   YXXX99UV<<XXXu::??JJuQx   
 e$$ 	 	DAqLL    "1u9;;/     	 UHr   directed
multigraphc                 J  
 |                                  dk    rt          j        d          S |                                  dk    r0t          |           }|df}|dft          j        |fg          }|S |                                  dk    r.|                                 dk    rd}t          j        |          t          j        |           dk    rd}t          j        |          t          |           }t          | |          }t                              | j        d          
|D ]}|D ]}
|xx         dz  cc<   t          
                                          dk    rd}t          j        |          t          
fd
D                       }	t          j                    }|                    |           |                    |	           t#          |j        d          D ]6\  }t%          fd|D                       r|                    |           7|S )	af  Returns the inverse line graph of graph G.

    If H is a graph, and G is the line graph of H, such that G = L(H).
    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 function raises 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[1]_.

    If G consists of multiple components, then the algorithm doesn't work.
    You should invert every component separately:

    >>> K5 = nx.complete_graph(5)
    >>> P4 = nx.Graph([("a", "b"), ("b", "c"), ("c", "d")])
    >>> G = nx.union(K5, P4)
    >>> root_graphs = []
    >>> for comp in nx.connected_components(G):
    ...     root_graphs.append(nx.inverse_line_graph(G.subgraph(comp)))
    >>> len(root_graphs)
    2

    References
    ----------
    .. [1] Roussopoulos, N.D. , "A max {m, n} algorithm for determining the graph H from
       its line graph G", Information Processing Letters 2, (1973), 108--112, ISSN 0020-0190,
       `DOI link <https://doi.org/10.1016/0020-0190(73)90029-X>`_

    r   r   zninverse_line_graph() doesn't work on an edgeless graph. Please use this function on each component separately.zA line graph as generated by NetworkX has no selfloops, so G has no inverse line graph. Please remove the selfloops from G and try again.r1   zEG is not a line graph (vertex found in more than two partition cells)c              3   6   K   | ]}|         d k    |fV  dS )r   Nr'   )r(   rB   P_counts     r   	<genexpr>z%inverse_line_graph.<locals>.<genexpr>0  s-      77qwqzQqd77r   c              3       K   | ]}|v V  	d S Nr'   )r(   a_bitr:   s     r   rI   z%inverse_line_graph.<locals>.<genexpr>5  s'      ))euz))))))r   )number_of_nodesr   r   r   Graphnumber_of_edgesNetworkXErrornumber_of_selfloops_select_starting_cell_find_partitiondictfromkeysrC   maxvaluesr4   add_nodes_fromr   anyr!   )r   vr;   Hmsgstarting_cellPprB   WrH   r:   s             @@r   r	   r	      sP   j 	a~a   	
					!	!a  FFHq!fX	
				q	 	 Q%6%6%8%8A%=%=E 	 s###	a  A%%T 	 s###)!,,M=))AmmAGQ''G   	 	AAJJJ!OJJJJ	 7>>q  Us###7777G77777A


AQQQWa((  1))))q))))) 	JJq!Hr   c                     |\  }}|| vrt          j        d| d          || |         vrt          j        d| d| d          g }| |         D ]$}|| |         v r|                    |||f           %|S )z.Return list of all triangles containing edge eVertex  not in graphEdge (, ) not in graph)r   rP   append)r   erB   rZ   triangle_listr7   s         r   
_trianglesrj   :  s    DAqzz9999:::!}}>>>Q>>>???MqT , ,!99  !Q+++r   c                    |D ]0}||                                  vrt          j        d| d          1t          t	          |d                    D ]?}|d         | |d                  vr't          j        d|d          d|d          d          @t          t                    |D ]!}| |         D ]}||vr|xx         dz  cc<   "t          fd	D                       S )
a  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.

    rb   rc   r1   r   r   rd   re   rf   c              3   ,   K   | ]}|         d v V  dS ))r      Nr'   )r(   rZ   T_nbrss     r   rI   z _odd_triangle.<locals>.<genexpr>m  s,      33qvayF"333333r   )rC   r   rP   listr   r   intrY   )r   TrB   rh   trZ   rn   s         @r   _odd_trianglers   H  s/   2  ? ?AGGII"#=Q#=#=#=>>> ,q!$$%% J JQ4q1w"#HAaD#H#HAaD#H#H#HIII  F  1 	 	Azzq			Q				 3333F333333r   c                    |                                  }|g}|                    t          t          |d                               t          |          }|                                dk    r|                                }t          ||                   }|dk    r|gt          ||                   z   }|D ]-}|D ](}||k    r |||         vrd}	t          j        |	          ).|	                    t          |                     |                    t          t          |d                               ||z  }|                                dk    |S )ai  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
    r1   r   z>G is not a line graph (partition cell not a complete subgraph))copyremove_edges_fromro   r   rO   popr>   r   rP   rg   r4   )
r   r]   G_partitionr^   partitioned_verticesrB   deg_unew_cellrZ   r\   s
             r   rS   rS   p  sl   " &&((K	A!!$|M1'E'E"F"FGGG..

%
%
'
'!
+
+ $$&&KN##A:: sT+a.111H 4 4! 4 4AQQk!n%<%<G  !.s3334 HHU8__%%%))$|Ha/H/H*I*IJJJ H, ' 
%
%
'
'!
+
+( Hr   c                 T   |"t          |                                           }n{|}|d         |                                 vrt          j        d|d          d          |d         | |d                  vr)d|d          d|d          d}t          j        |          t          | |          }t          |          }|dk    r|}n_|dk    r|d         }|\  }}	}
t          t          | ||
f                    }t          t          | |	|
f                    }|dk    r|dk    r|}nt          | |	|
f	          S t          | ||
f	          S d}g }|D ],}t          | |          r|dz  }|	                    |           -|d
k    r	|dk    r|}n|dz
  |cxk    r|k    rpn nmt                      }|D ]}|D ]}|                    |           |D ]-}|D ](}||k    r || |         vrd}t          j        |          ).t          |          }nd}t          j        |          |S )a_  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.
    Nr   rb   rc   r   zstarting_edge (re   z) is not in the Graph)starting_edger1   zCG is not a line graph (odd triangles do not form complete subgraph)zNG is not a line graph (incorrect number of odd triangles around starting edge))r   r   rC   r   rP   rj   r>   rR   rs   rg   r=   addr4   )r   r}   rh   r\   e_trianglesrr]   rq   r;   r:   cac_edgesbc_edgessodd_trianglestriangle_nodesr7   rB   rZ   s                      r   rR   rR     s   0 aggii((Q4qwwyy  "#@QqT#@#@#@AAAQ4q1wGAaDGGAaDGGGC"3'''Q""KKAAvv	
a N1az!aV,,--z!aV,,--q==1}} !,Qq!fEEEE(1a&AAAA  	( 	(AQ"" (Q$$Q'''66a1ffMMUa____1_____ UUN" * * * *A"&&q))))* $ 4 4' 4 4AAvv1AaD===  !.s3334 ".11MM6  "3'''r   rK   )FN)__doc__collectionsr   	functoolsr   	itertoolsr   networkxr   networkx.utilsr   networkx.utils.decoratorsr   __all___dispatchabler   r   r   r	   rj   rs   rS   rR   r'   r   r   <module>r      s   + + # # # # # #       " " " " " "     , , , , , , 9 9 9 9 9 9-
. %%%i i i &%iX   <> > > >B Z  \""%%%Z Z &% #" ! Zz  %4 %4 %4P* * *ZX X X X X Xr   