ó ŸÃÒYc@spdZdjddddgƒZdgZd d„Zd„Zd „Zd „Zd d „Z e d d „Z d S(s'Functions for generating line graphs. s sAric Hagberg (hagberg@lanl.gov)sPieter Swart (swart@lanl.gov)s Dan Schult (dschult@colgate.edu)schebee7i (chebee7i@gmail.com)t line_graphcCs=|jƒr!t|d|ƒ}nt|dtd|ƒ}|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. 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_undirectedtFalse(tGRtL((sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyRsX cCs%|jƒrd„}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. cSs&||kr|||fS|||fS(N((tutvtkey((sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyt sorted_nodeyscSs ||kr||fS||fS(N((R R ((sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyR |s(t is_multigraph(RR ((sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyt _node_funcqs   cs7ˆjƒr!d‡fd†}nd‡fd†}|S(sKReturns the edges from G, handling keys for multigraphs as necessary. csˆj|dtƒS(Ntkeys(tedgestTrue(tnbunch(R(sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyt get_edges†scs ˆj|ƒS(N(R(R(R(sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyR‰sN(R tNone(RR((Rsn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyt _edge_funcs cCs ||kr||fS||fS(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 ((sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyt _sorted_edgeŽs cCs}|dkr|jƒ}n|}t|ƒ}xI|ƒD]>}|j|ƒx(||dƒD]}|j||ƒq[Wq7W|S(sÌ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 : None A digraph instance used to populate the line graph. iN(Rt fresh_copyRtadd_nodetadd_edge(RRRRt from_nodetto_node((sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyRœs   cCs|dkr|jƒ}n|}t|ƒ}t|ƒ}|rEdnd}tgƒ}x§|D]Ÿ}g||ƒD]} || Œ^qq} t| ƒdkr¯|j| dƒnxKt| ƒD]=\} } |jg| | |D]} t | | ƒ^q݃q¼Wq^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 : None A graph instance used to populate the line graph. Notes ----- The standard algorithm for line graphs of undirected graphs does not produce self-loops. iiN( RRRRtsettlenRt enumeratetupdateRtadd_edges_from(RRRRRR tshiftRR txtnodestitatb((sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyR¼s     %9 N( t__doc__tjoint __author__t__all__RRRRRRRR(((sn/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/generators/line.pyts    _