
    hE                     n   S r SSKrSSKr/ SQr\R
                  " S/ SQ5      r\R
                  " S/ SQ5      r\R                  " SSS	.S
S0S9SS j5       r	\R                  " SSS	.S
S0S9SS j5       r
\R                  " SSS	.S
S0S9SS j5       rS rSS jrS rS rS rS rS rS rS rS rS rg)uu  
***************
VF2++ Algorithm
***************

An implementation of the VF2++ algorithm [1]_ for Graph Isomorphism testing.

The simplest interface to use this module is to call:

`vf2pp_is_isomorphic`: to check whether two graphs are isomorphic.
`vf2pp_isomorphism`: to obtain the node mapping between two graphs,
in case they are isomorphic.
`vf2pp_all_isomorphisms`: to generate all possible mappings between two graphs,
if isomorphic.

Introduction
------------
The VF2++ algorithm, follows a similar logic to that of VF2, while also
introducing new easy-to-check cutting rules and determining the optimal access
order of nodes. It is also implemented in a non-recursive manner, which saves
both time and space, when compared to its previous counterpart.

The optimal node ordering is obtained after taking into consideration both the
degree but also the label rarity of each node.
This way we place the nodes that are more likely to match, first in the order,
thus examining the most promising branches in the beginning.
The rules also consider node labels, making it easier to prune unfruitful
branches early in the process.

Examples
--------

Suppose G1 and G2 are Isomorphic Graphs. Verification is as follows:

Without node labels:

>>> import networkx as nx
>>> G1 = nx.path_graph(4)
>>> G2 = nx.path_graph(4)
>>> nx.vf2pp_is_isomorphic(G1, G2, node_label=None)
True
>>> nx.vf2pp_isomorphism(G1, G2, node_label=None)
{1: 1, 2: 2, 0: 0, 3: 3}

With node labels:

>>> G1 = nx.path_graph(4)
>>> G2 = nx.path_graph(4)
>>> mapped = {1: 1, 2: 2, 3: 3, 0: 0}
>>> nx.set_node_attributes(
...     G1, dict(zip(G1, ["blue", "red", "green", "yellow"])), "label"
... )
>>> nx.set_node_attributes(
...     G2,
...     dict(zip([mapped[u] for u in G1], ["blue", "red", "green", "yellow"])),
...     "label",
... )
>>> nx.vf2pp_is_isomorphic(G1, G2, node_label="label")
True
>>> nx.vf2pp_isomorphism(G1, G2, node_label="label")
{1: 1, 2: 2, 0: 0, 3: 3}

References
----------
.. [1] Jüttner, Alpár & Madarasi, Péter. (2018). "VF2++—An improved subgraph
   isomorphism algorithm". Discrete Applied Mathematics. 242.
   https://doi.org/10.1016/j.dam.2018.02.018

    N)vf2pp_isomorphismvf2pp_is_isomorphicvf2pp_all_isomorphisms_GraphParameters)G1G2	G1_labels	G2_labelsnodes_of_G1Labelsnodes_of_G2LabelsG2_nodes_of_degree_StateParameters)
