3
Md*                 @   s^   d Z ddlZddddddd	gZdd
dZdd Zdd Zdd Zdd Zdd Z	ddd	Z
dS )zA
Operations on graphs including union, intersection, difference.
    Nunioncomposedisjoint_unionintersection
differencesymmetric_difference	full_joinc       	      C   s<  | j  |j  kstjd| j }|jj| j |jj|j dd }|| |d } |||d }t| t|@ r~tjdd| j  r| jddd	}n| jdd
}|j  r|jddd	}n|jdd
}|j|  |j| |j	| |j	| x"| D ]}|j
| j| j
|  qW x$|D ]}|j
| j|j
|  qW |S )a   Return the union of graphs G and H.

    Graphs G and H must be disjoint, otherwise an exception is raised.

    Parameters
    ----------
    G,H : graph
       A NetworkX graph

    rename : bool , default=(None, None)
       Node names of G and H can be changed by specifying the tuple
       rename=('G-','H-') (for example).  Node "u" in G is then renamed
       "G-u" and "v" in H is renamed "H-v".

    name : string
       Specify the name for the union graph

    Returns
    -------
    U : A union graph with the same type as G.

    Notes
    -----
    To force a disjoint union with node relabeling, use
    disjoint_union(G,H) or convert_node_labels_to integers().

    Graph, edge, and node attributes are propagated from G and H
    to the union graph.  If a graph attribute is present in both
    G and H the value from H is used.

    See Also
    --------
    disjoint_union
    z+G and H must both be graphs or multigraphs.c                s$    d kr| S  fdd}t j| |S )Nc                s$   t | tr |  }n t|  }|S )N)
isinstancestrrepr)xname)prefix V/var/www/html/virt/lib/python3.6/site-packages/networkx/algorithms/operators/binary.pylabelA   s    

z(union.<locals>.add_prefix.<locals>.label)nxrelabel_nodes)graphr   r   r   )r   r   
add_prefix=   s    zunion.<locals>.add_prefixr      z*The node sets of G and H are not disjoint.zCUse appropriate rename=(Gprefix,Hprefix)or use disjoint_union(G,H).T)keysdata)r   )is_multigraphr   NetworkXError	__class__r   updatesetedgesadd_nodes_fromadd_edges_fromnodes)	GHrenamer   Rr   ZG_edgesZH_edgesnr   r   r   r      s6    #






c             C   sF   t j| }t j|t|d}t||}|jj| j |jj|j |S )a   Return the disjoint union of graphs G and H.

    This algorithm forces distinct integer node labels.

    Parameters
    ----------
    G,H : graph
       A NetworkX graph

    Returns
    -------
    U : A union graph with the same type as G.

    Notes
    -----
    A new graph is created, of the same class as G.  It is recommended
    that G and H be either both directed or both undirected.

    The nodes of G are relabeled 0 to len(G)-1, and the nodes of H are
    relabeled len(G) to len(G)+len(H)-1.

    Graph, edge, and node attributes are propagated from G and H
    to the union graph.  If a graph attribute is present in both
    G and H the value from H is used.
    )Zfirst_label)r   Zconvert_node_labels_to_integerslenr   r   r   )r"   r#   ZR1ZR2r%   r   r   r   r   i   s    

c             C   s   t j| }| j |j ks$t jdt| t|kr>t jd| j |j kr| j rd| jdd}n| j }xb|D ]}|j| rr|j|  qrW n@|j r|jdd}n|j }x |D ]}| j| r|j|  qW |S )a  Returns a new graph that contains only the edges that exist in
    both G and H.

    The node sets of H and G must be the same.

    Parameters
    ----------
    G,H : graph
       A NetworkX graph.  G and H must have the same node sets.

    Returns
    -------
    GH : A new graph with the same type as G.

    Notes
    -----
    Attributes from the graph, nodes, and edges are not copied to the new
    graph.  If you want a new graph of the intersection of G and H
    with the attributes (including edge data) from G use remove_nodes_from()
    as follows

    >>> G = nx.path_graph(3)
    >>> H = nx.path_graph(5)
    >>> R = G.copy()
    >>> R.remove_nodes_from(n for n in G if n not in H)
    z+G and H must both be graphs or multigraphs.z!Node sets of graphs are not equalT)r   )	r   create_empty_copyr   r   r   Znumber_of_edgesr   has_edgeadd_edge)r"   r#   r%   r   er   r   r   r      s&    






