o
    3ήc!6                     @   s   d Z ddlmZ ddlZddlmZ g dZdd Zdd	 Z	d
d Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zededd d! Zedd"d# ZdS )$z
Graph products.
    )productN)not_implemented_for)tensor_productcartesian_productlexicographic_productstrong_productpowerrooted_productc                    s     fddt  t B D S )Nc                    s"   i | ]}|  | |fqS  )get).0kd1d2r
   L/tmp/pip-target-vg8gfxp4/lib/python/networkx/algorithms/operators/product.py
<dictcomp>   s   " z!_dict_product.<locals>.<dictcomp>)setr   r
   r   r   _dict_product   s    r   c                 c   s:    t | |D ]\}}||ft| j| |j| fV  qd S N)r   r   nodes)GHuvr
   r
   r   _node_product   s   "r   c           
      c   s   |   s.|  s.| jddD ]\}}}|jddD ]\}}}||f||ft||fV  qq|   s^|  r^| jddD ]!\}}}|jdddD ]\}}}}||f||f|t||fV  qHq<|   r|  s| jdddD ] \}}}}|jddD ]\}}}||f||f|t||fV  qyqm|   r|  r| jdddD ](\}}}	}|jdddD ]\}}}}||f||f|	|ft||fV  qqd S d S d S NTdatar   keysis_multigraphedgesr   
r   r   r   r   cxydr   jr
   r
   r   _directed_edges_cross_edges   .   "r*   c           
      c   s   |   s.|  s.| jddD ]\}}}|jddD ]\}}}||f||ft||fV  qq|   s^|  r^| jddD ]!\}}}|jdddD ]\}}}}||f||f|t||fV  qHq<|   r|  s| jdddD ] \}}}}|jddD ]\}}}||f||f|t||fV  qyqm|   r|  r| jdddD ](\}}}	}|jdddD ]\}}}}||f||f|	|ft||fV  qqd S d S d S r   r!   r$   r
   r
   r   _undirected_edges_cross_edges0   r+   r,   c                 c   s    |   r%| jdddD ]\}}}}|D ]}||f||f||fV  qqd S | jddD ]$\}}}|D ]}|  rD||f||fd |fV  q2||f||f|fV  q2q+d S NTr   r   r"   r#   )r   r   r   r   r   r(   r&   r
   r
   r   _edges_cross_nodesC   s   r/   c                 c   s    |  r%| D ]}|jdddD ]\}}}}||f||f||fV  qqd S | D ](}|jddD ]\}}}|   rD||f||fd |fV  q/||f||f|fV  q/q'd S r-   r.   )r   r   r&   r   r   r   r(   r
   r
   r   _nodes_cross_edgesQ   s   r0   c                 c   s    |   r*| jdddD ]\}}}}|D ]}|D ]}||f||f||fV  qqqd S | jddD ])\}}}|D ]!}|D ]}|  rM||f||fd |fV  q;||f||f|fV  q;q7q0d S r-   r.   )r   r   r   r   r   r(   r&   r'   r
   r
   r   _edges_cross_nodes_and_nodes_   s$   r1   c                 C   sT   |   |  ksd}t||  s| rt }nt }|   r(| }|S )Nz0G and H must be both directed or both undirected)is_directednxNetworkXErrorr"   
MultiGraphGraphto_directed)r   r   msgGHr
   r
   r   _init_product_grapho   s   

r:   c                 C   sF   t | |}|t| | |t| | | s!|t| | |S )a  Returns the tensor product of G and H.

    The tensor product $P$ of the graphs $G$ and $H$ has a node set that
    is the tensor product of the node sets, $V(P)=V(G) \times V(H)$.
    $P$ has an edge $((u,v), (x,y))$ if and only if $(u,x)$ is an edge in $G$
    and $(v,y)$ is an edge in $H$.

    Tensor product is sometimes also referred to as the categorical product,
    direct product, cardinal product or conjunction.


    Parameters
    ----------
    G, H: graphs
     Networkx graphs.

    Returns
    -------
    P: NetworkX graph
     The tensor product of G and H. P will be a multi-graph if either G
     or H is a multi-graph, will be a directed if G and H are directed,
     and undirected if G and H are undirected.

    Raises
    ------
    NetworkXError
     If G and H are not both directed or both undirected.

    Notes
    -----
    Node attributes in P are two-tuple of the G and H node attributes.
    Missing attributes are assigned None.

    Examples
    --------
    >>> G = nx.Graph()
    >>> H = nx.Graph()
    >>> G.add_node(0, a1=True)
    >>> H.add_node("a", a2="Spam")
    >>> P = nx.tensor_product(G, H)
    >>> list(P)
    [(0, 'a')]

    Edge attributes and edge keys (for multigraphs) are also copied to the
    new product graph
    )r:   add_nodes_fromr   add_edges_fromr*   r2   r,   r   r   r9   r
   r
   r   r   |   s   