mappingreverse_mappingT1T1_inT1_tildeT1_tilde_inT2T2_inT2_tildeT2_tilde_in   )r   r   
node_labeldefault_label)graphs
node_attrsc                 R     [        [        XX#5      5      nU$ ! [         a     gf = f)a  Return an isomorphic mapping between `G1` and `G2` if it exists.

Parameters
----------
G1, G2 : NetworkX Graph or MultiGraph instances.
    The two graphs to check for isomorphism.

node_label : str, optional
    The name of the node attribute to be used when comparing nodes.
    The default is `None`, meaning node attributes are not considered
    in the comparison. Any node that doesn't have the `node_label`
    attribute uses `default_label` instead.

default_label : scalar
    Default value to use when a node doesn't have an attribute
    named `node_label`. Default is `None`.

Returns
-------
dict or None
    Node mapping if the two graphs are isomorphic. None otherwise.
N)nextr   StopIteration)r   r   r   r   r   s        W/var/www/html/env/lib/python3.13/site-packages/networkx/algorithms/isomorphism/vf2pp.pyr   r   k   s0    0-bjPQ s    
&&c                      [        XX#5      b  gg)a  Examines whether G1 and G2 are isomorphic.

Parameters
----------
G1, G2 : NetworkX Graph or MultiGraph instances.
    The two graphs to check for isomorphism.

node_label : str, optional
    The name of the node attribute to be used when comparing nodes.
    The default is `None`, meaning node attributes are not considered
    in the comparison. Any node that doesn't have the `node_label`
    attribute uses `default_label` instead.

default_label : scalar
    Default value to use when a node doesn't have an attribute
    named `node_label`. Default is `None`.

Returns
-------
bool
    True if the two graphs are isomorphic, False otherwise.
TF)r   )r   r   r   r   s       r!   r   r      s    0 ;G    c           	   #   .  #    U R                  5       S:X  d  UR                  5       S:X  a  gU R                  5       (       a  [        U R                  U R                  5       VVVVs0 s H  u  u  pEu  pgXEU4_M     nnnnn[        UR                  UR                  5       VVVVs0 s H  u  u  pEu  pgXEU4_M     n	nnnnO*[        U R                  5      n[        UR                  5      n	U R                  5       (       d  [        n
[        nO[        n
[        nU R                  5       UR                  5       :w  a  g[        UR                  5       5      [        U	R                  5       5      :w  a  g[        XXU5      u  p[        U5      (       d  g[!        U5      n/ n[#        U
" US   XU5      5      nUR%                  US   U45        UR&                  nUR(                  nSnU(       a  US   u  nn [+        U5      n[1        UUX5      (       a  [3        U5      UR                  5       S-
  :X  a  UR5                  5       nUUU'   Uv   Mh  UUU'   UUU'   [7        UUX5        [#        U
" UU   XU5      5      nUR%                  UU   U45        US-  nU(       a  M  ggs  snnnnf s  snnnnf ! [,         aZ    UR/                  5         US-  nU(       a9  US   u  nnUU   nUR/                  U5        UR/                  U5        U" UUX5         GM.  f = f7f)a  Yields all the possible mappings between G1 and G2.

Parameters
----------
G1, G2 : NetworkX Graph or MultiGraph instances.
    The two graphs to check for isomorphism.

node_label : str, optional
    The name of the node attribute to be used when comparing nodes.
    The default is `None`, meaning node attributes are not considered
    in the comparison. Any node that doesn't have the `node_label`
    attribute uses `default_label` instead.

default_label : scalar
    Default value to use when a node doesn't have an attribute
    named `node_label`. Default is `None`.

Yields
------
dict
    Isomorphic mapping between the nodes in `G1` and `G2`.
r   Fr   N)number_of_nodesis_directedzip	in_degree
out_degreedictdegree_find_candidates_restore_Tinout_find_candidates_Di_restore_Tinout_Diordersortedvalues_initialize_parameters_precheck_label_properties_matching_orderiterappendr   r   r   r    pop_feasibilitylencopy_update_Tinout)r   r   r   r   nr)   _r*   	G1_degree	G2_degreefind_candidatesrestore_Tinoutgraph_paramsstate_params
node_orderstack
candidatesr   r   matching_nodecurrent_nodecandidate_nodes	candidatepopped_node1popped_node2
cp_mappings                             r!   r   r      s	    0 
q B$6$6$8A$= 
~~ 47r||R]]3S
3S/ :&&3S 	 
 47r||R]]3S
3S/ :&&3S 	 
	
 O	O	>>*(-+ 
xxzRXXZi !VI,<,<,>%?? "8
	}"L
 &l33 !.J E
1|9MJ 
LL*Q-,-""G"22O M
(-b	%o	_-I iLL7|r113a77$\\^
+4
<(   %.GL!)5OI&<LO}-|9J
 LL*]3Z@AQMK %e

f  	IIKQM"')a&|4L)##L1|\<V	sK   A$L&J
;*L%J&
:D8L3J. >BLL.ALLLLc                 f   ^ U u  pp4mpV[        U4S jUR                  5        5       5      (       a  gg)Nc              3   t   >#    U  H-  u  pUT;  =(       d    [        TU   5      [        U5      :g  v   M/     g 7fN)r;   ).0labelnodesr   s      r!   	<genexpr>-_precheck_label_properties.<locals>.<genexpr>   s<      5LE 	&&U#.?.F*G3u:*UU5s   58FT)anyitems)rD   r   r   r	   r
   r   r?   r   s          @r!   r5   r5     s>    LXIBI"35F
 -335   r#   c                    [        U R                  X4S95      n[        UR                  X4S95      n[        U UUU[        R                  R                  U5      [        R                  R                  U5      [        R                  R                  U5      5      n[        5       [        5       p[        5       [        5       pU R                  5       (       aE  [        U R                  5       5      [        5       p[        UR                  5       5      [        5       pOD[        U R                  5       5      [        5       p[        UR                  5       5      [        5       p[        0 0 UU	UUU
UUU5
      nUU4$ )a  Initializes all the necessary parameters for VF2++

Parameters
----------
G1,G2: NetworkX Graph or MultiGraph instances.
    The two graphs to check for isomorphism or monomorphism

G1_labels,G2_labels: dict
    The label of every node in G1 and G2 respectively

Returns
-------
graph_params: namedtuple
    Contains all the Graph-related parameters:

    G1,G2
    G1_labels,G2_labels: dict

state_params: namedtuple
    Contains all the State-related parameters:

    mapping: dict
        The mapping as extended so far. Maps nodes of G1 to nodes of G2

    reverse_mapping: dict
        The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1. It's basically "mapping" reversed

    T1, T2: set
        Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes that are not in the mapping, but are
        neighbors of nodes that are.

    T1_out, T2_out: set
        Ti_out contains all the nodes from Gi, that are neither in the mapping nor in Ti
)datadefault)	r+   rU   r   nxutilsgroupssetr'   r   )r   r   rA   r   r   r	   r
   rD   r   r   r   r   r   r   r   r   rE   s                    r!   r4   r4   (  s!   F RXX:XEFIRXX:XEFI#


	"
	"
	"L susu	~~
OE  !$BHHJ+ #BHHJ+ #BHHJ+#



L %%r#   c                 |  ^^^^ U u  mnm  p#nT(       d	  U(       d  0 $ TR                  5       (       a  TR                  SS9m[        TR                  5       5      nUR	                  5        VVs0 s H  u  pVU[        U5      _M     snnmT Vs0 s H  owS_M     snm/ nU(       Ga{  [        UU4S jU 5       5      n	U V
s/ s H  n
TTU
      U	:X  d  M  U
PM     nn
[        UTR                  S9n[        R                  " TU5       GH  nUR                  5       nU(       d  M  [        U4S jU 5       5      nU V
s/ s H  n
TU
   U:X  d  M  U
PM     nn
[        U4S jU 5       5      nU V
s/ s H  n
TR                  U
   U:X  d  M  U
PM     nn
[        UUU4S jS9nUR                  U5        TR                  U5       H  nTU==   S	-  ss'   M     UR                  U5        TTU   ==   S	-  ss'   UR                  U5        U(       a  M  GM     U(       a  GM{  U$ s  snnf s  snf s  sn
f s  sn
f s  sn
f )
a/  The node ordering as introduced in VF2++.

Notes
-----
Taking into account the structure of the Graph and the node labeling, the nodes are placed in an order such that,
most of the unfruitful/infeasible branches of the search space can be pruned on high levels, significantly
decreasing the number of visited states. The premise is that, the algorithm will be able to recognize
inconsistencies early, proceeding to go deep into the search tree only if it's needed.

Parameters
----------
graph_params: namedtuple
    Contains:

        G1,G2: NetworkX Graph or MultiGraph instances.
            The two graphs to check for isomorphism or monomorphism.

        G1_labels,G2_labels: dict
            The label of every node in G1 and G2 respectively.

Returns
-------
node_order: list
    The ordering of the nodes.
T)as_viewr   c              3   4   >#    U  H  nTTU      v   M     g 7frR    )rS   xr	   label_raritys     r!   rV   "_matching_order.<locals>.<genexpr>  s     J\il3\s   )keyc              3   .   >#    U  H
  nTU   v   M     g 7frR   rd   )rS   r>   used_degreess     r!   rV   rg     s     %L|!l1o|s   c              3   B   >#    U  H  nTR                   U   v   M     g 7frR   )r,   )rS   r>   r   s     r!   rV   rg     s      M7L!17Ls   c                    > TTU       $ rR   rd   )re   r	   rf   s    r!   <lambda>!_matching_order.<locals>.<lambda>  s    L14Nr#   r   )r'   to_undirectedr`   rU   rY   r;   minmaxr,   r]   
bfs_layersr<   r8   	neighborsremovediscard)rD   r   r?   r   V1_unorderedrT   rU   noderF   
max_rarityr>   rarest_nodesmax_nodedlevel_nodesnodes_to_addmax_used_degreemax_used_degree_nodes
max_degreemax_degree_nodes	next_noder   r	   rf   rj   s                       @@@@r!   r6   r6   t  s,   4 5A1BIq!b		~~d+rxxz?L:K:Q:Q:ST:S,%E3u:%:STL(*+!G+LJ
J\JJ
#
#!|IaL'AZ'OA| 	 
 |3MM"h7L',,.L,"%%L|%L"L+)+!|A//QA| & ) ! M7L MM
4$4!		!
8RA4 ! $  $*N	 !!),LL3D &!+& 4 ##I.Yy12a72$$Y/' , 8 ,< E U+

)$s0   .H$H*H/H/>H4H40H9H9c           
         Uu  pEn  pxn	Uu
  p          p|nX@    Vs/ s H  oU
;   d  M
  UPM     nnU(       d  [        XU       5      nUR                  XU       5        UR                  U5        UR                  U5        UR                  5       (       aI  UR                  U Vs1 s H,  nUR	                  X 5      UR	                  UU5      :w  d  M*  UiM.     sn5        U$ US   n[        XZU      5      nUSS  H  nUR                  XZU      5        M     UR                  U5        UR                  XU       5        UR                  XU       5        UR                  5       (       aI  UR                  U Vs1 s H,  nUR	                  X 5      UR	                  UU5      :w  d  M*  UiM.     sn5        U$ s  snf s  snf s  snf )aX  Given node u of G1, finds the candidates of u from G2.

Parameters
----------
u: Graph node
    The node from G1 for which to find the candidates from G2.

graph_params: namedtuple
    Contains all the Graph-related parameters:

    G1,G2: NetworkX Graph or MultiGraph instances.
        The two graphs to check for isomorphism or monomorphism

    G1_labels,G2_labels: dict
        The label of every node in G1 and G2 respectively

state_params: namedtuple
    Contains all the State-related parameters:

    mapping: dict
        The mapping as extended so far. Maps nodes of G1 to nodes of G2

    reverse_mapping: dict
        The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1. It's basically "mapping" reversed

    T1, T2: set
        Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes that are not in the mapping, but are
        neighbors of nodes that are.

    T1_tilde, T2_tilde: set
        Ti_tilde contains all the nodes from Gi, that are neither in the mapping nor in Ti

Returns
-------
candidates: set
    The nodes from G2 which are candidates for u.
r   r   N)r`   intersection_updatedifference_updateis_multigraphnumber_of_edges)urD   rE   r@   r   r   r	   r?   r   r   r   r   r   nbrcovered_nbrsrH   rw   nbr1common_nodess                      r!   r-   r-     s   P FRBBIq!0B>J;GaAq!Q!#%5;5C7NC5L;*Q<89
&&'9A,'GH&&x0$$_5(( !+ *))!/23E3EdD3QQ  * ?Dr$-()LQR ((DM):; ! ""?3$$%7!%EF$$%6|%DE	&& )(D%%a+r/A/A$/MM (	
 C <&s"   	F2F2")F7F76)F<#F<c           
         Uu  pEn  pxn	Uu
  p          p|nX@    Vs/ s H  oU
;   d  M
  UPM     nnUR                   U     Vs/ s H  oU
;   d  M
  UPM     nnU(       d  U(       d  [        XU       5      nUR                  XU       5        UR                  U5        UR                  U5        UR	                  5       (       aI  UR                  U Vs1 s H,  nUR                  X 5      UR                  UU5      :w  d  M*  UiM.     sn5        U$ U(       aN  US   n[        UR                   U
U      5      nUSS   H$  nUR                  UR                   U
U      5        M&     O UR                  5       n[        XZU      5      nU H  nUR                  XZU      5        M     UR                  U5        UR                  XU       5        UR                  XU       5        UR	                  5       (       aI  UR                  U Vs1 s H,  nUR                  X 5      UR                  UU5      :w  d  M*  UiM.     sn5        U$ s  snf s  snf s  snf s  snf )Nr   r   )predr`   r   r   r   r   r9   )r   rD   rE   r@   r   r   r	   r?   r   r   r   r   r   succcovered_successorsr   covered_predecessorsrH   rw   succ1r   pred1s                         r!   r/   r/   
  sS   EQBBIq!0B>J;GaAq!Q!+-5D54GO$5D-/WWQZKZT7?DZK"6*Q<89
&&'9A,'GH&&x0$$_5(( !+ *))!/23E3EdD3QQ  * "1%27775>23'+E,,RWWWU^-DE , %((*2en-.%((EN);< & ""?3$$%7!%EF$$%6|%DE	&& )(D%%a+r/A/A$/MM (	
 U EK4s.   	H<H< 	II)I<I )I-Ic                     UR                   n[        XX#5      (       a  gUR                  5       (       a  [        XX#5      (       d  gg)a  Given a candidate pair of nodes u and v from G1 and G2 respectively, checks if it's feasible to extend the
mapping, i.e. if u and v can be matched.

Notes
-----
This function performs all the necessary checking by applying both consistency and cutting rules.

Parameters
----------
node1, node2: Graph node
    The candidate pair of nodes being checked for matching

graph_params: namedtuple
    Contains all the Graph-related parameters:

    G1,G2: NetworkX Graph or MultiGraph instances.
        The two graphs to check for isomorphism or monomorphism

    G1_labels,G2_labels: dict
        The label of every node in G1 and G2 respectively

state_params: namedtuple
    Contains all the State-related parameters:

    mapping: dict
        The mapping as extended so far. Maps nodes of G1 to nodes of G2

    reverse_mapping: dict
        The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1. It's basically "mapping" reversed

    T1, T2: set
        Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes that are not in the mapping, but are
        neighbors of nodes that are.

    T1_out, T2_out: set
        Ti_out contains all the nodes from Gi, that are neither in the mapping nor in Ti

Returns
-------
True if all checks are successful, False otherwise.
FT)r   _cut_PTr   _consistent_PT)node1node2rD   rE   r   s        r!   r:   r:   ;  s@    T 
Bu\88	eLGGr#   c           
      J  ^ ^^^ Uu  mmpE    nUu
  nnnnn	nn
nnn0 0 pTR                  5       (       a  [        R                  R                  TR                  T     Vs0 s H  oXO   _M	     sn5      n[        R                  R                  TR                  T    Vs0 s H	  nUUU   _M     sn5      n[        UR                  5       5      [        UR                  5       5      :w  a  g[        R                  R                  TT     Vs0 s H  oXO   _M	     sn5      n[        R                  R                  TT    Vs0 s H	  nUUU   _M     sn5      n[        UR                  5       5      [        UR                  5       5      :w  a  gUR                  5        GH/  u  nnUU   nTR                  5       (       aO  [        UU 4S jU 5       5      n[        UU4S jU 5       5      n[        S [        UU5       5       5      (       a    g[        UR                  U5      5      [        U
R                  U5      5      :w  a    g[        U	R                  U5      5      [        UR                  U5      5      :w  a    gTR                  5       (       d  M  [        UR                  U5      5      [        UR                  U5      5      :w  d  GM0    g   TR                  5       (       d  gUR                  5        GH  u  nnUU   nTR                  5       (       aO  [        UU 4S jU 5       5      n[        UU4S jU 5       5      n[        S [        UU5       5       5      (       a    g[        UR                  U5      5      [        U
R                  U5      5      :w  a    g[        U	R                  U5      5      [        UR                  U5      5      :w  a    g[        UR                  U5      5      [        UR                  U5      5      :w  d  GM    g   gs  snf s  snf s  snf s  snf )	ac  Implements the cutting rules for the ISO problem.

Parameters
----------
u, v: Graph node
    The two candidate nodes being examined.

graph_params: namedtuple
    Contains all the Graph-related parameters:

    G1,G2: NetworkX Graph or MultiGraph instances.
        The two graphs to check for isomorphism or monomorphism

    G1_labels,G2_labels: dict
        The label of every node in G1 and G2 respectively

state_params: namedtuple
    Contains all the State-related parameters:

    mapping: dict
        The mapping as extended so far. Maps nodes of G1 to nodes of G2

    reverse_mapping: dict
        The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1. It's basically "mapping" reversed

    T1, T2: set
        Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes that are not in the mapping, but are
        neighbors of nodes that are.

    T1_tilde, T2_tilde: set
        Ti_out contains all the nodes from Gi, that are neither in the mapping nor in Ti

Returns
-------
True if we should prune this branch, i.e. the node pair failed the cutting checks. False otherwise.
Tc              3   H   >#    U  H  nTR                  TU5      v   M     g 7frR   r   rS   re   r   r   s     r!   rV   _cut_PT.<locals>.<genexpr>  !     !KFq""4"4Q":":F   "c              3   H   >#    U  H  nTR                  TU5      v   M     g 7frR   r   rS   re   r   vs     r!   rV   r     r   r   c              3   .   #    U  H  u  pX:g  v   M     g 7frR   rd   rS   u_nbr_edgesv_nbr_edgess      r!   rV   r           0O,K *0O   Fc              3   H   >#    U  H  nTR                  TU5      v   M     g 7frR   r   r   s     r!   rV   r     !     !LGq""4"4Q":":Gr   c              3   H   >#    U  H  nTR                  TU5      v   M     g 7frR   r   r   s     r!   rV   r     r   r   c              3   .   #    U  H  u  pX:g  v   M     g 7frR   rd   r   s      r!   rV   r     r   r   )r'   r]   r^   r_   r   r`   keysrY   r   r2   rX   r(   r;   intersection)r   r   rD   rE   r	   r
   r?   r   r   r   r   r   r   u_labels_predecessorsv_labels_predecessorsn1n2u_labels_successorsv_labels_successorsrT   G1_nbhG2_nbhu_nbrs_edgesv_nbrs_edgesG1_predG2_predu_pred_edgesv_pred_edgesr   r   s   ``                          @@r!   r   r   q  s   J -9)BI!Q 			
	
	 46r0	~~ ")+424!
 !#)+42R24!
 $))+,4I4N4N4P0QQ((//r!u*Muy}+<u*MN((//r!u*Mu2y}+<u*MN ##%&#.A.F.F.H*II,224v$U+!!KF!KKL!!KF!KKL 03L,0O   rv&'3rv/F+GGx$$V,-X5J5J65R1SS>>E$6$6v$> ?3v&D
 !
 ) 5, >>/557w'.!!LG!LLL!!LG!LLL 03L,0O   rw'(C0H,IIx$$W-.#h6K6KG6T2UUu!!'*+s53E3Eg3N/OO% 8( { 5 5 +N*Ms   PPP=P c                    UR                   UR                  pTUR                  UR                  pvX@    H3  nX;   d  M
  UR	                  X5      UR	                  XU   5      :w  d  M3    g   XQ    H3  nX;   d  M
  UR	                  XU   5      UR	                  X5      :w  d  M3    g   UR                  5       (       d  gUR                  U     H3  n	X;   d  M
  UR	                  X5      UR	                  Xi   U5      :w  d  M3    g   UR                  U    H3  n	X;   d  M
  UR	                  Xy   U 5      UR	                  X5      :w  d  M3    g   g)ah  Checks the consistency of extending the mapping using the current node pair.

Parameters
----------
u, v: Graph node
    The two candidate nodes being examined.

graph_params: namedtuple
    Contains all the Graph-related parameters:

    G1,G2: NetworkX Graph or MultiGraph instances.
        The two graphs to check for isomorphism or monomorphism

    G1_labels,G2_labels: dict
        The label of every node in G1 and G2 respectively

state_params: namedtuple
    Contains all the State-related parameters:

    mapping: dict
        The mapping as extended so far. Maps nodes of G1 to nodes of G2

    reverse_mapping: dict
        The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1. It's basically "mapping" reversed

    T1, T2: set
        Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes that are not in the mapping, but are
        neighbors of nodes that are.

    T1_out, T2_out: set
        Ti_out contains all the nodes from Gi, that are neither in the mapping nor in Ti

Returns
-------
True if the pair passes all the consistency checks successfully. False otherwise.
FT)r   r   r   r   r   r'   r   )
r   r   rD   rE   r   r   r   r   neighborpredecessors
             r!   r   r     sL   J __loo+33\5Q5Q_E!!!."2D2D8$3    E&!!!X%>?2CUCUD    >>wwqz!!!+1R5G5G$a6   " wwqz)!!,a##K34  " r#   c           
         Uu  pE        nUu
  nnn	n
nnnnnnX@    Vs1 s H  nUU;  d  M  UiM     nnXQ    Vs1 s H  nUU;  d  M  UiM     nnU	R                  U5        UR                  U5        U	R                  U 5        UR                  U5        UR                  U5        UR                  U5        UR                  U 5        UR                  U5        UR                  5       (       d  gUR                  U     Vs1 s H  nUU;  d  M  UiM     nnUR                  U    Vs1 s H  nUU;  d  M  UiM     nnU
R                  U5        UR                  U5        U
R                  U 5        UR                  U5        UR                  U5        UR                  U5        UR                  U 5        UR                  U5        gs  snf s  snf s  snf s  snf )a  Updates the Ti/Ti_out (i=1,2) when a new node pair u-v is added to the mapping.

Notes
-----
This function should be called right after the feasibility checks are passed, and node1 is mapped to node2. The
purpose of this function is to avoid brute force computing of Ti/Ti_out by iterating over all nodes of the graph
and checking which nodes satisfy the necessary conditions. Instead, in every step of the algorithm we focus
exclusively on the two nodes that are being added to the mapping, incrementally updating Ti/Ti_out.

Parameters
----------
new_node1, new_node2: Graph node
    The two new nodes, added to the mapping.

graph_params: namedtuple
    Contains all the Graph-related parameters:

    G1,G2: NetworkX Graph or MultiGraph instances.
        The two graphs to check for isomorphism or monomorphism

    G1_labels,G2_labels: dict
        The label of every node in G1 and G2 respectively

state_params: namedtuple
    Contains all the State-related parameters:

    mapping: dict
        The mapping as extended so far. Maps nodes of G1 to nodes of G2

    reverse_mapping: dict
        The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1. It's basically "mapping" reversed

    T1, T2: set
        Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes that are not in the mapping, but are
        neighbors of nodes that are.

    T1_tilde, T2_tilde: set
        Ti_out contains all the nodes from Gi, that are neither in the mapping nor in Ti
N)updateru   r   r'   r   )	new_node1	new_node2rD   rE   r   r   r?   r   r   r   r   r   r   r   r   r   r   r   uncovered_successors_G1uncovered_successors_G2r   uncovered_predecessors_G1uncovered_predecessors_G2s                          r!   r=   r=   1  s   P )BAq!Q 	

 13UWATtU&$o*E  
 II%&II%&JJyJJy6767YY>> +!+t7/B+  ! +!+t?/J+  ! 
LL*+	LL*+	MM)	MM)8989YYE V$!!s-   
GG
G	G	>
GG%
G3Gc           
      :  ^^ Uu  pE        nUu
  mmnnn	n
nnnnSnX@    H_  nUT;   a  SnUR                  U 5        M  [        U4S jUU    5       5      (       a  M=  UR                  U5        U	R                  U5        Ma     U(       d  U	R                  U 5        SnXQ    H_  nUT;   a  SnUR                  U5        M  [        U4S jUU    5       5      (       a  M=  UR                  U5        UR                  U5        Ma     U(       d  UR                  U5        gg)a+  Restores the previous version of Ti/Ti_out when a node pair is deleted from the mapping.

Parameters
----------
popped_node1, popped_node2: Graph node
    The two nodes deleted from the mapping.

graph_params: namedtuple
    Contains all the Graph-related parameters:

    G1,G2: NetworkX Graph or MultiGraph instances.
        The two graphs to check for isomorphism or monomorphism

    G1_labels,G2_labels: dict
        The label of every node in G1 and G2 respectively

state_params: namedtuple
    Contains all the State-related parameters:

    mapping: dict
        The mapping as extended so far. Maps nodes of G1 to nodes of G2

    reverse_mapping: dict
        The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1. It's basically "mapping" reversed

    T1, T2: set
        Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes that are not in the mapping, but are
        neighbors of nodes that are.

    T1_tilde, T2_tilde: set
        Ti_out contains all the nodes from Gi, that are neither in the mapping nor in Ti
FTc              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   )rS   r   r   s     r!   rV   "_restore_Tinout.<locals>.<genexpr>  s     :\c'>\   c              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   )rS   r   r   s     r!   rV   r     s     B\c/)\r   N)addrX   ru   )rM   rN   rD   rE   r   r   r?   r   r   r   r   r   r   r   r   is_addedr   r   r   s                    @@r!   r.   r.     s!   D )BAq!Q 	

 H$wHFF<  :R\:::JJx LL" % \"H$&HFF< BR\BBBJJx LL" % \" r#   c           
      2  ^^ Uu  pE        nUu
  mmnnn	n
nnnnSnX@    H  nUT;   a  SnUR                  U 5        M  [        U4S jUR                  U    5       5      (       d  UR                  U5        [        U4S jUU    5       5      (       d  UR                  U5        UU;  d  M  UU;  d  M  U	R                  U5        M     UR                  U     H  nUT;   a  SnUR                  U 5        M  [        U4S jUR                  U    5       5      (       d  UR                  U5        [        U4S jUU    5       5      (       d  UR                  U5        UU;   a  M  UU;   a  M  U	R                  U5        M     U(       d  U	R                  U 5        SnXQ    H  nUT;   a  SnUR                  U5        M  [        U4S jUR                  U    5       5      (       d  UR                  U5        [        U4S jUU    5       5      (       d  UR                  U5        UU;  d  M  UU;  d  M  UR                  U5        M     UR                  U    H  nUT;   a  SnUR                  U5        M  [        U4S	 jUR                  U    5       5      (       d  UR                  U5        [        U4S
 jUU    5       5      (       d  UR                  U5        UU;   a  M  UU;   a  M  UR                  U5        M     U(       d  UR                  U5        g g )NFTc              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   rS   r   r   s     r!   rV   %_restore_Tinout_Di.<locals>.<genexpr>  s     F3E4w3Er   c              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   rS   r   r   s     r!   rV   r     s     A=4w=r   c              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   r   s     r!   rV   r     s     H3G4w3Gr   c              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   r   s     r!   rV   r     s     C?4w?r   c              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   rS   r   r   s     r!   rV   r     s     N;M4.;Mr   c              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   rS   r   r   s     r!   rV   r     s     I=4.=r   c              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   r   s     r!   rV   r   )  s     P;O4.;Or   c              3   ,   >#    U  H	  oT;   v   M     g 7frR   rd   r   s     r!   rV   r   ,  s     K?4.?r   )r   rX   r   ru   )rM   rN   rD   rE   r   r   r?   r   r   r   r   r   r   r   r   r   	successorr   r   r   s                     @@r!   r0   r0     s   (BAq!Q 	

 H%	HIIl# F27793EFFF

9%A2i=AAAi("E)LL+ &" ww|,'!HFF<  H277;3GHHH

;'C2k?CCCk*2%)=[) -" \"H%	'HIIl#N2779;MNNN

9%I2i=IIIi("E)LL+ & ww|,/)HFF<  P277;;OPPP

;'K2k?KKKk*2%)=[) -  \" r#   )NN)Nr%   )__doc__collectionsnetworkxr]   __all__
namedtupler   r   _dispatchabler   r   r   r5   r4   r6   r-   r/   r:   r   r   r=   r.   r0   rd   r#   r!   <module>r      s  DL  
P))  )) " +8WX Y< +8WX Y8 +8WXs YslI&XDNL^.b3lslGTX vM#`W#r#   