K iDdZddlmZddlmZddlmZddlZddl m Z ddl m Z dd gZ ejd dd Zdd ZddZe de dejd dZdZdZdZddZy)z%Functions for generating line graphs.) defaultdict)partial) combinationsN)arbitrary_element)not_implemented_for line_graphinverse_line_graphT) returns_graphc`|jrt||}|St|d|}|S)aReturns 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 ^/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/networkx/generators/line.pyrrs6L }}  6 H 1L I Hc.tjd||j}|jrt |j dn |j }|D]5}|j |||dD]}|j||7|S)a6Returns 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`. rdefaultTkeys)nx empty_graph __class__ is_multigraphredgesadd_nodeadd_edge)rr r get_edges from_nodeto_nodes rrr{s q, .edge_key_functions $q'"JtAw$777rN)key)rrrrrr enumeratesettuplesortedgetlenr updateadd_edges_from)rr r rr"shiftinr*ruxnodesabr)s @rrrsY0 q, ?@  *U H;1Ys+ E0EE directed multigraphc |jdk(rtjdS|jdk(r-t|}|df}|df tj| fg}|S|jdkDr*|j dk(rd}tj |tj|dk7rd}tj |t|}t||}tj|jd |D]}|D]} |xxdz cc<t jdkDrd}tj |t fd D} tj}|j!||j!| t#|jdD],\} t% fd|Ds|j'| .|S) afReturns 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 `_ rrzninverse_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.r+zEG is not a line graph (vertex found in more than two partition cells)c36K|]}|dk(s |fyw)rNr').0r8P_counts r z%inverse_line_graph..0s 7qwqzQqd 7s c3&K|]}|v ywNr')rAa_bitr<s rrCz%inverse_line_graph..5s)euz)s)number_of_nodesrrrGraphnumber_of_edges NetworkXErrornumber_of_selfloops_select_starting_cell_find_partitiondictfromkeysr:maxvaluesr/add_nodes_fromranyr!) rvr;Hmsg starting_cellPpr8WrBr<s @@rr r sj a~~a     ! a  F F HHq!fX    q Q%6%6%8A%= E s## a A% T s##)!,M=)AmmAGGQ'G  A AJ!OJ  7>> q Us## 7G 77A  AQQQWWa(1 )q) ) JJq!  Hrc|\}}||vrtjd|d|||vrtjd|d|dg}||D]}|||vs |j|||f |S)z.Return list of all triangles containing edge eVertex not in graphEdge (, ) not in graph)rrJappend)rer8rT triangle_listr9s r _trianglesrd:s DAqz=9::!}s"QC~>??M qT, !9  !Q +, rc|D]-}||jvstjd|dtt |dD]1}|d||dvstjd|dd|ddt t |D]}||D]}||vs|xxdz cc< tfd DS) aTest 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. r\r]r+rrr^r_r`c3,K|] }|dv yw))rNr')rArTT_nbrss rrCz _odd_triangle..ms3qvayF"3s)r:rrJlistrrintrS)rTr8rbtrTrhs @r _odd_trianglermHs2? AGGI ""WQC}#=> >?,q!$ %J Q4q1w ""VAaD6AaD6#HI IJ F 1 Azq Q   3F3 33rc,|j}|g}|jtt|dt|}|j dkDr|j }t ||}|dk7r|gt||z}|D]-}|D]&}||k7s |||vsd} tj| /|jt||jtt|d||z }|j dkDr|S)aiFind 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 r+rz>G is not a line graph (partition cell not a complete subgraph)) copyremove_edges_fromrirrIpopr2rrJrar/) rrW G_partitionrXpartitioned_verticesr8deg_unew_cellrTrVs rrMrMps%"&&(K A!!$|M1'E"FG .  % % '! + $ $ &KN# A:sT+a.11H 4!4AQQk!n%<G!..s33 4 4 HHU8_ %  ) )$|Ha/H*I J H , '  % % '! +( Hrc|t|j}nd|}|d|jvrtjd|dd|d||dvr$d|dd|dd}tj|t ||}t |}|dk(r|}|S|dk(re|d}|\}} } t t ||| f} t t || | f} | dk(r| dk(r|}|St|| | fSt||| fSd} g}|D]%}t||s| dz } |j|'|d k(r | dk(r}|S|dz | cxkr|krknnht}|D]}|D]}|j||D]-}|D]&}||k7s |||vsd }tj|/t|}|Sd }tj|) 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. rr\r]rzstarting_edge (r_z) is not in the Graph) starting_edger+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)) rrr:rrJrdr2rLrmrar.addr/)rrwrbrV e_trianglesrrWrkr;r<cac_edgesbc_edgess odd_trianglestriangle_nodesr9r8rTs rrLrLsb0 aggi (  Q4qwwy ""WQqTF-#@A A Q4q1w #AaD6AaD61FGC""3' 'Q"K KAAv f e a N1az!aV,-z!aV,- q=1} ! P M-Qq!fEE(1a&A A   (AQ"Q$$Q' ( 6a1fM2 1Ua_1_ UN" **A"&&q)* *$ 4'4AAv1AaD==!..s33 4 4".1M  6 ""3' 'rrE)FN)__doc__ collectionsr functoolsr itertoolsrnetworkxrnetworkx.utilsrnetworkx.utils.decoratorsr__all__ _dispatchablerrrr rdrmrMrLr'rrrs+#",9 - .%i &i X <> BZ \"%Z &#!Z z %4P* ZXr