/r   c                 C   >   t | |}|t| | |t| | |t| | |S )a  Returns the Cartesian product of G and H.

    The Cartesian product $P$ of the graphs $G$ and $H$ has a node set that
    is the Cartesian product of the node sets, $V(P)=V(G) \times V(H)$.
    $P$ has an edge $((u,v),(x,y))$ if and only if either $u$ is equal to $x$
    and both $v$ and $y$ are adjacent in $H$ or if $v$ is equal to $y$ and
    both $u$ and $x$ are adjacent in $G$.

    Parameters
    ----------
    G, H: graphs
     Networkx graphs.

    Returns
    -------
    P: NetworkX graph
     The Cartesian product of G and H. P will be a multi-graph if either G
     or H is a multi-graph. Will be a directed if G and H are directed,
     and undirected if G and H are undirected.

    Raises
    ------
    NetworkXError
     If G and H are not both directed or both undirected.

    Notes
    -----
    Node attributes in P are two-tuple of the G and H node attributes.
    Missing attributes are assigned None.

    Examples
    --------
    >>> G = nx.Graph()
    >>> H = nx.Graph()
    >>> G.add_node(0, a1=True)
    >>> H.add_node("a", a2="Spam")
    >>> P = nx.cartesian_product(G, H)
    >>> list(P)
    [(0, 'a')]

    Edge attributes and edge keys (for multigraphs) are also copied to the
    new product graph
    )r:   r;   r   r<   r/   r0   r=   r
   r
   r   r      s
   
,r   c                 C   r>   )a  Returns the lexicographic product of G and H.

    The lexicographical product $P$ of the graphs $G$ and $H$ has a node set
    that is the Cartesian product of the node sets, $V(P)=V(G) \times V(H)$.
    $P$ has an edge $((u,v), (x,y))$ if and only if $(u,v)$ is an edge in $G$
    or $u==v$ and $(x,y)$ is an edge in $H$.

    Parameters
    ----------
    G, H: graphs
     Networkx graphs.

    Returns
    -------
    P: NetworkX graph
     The Cartesian product of G and H. P will be a multi-graph if either G
     or H is a multi-graph. Will be a directed if G and H are directed,
     and undirected if G and H are undirected.

    Raises
    ------
    NetworkXError
     If G and H are not both directed or both undirected.

    Notes
    -----
    Node attributes in P are two-tuple of the G and H node attributes.
    Missing attributes are assigned None.

    Examples
    --------
    >>> G = nx.Graph()
    >>> H = nx.Graph()
    >>> G.add_node(0, a1=True)
    >>> H.add_node("a", a2="Spam")
    >>> P = nx.lexicographic_product(G, H)
    >>> list(P)
    [(0, 'a')]

    Edge attributes and edge keys (for multigraphs) are also copied to the
    new product graph
    )r:   r;   r   r<   r1   r0   r=   r
   r
   r   r      s
   
+r   c                 C   sf   t | |}|t| | |t| | |t| | |t| | | s1|t| | |S )a  Returns the strong product of G and H.

    The strong product $P$ of the graphs $G$ and $H$ has a node set that
    is the Cartesian product of the node sets, $V(P)=V(G) \times V(H)$.
    $P$ has an edge $((u,v), (x,y))$ if and only if
    $u==v$ and $(x,y)$ is an edge in $H$, or
    $x==y$ and $(u,v)$ is an edge in $G$, or
    $(u,v)$ is an edge in $G$ and $(x,y)$ is an edge in $H$.

    Parameters
    ----------
    G, H: graphs
     Networkx graphs.

    Returns
    -------
    P: NetworkX graph
     The Cartesian product of G and H. P will be a multi-graph if either G
     or H is a multi-graph. Will be a directed if G and H are directed,
     and undirected if G and H are undirected.

    Raises
    ------
    NetworkXError
     If G and H are not both directed or both undirected.

    Notes
    -----
    Node attributes in P are two-tuple of the G and H node attributes.
    Missing attributes are assigned None.

    Examples
    --------
    >>> G = nx.Graph()
    >>> H = nx.Graph()
    >>> G.add_node(0, a1=True)
    >>> H.add_node("a", a2="Spam")
    >>> P = nx.strong_product(G, H)
    >>> list(P)
    [(0, 'a')]

    Edge attributes and edge keys (for multigraphs) are also copied to the
    new product graph
    )	r:   r;   r   r<   r0   r/   r*   r2   r,   r=   r
   r
   r   r     s   