c             C   s   | j  |j  kstjdtj| }t| t|kr>tjd| j  rT| jdd}n| j }x |D ]}|j| sb|j|  qbW |S )a  Returns a new graph that contains the edges that exist in G but not in H.

    The node sets of H and G must be the same.

    Parameters
    ----------
    G,H : graph
       A NetworkX graph.  G and H must have the same node sets.

    Returns
    -------
    D : A new graph with the same type as G.

    Notes
    -----
    Attributes from the graph, nodes, and edges are not copied to the new
    graph.  If you want a new graph of the difference of G and H with
    with the attributes (including edge data) from G use remove_nodes_from()
    as follows:

    >>> G = nx.path_graph(3)
    >>> H = nx.path_graph(5)
    >>> R = G.copy()
    >>> R.remove_nodes_from(n for n in G if n in H)
    z+G and H must both be graphs or multigraphs.zNode sets of graphs not equalT)r   )r   r   r   r(   r   r   r)   r*   )r"   r#   r%   r   r+   r   r   r   r      s    




c             C   s   | j  |j  kstjdtj| }t| t|kr>tjdt| }t|}|j|}|j| | j  rx| jdd}n| j }x |D ]}|j| s|j	|  qW |j  r|jdd}n|j }x |D ]}| j| s|j	|  qW |S )a  Returns new graph with edges that exist in either G or H but not both.

    The node sets of H and G must be the same.

    Parameters
    ----------
    G,H : graph
       A NetworkX graph.  G and H must have the same node sets.

    Returns
    -------
    D : A new graph with the same type as G.

    Notes
    -----
    Attributes from the graph, nodes, and edges are not copied to the new
    graph.
    z+G and H must both be graphs or multigraphs.zNode sets of graphs not equalT)r   )
r   r   r   r(   r   r   r   r   r)   r*   )r"   r#   r%   ZgnodesZhnodesr!   r   r+   r   r   r   r      s,    








c             C   s   | j  |j  kstjd| j }|jj| j |jj|j |j| jdd |j|jdd | j  r|j| j	ddd n|j| j	dd |j  r|j|j	ddd n|j|j	dd |S )a  Returns a new graph of G composed with H.

    Composition is the simple union of the node sets and edge sets.
    The node sets of G and H do not need to be disjoint.

    Parameters
    ----------
    G, H : graph
       A NetworkX graph

    Returns
    -------
    C: A new graph  with the same type as G

    Notes
    -----
    It is recommended that G and H be either both directed or both undirected.
    Attributes from H take precedent over attributes from G.

    For MultiGraphs, the edges are identified by incident nodes AND edge-key.
    This can cause surprises (i.e., edge `(1, 2)` may or may not be the same
    in two graphs) if you use MultiGraph without keeping track of edge keys.
    z+G and H must both be graphs or multigraphs.T)r   )r   r   )
r   r   r   r   r   r   r   r!   r    r   )r"   r#   r%   r   r   r   r   !  s    
c             C   s   t | ||}dd }|| |d } |||d }x&| D ]}x|D ]}|j|| q@W q6W |j rx&|D ]}x| D ]}|j|| qpW qfW |S )a  Returns the full join of graphs G and H.

    Full join is the union of G and H in which all edges between
    G and H are added.
    The node sets of G and H must be disjoint,
    otherwise an exception is raised.

    Parameters
    ----------
    G, H : graph
       A NetworkX graph

    rename : bool , default=(None, None)
       Node names of G and H can be changed by specifying the tuple
       rename=('G-','H-') (for example).  Node "u" in G is then renamed
       "G-u" and "v" in H is renamed "H-v".

    Returns
    -------
    U : The full join graph with the same type as G.

    Notes
    -----
    It is recommended that G and H be either both directed or both undirected.

    If G is directed, then edges from G to H are added as well as from H to G.

    Note that full_join() does not produce parallel edges for MultiGraphs.

    The full join operation of graphs G and H is the same as getting
    their complement, performing a disjoint union, and finally getting
    the complement of the resulting graph.

    Graph, edge, and node attributes are propagated from G and H
    to the union graph.  If a graph attribute is present in both
    G and H the value from H is used.

    See Also
    --------
    union
    disjoint_union
    c                s$    d kr| S  fdd}t j| |S )Nc                s$   t | tr |  }n t|  }|S )N)r	   r
   r   )r   r   )r   r   r   r     s    

z,full_join.<locals>.add_prefix.<locals>.label)r   r   )r   r   r   r   )r   r   r   |  s    zfull_join.<locals>.add_prefixr   r   )r   r*   Zis_directed)r"   r#   r$   r%   r   ijr   r   r   r   O  s    +



NN)r.   NNN)r/   )__doc__Znetworkxr   __all__r   r   r   r   r   r   r   r   r   r   r   <module>   s   
X"6,4.