-r   directed
multigraphc                    s   |dkrt dt }||  | D ]@ i }d}|   }|rG|}i }|D ]}| kr,q%||vr;|||< || |  q%||krAn|d7 }|s| fdd|D  q|S )a0  Returns the specified power of a graph.

    The $k$th power of a simple graph $G$, denoted $G^k$, is a
    graph on the same set of nodes in which two distinct nodes $u$ and
    $v$ are adjacent in $G^k$ if and only if the shortest path
    distance between $u$ and $v$ in $G$ is at most $k$.

    Parameters
    ----------
    G : graph
        A NetworkX simple graph object.

    k : positive integer
        The power to which to raise the graph `G`.

    Returns
    -------
    NetworkX simple graph
        `G` to the power `k`.

    Raises
    ------
    ValueError
        If the exponent `k` is not positive.

    NetworkXNotImplemented
        If `G` is not a simple graph.

    Examples
    --------
    The number of edges will never decrease when taking successive
    powers:

    >>> G = nx.path_graph(4)
    >>> list(nx.power(G, 2).edges)
    [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)]
    >>> list(nx.power(G, 3).edges)
    [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]

    The `k`th power of a cycle graph on *n* nodes is the complete graph
    on *n* nodes, if `k` is at least ``n // 2``:

    >>> G = nx.cycle_graph(5)
    >>> H = nx.complete_graph(5)
    >>> nx.is_isomorphic(nx.power(G, 2), H)
    True
    >>> G = nx.cycle_graph(8)
    >>> H = nx.complete_graph(8)
    >>> nx.is_isomorphic(nx.power(G, 4), H)
    True

    References
    ----------
    .. [1] J. A. Bondy, U. S. R. Murty, *Graph Theory*. Springer, 2008.

    Notes
    -----
    This definition of "power graph" comes from Exercise 3.1.6 of
    *Graph Theory* by Bondy and Murty [1]_.

    r   zk must be a positive integer   c                 3   s    | ]} |fV  qd S r   r
   )r   nbrnr
   r   	<genexpr>  s    zpower.<locals>.<genexpr>)
ValueErrorr3   r6   r;   updater<   )r   r   r   seenlevel	nextlevel	thislevelr   r
   rC   r   r   Q  s0   @
r   c                    sb    vr	t dt  }|t|   |fdd|  D  | fdd| D  |S )a  Return the rooted product of graphs G and H rooted at root in H.

    A new graph is constructed representing the rooted product of
    the inputted graphs, G and H, with a root in H.
    A rooted product duplicates H for each nodes in G with the root
    of H corresponding to the node in G. Nodes are renamed as the direct
    product of G and H. The result is a subgraph of the cartesian product.

    Parameters
    ----------
    G,H : graph
       A NetworkX graph
    root : node
       A node in H

    Returns
    -------
    R : The rooted product of G and H with a specified root in H

    Notes
    -----
    The nodes of R are the Cartesian Product of the nodes of G and H.
    The nodes of G and H are not relabeled.
    zroot must be a vertex in Hc                 3   s(    | ]}|d   f|d  ffV  qdS r   rA   Nr
   )r   e)rootr
   r   rE     s   & z!rooted_product.<locals>.<genexpr>c                 3   s6    | ]}   D ]}||d  f||d ffV  qqdS rL   )r#   )r   grM   )r   r
   r   rE     s   4 )r3   r4   r6   r;   r   r<   r#   )r   r   rN   Rr
   )r   rN   r   r	     s   
r	   )__doc__	itertoolsr   networkxr3   networkx.utilsr   __all__r   r   r*   r,   r/   r0   r1   r:   r   r   r   r   r   r	   r
   r
   r
   r   <module>   s,    
7347W