Ë
    D^(hEŽ  ã                   óx  — d Z ddlZddlZg d¢Z ej
                  dg d¢«      Z ej
                  dg d¢«      Z ej                  ddd	œd
di¬«      dd„«       Z	 ej                  ddd	œd
di¬«      dd„«       Z
 ej                  ddd	œd
di¬«      dd„«       Zd„ Zdd„Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zy)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                 óT   — 	 t        t        | |||«      «      }|S # t        $ r Y yw xY w)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        úc/var/www/skyplay_api_hub/venv/lib/python3.12/site-packages/networkx/algorithms/isomorphism/vf2pp.pyr   r   k   s4   € ð0ÜÔ-¨b°"°jÀ-ÓPÓQˆØˆøÜò Ùðús   ‚ ›	'¦'c                 ó"   — t        | |||«      �yy)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 ˜˜R ¨]Ó;ÐGØØó    c           	   #   óæ  K  — | j                  «       dk(  s|j                  «       dk(  ry| j                  «       rt        | j                  | j                  «      D ����ci c]  \  \  }}\  }}|||f“Œ }}}}}t        |j                  |j                  «      D ����ci c]  \  \  }}\  }}|||f“Œ }	}}}}n*t        | j                  «      }t        |j                  «      }	| j                  «       st        }
t        }nt        }
t        }| j                  «       |j                  «       k7  ryt        |j                  «       «      t        |	j                  «       «      k7  ryt        | ||	||«      \  }}t        |«      syt!        |«      }g }t#         |
|d   |||«      «      }|j%                  |d   |f«       |j&                  }|j(                  }d}|r©|d   \  }}	 t+        |«      }t1        ||||«      rƒt3        |«      |j                  «       dz
  k(  r|j5                  «       }|||<   |–— Œ]|||<   |||<   t7        ||||«       t#         |
||   |||«      «      }|j%                  ||   |f«       |dz  }|rŒ¨yyc c}}}}w c c}}}}w # t,        $ rU |j/                  «        |dz  }|r:|d   \  }}||   }|j/                  |«       |j/                  |«        |||||«       Y �Œw xY w­w)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Ó$8¸AÒ$=Øð 
‡~�~Ôô 47°r·|±|ÀRÇ]Á]Ó3S÷
ñ 
á/‘��I¡  Jð �	˜:Ð&Ñ&ð
ˆ	ó 
ô 47°r·|±|ÀRÇ]Á]Ó3S÷
ñ 
á/‘��I¡  Jð �	˜:Ð&Ñ&ð
ˆ	ô 
ô
 ˜Ÿ™“Oˆ	Ü˜Ÿ™“Oˆ	à�>‰>ÔÜ*ˆÜ(‰ä-ˆÜ+ˆð 
‡x�xƒz�R—X‘X“ZÒØÜˆi×ÑÓ Ó!¤V¨I×,<Ñ,<Ó,>Ó%?Ò?Øô "8Ø
ˆB�	˜: }ó"Ñ€L�,ô
 & lÔ3Øô ! Ó.€Jð €EÜÙ˜
 1™ |°\À9ÓMó€Jð 
‡L�L�*˜Q‘- Ð,Ô-à×"Ñ"€GØ"×2Ñ2€Oð €Má
Ø(-¨b©	Ñ%ˆ�oð	Ü˜_Ó-ˆIô ˜ i°¸|ÔLä�7‹|˜r×1Ñ1Ó3°aÑ7Ò7Ø$Ÿ\™\›^�
Ø+4�
˜<Ñ(Ø Ò Øð %.ˆG�LÑ!Ø)5ˆO˜IÑ&Ü˜<¨°LÀ,ÔOäÙØ˜}Ñ-¨|¸\È9óóˆJð
 �L‰L˜* ]Ñ3°ZÐ@ÔAØ˜QÑˆMôK ùõe
ùõ
øôf ò 	à�I‰IŒKØ˜QÑˆMÙà"'¨¡)‘�˜aØ& |Ñ4�Ø—‘˜LÔ)Ø×#Ñ# LÔ1Ù˜|¨\¸<ÈÔVÚð	üsK   ‚AK1ÁJ 
Á4*K1ÂJ
Â3D+K1ÇJ Ç*BK1É>K1ÊAK.Ë*K1Ë-K.Ë.K1c                 ó`   ‡— | \  }}}}Š}}t        ˆfd„|j                  «       D «       «      ryy)Nc              3   ód   •K  — | ]'  \  }}|‰vxs t        ‰|   «      t        |«      k7  –— Œ) y ­w©N)r;   )Ú.0ÚlabelÚnodesr   s      €r!   ú	<genexpr>z-_precheck_label_properties.<locals>.<genexpr>   s?   øè ø€ ò áˆE�5ð 	Ð&Ð&ÒU¬#Ð.?ÀÑ.FÓ*GÌ3ÈuË:Ñ*UÓUñùs   ƒ-0FT)ÚanyÚitems)rD   r   r   r	   r
   r   r?   r   s          @r!   r5   r5     s?   ø€ ØLXÑI€BˆˆI�yÐ"3Ð5FÈÜ
ó à-×3Ñ3Ó5ôô ð Ør#   c                 óü  — t        | j                  ||¬«      «      }t        |j                  ||¬«      «      }t        | |||t        j                  j                  |«      t        j                  j                  |«      t        j                  j                  |«      «      }t        «       t        «       }	}t        «       t        «       }}
| j                  «       rGt        | j                  «       «      t        «       }}t        |j                  «       «      t        «       }}nFt        | j                  «       «      t        «       }}t        |j                  «       «      t        «       }}t        i i ||	|||
|||«
      }||fS )a6  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 �R—X‘X :°}�XÓEÓF€IÜ�R—X‘X :°}�XÓEÓF€Iä#Ø
Ø
ØØÜ
�‰�‰˜	Ó"Ü
�‰�‰˜	Ó"Ü
�‰�‰˜	Ó"ó€Lô “”s“uˆ€BÜ“”s“uˆ€BØ	‡~�~Ôä�—‘“
‹OÜ‹Eð ˆô !$ B§H¡H£J£´³�+‰ä # B§H¡H£J£´³�+ˆÜ # B§H¡H£J£´³�+ˆä#Ø
Ø
Ø
ØØØØ
ØØØó€Lð ˜Ð%Ð%r#   c                 ó  ‡‡‡‡— | \  Š}Š}}}}‰s|si S ‰j                  «       r‰j                  d¬«      Št        ‰j                  «       «      }|j	                  «       D ��ci c]  \  }}|t        |«      “Œ c}}Š‰D �ci c]  }|d“Œ c}Šg }|�rUt        ˆˆfd„|D «       «      }	|D �
cg c]  }
‰‰|
      |	k(  sŒ|
‘Œ }}
t        |‰j                  ¬«      }t        j                  ‰|«      D ]ñ  }|j                  «       }|sŒt        ˆfd„|D «       «      }|D �
cg c]  }
‰|
   |k(  sŒ|
‘Œ }}
t        ˆfd„|D «       «      }|D �
cg c]  }
‰j                  |
   |k(  sŒ|
‘Œ }}
t        |ˆˆfd„¬«      }|j                  |«       ‰j                  |«      D ]  }‰|xx   d	z  cc<   Œ |j                  |«       ‰‰|   xx   d	z  cc<   |j                  |«       |rŒÜŒó |r�ŒU|S c c}}w c c}w c c}
w c c}
w c c}
w )
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   ó.   •K  — | ]  }‰‰|      –— Œ y ­wrR   © )rS   Úxr	   Úlabel_raritys     €€r!   rV   z"_matching_order.<locals>.<genexpr>›  s   øè ø€ ÒJ¸˜ i°¡lÕ3ÑJùs   ƒ)Úkeyc              3   ó(   •K  — | ]	  }‰|   –— Œ y ­wrR   rc   )rS   r>   Úused_degreess     €r!   rV   z"_matching_order.<locals>.<genexpr>¤  s   øè ø€ Ò%L¸! l°1¥oÑ%Lùs   ƒc              3   ó<   •K  — | ]  }‰j                   |   –— Œ y ­wrR   )r,   )rS   r>   r   s     €r!   rV   z"_matching_order.<locals>.<genexpr>¨  s   øè ø€ Ò M°! §¡¨1¥Ñ Mùs   ƒc                 ó   •— ‰‰|       S rR   rc   )rd   r	   re   s    €€r!   ú<lambda>z!_matching_order.<locals>.<lambda>­  s   ø€ °LÀÈ1ÁÑ4N€ r#   r   )r'   Úto_undirectedr_   rU   rX   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	   re   rh   s                       @@@@r!   r6   r6   t  s%  û€ ð4 5AÑ1€BˆˆI�q˜!Ð.°Ù‘bØˆ	à	‡~�~ÔØ×Ñ dÐÓ+ˆä�r—x‘x“z“?€LØ:K×:QÑ:QÓ:S×T©,¨%°�Eœ3˜u›:Ñ%ÓT€LØ(*Ö+ �D˜!‘GÒ+€LØ€Jâ
ÜÔJ¸\ÔJÓJˆ
à#ö
Ø |°I¸a±LÑ'AÀZÓ'OŠAð
ˆð 
ô �|¨¯©Ô3ˆäŸM™M¨"¨hÓ7ò 	0ˆLØ'×,Ñ,Ó.ˆLÚÜ"%Ó%L¸|Ô%LÓ"L�à+ö)Ø¨|¸A©À/Ó/Q’Að)Ð%ð )ô !Ó MÐ7LÔ MÓM�
à4ö$Ø¸¿	¹	À!¹È
Ó8R’Að$Ð ð $ô  Ø$Ô*Nô�	ð ×!Ñ! )Ô,ØŸL™L¨Ó3ò ,�DØ  Ó&¨!Ñ+Ô&ð,ð ×#Ñ# IÔ.Ø˜Y yÑ1Ó2°aÑ7Ó2Ø×$Ñ$ YÔ/ó' ð	0ó ð< ÐùóE UùÚ+ùò

ùò)ùò$s0   Á#G*Â
G0Â,G5Â=G5ÄG:Ä,G:Å
G?Å"G?c           
      óX  — |\  }}}}}}}	|\
  }
}}}}}}}}}||    D �cg c]	  }||
v sŒ|‘Œ }}|s t        |||       «      }|j                  |	||       «       |j                  |«       |j                  |«       |j                  «       rD|j                  |D �ch c])  }|j	                  | | «      |j	                  ||«      k7  r|’Œ+ c}«       |S |d   }t        ||
|      «      }|dd D ]  }|j                  ||
|      «       Œ |j                  |«       |j                  |	||       «       |j                  |||       «       |j                  «       rD|j                  |D �ch c])  }|j	                  | | «      |j	                  ||«      k7  r|’Œ+ c}«       |S c c}w c c}w c c}w )aÀ  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   rt   Únbr1Úcommon_nodess                      r!   r-   r-   »  sð  € ðP FRÑB€BˆˆI�q˜!Ð.Ð0BØ>JÑ;€Gˆ_˜a  A q¨!¨Q°¸!à#% a¡5Ö;˜C¨C°7ªN’CÐ;€LÐ;ÙÜÐ*¨9°Q©<Ñ8Ó9ˆ
Ø×&Ñ&Ð'9¸)ÀA¹,Ñ'GÔHØ×&Ñ& xÔ0Ø×$Ñ$ _Ô5Ø×ÑÔØ×(Ñ(ð !+öàØ×)Ñ)¨!¨QÓ/°2×3EÑ3EÀdÈDÓ3QÒQò òôð Ðà˜‰?€DÜ�r˜' $™-Ñ(Ó)€Là˜Q˜RÐ ò <ˆØ×(Ñ(¨¨G°D©MÑ):Õ;ð<ð ×"Ñ" ?Ô3Ø×$Ñ$Ð%7¸	À!¹Ñ%EÔFØ×$Ñ$Ð%6°yÀ±|Ñ%DÔEØ	×ÑÔØ×&Ñ&ð )öàØ×%Ñ% a¨Ó+¨r×/AÑ/AÀ$ÈÓ/MÒMò òô	
ð ÐùòC <ùòùò&s   Ÿ	F©FÂ.F"Å&.F'c           
      óT  — |\  }}}}}}}	|\
  }
}}}}}}}}}||    D �cg c]	  }||
v sŒ|‘Œ }}|j                   |    D �cg c]	  }||
v sŒ|‘Œ }}|s¢|s t        |||       «      }|j                  |	||       «       |j                  |«       |j                  |«       |j	                  «       rD|j                  |D �ch c])  }|j                  | | «      |j                  ||«      k7  r|’Œ+ c}«       |S |rL|d   }t        |j                   |
|      «      }|dd  D ]#  }|j                  |j                   |
|      «       Œ% n!|j                  «       }t        ||
|      «      }|D ]  }|j                  ||
|      «       Œ |j                  |«       |j                  |	||       «       |j                  |||       «       |j	                  «       rD|j                  |D �ch c])  }|j                  | | «      |j                  ||«      k7  r|’Œ+ c}«       |S c c}w c c}w c c}w c c}w )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   rt   Úsucc1rˆ   Úpred1s                         r!   r/   r/   
  sl  € ØEQÑB€BˆˆI�q˜!Ð.Ð0BØ>JÑ;€Gˆ_˜a  A q¨!¨Q°¸!à+-¨a©5ÖD 4°D¸G²Oš$ÐDÐÐDØ-/¯W©W°Q©ZÖK T¸4À7º?šDÐKÐÐKáÑ"6ÜÐ*¨9°Q©<Ñ8Ó9ˆ
Ø×&Ñ&Ð'9¸)ÀA¹,Ñ'GÔHØ×&Ñ& xÔ0Ø×$Ñ$ _Ô5Ø×ÑÔØ×(Ñ(ð !+öàØ×)Ñ)¨!¨QÓ/°2×3EÑ3EÀdÈDÓ3QÒQò òôð ÐáØ" 1Ñ%ˆÜ˜2Ÿ7™7 7¨5¡>Ñ2Ó3ˆà'¨¨Ð+ò 	FˆEØ×,Ñ,¨R¯W©W°W¸U±^Ñ-DÕEñ	Fð %×(Ñ(Ó*ˆÜ˜2˜g e™nÑ-Ó.ˆà%ò =ˆØ×(Ñ(¨¨G°E©NÑ);Õ<ð=ð ×"Ñ" ?Ô3Ø×$Ñ$Ð%7¸	À!¹Ñ%EÔFØ×$Ñ$Ð%6°yÀ±|Ñ%DÔEØ	×ÑÔØ×&Ñ&ð )öàØ×%Ñ% a¨Ó+¨r×/AÑ/AÀ$ÈÓ/MÒMò òô	
ð ÐùòU EùÚKùòùò4s"   Ÿ	H©HÁ 	HÁ
HÂ=.H Ç.H%c                 óx   — |j                   }t        | |||«      ry|j                  «       rt        | |||«      syy)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�e˜\¨<Ô8Øà	×ÑÔÜ˜e U¨L¸,ÔGØàr#   c           
      óÖ  ‡ ‡‡‡— |\  ŠŠ}}}}}|\
  }}}}}	}}
}}}i i }}‰j                  «       r°t        j                  j                  ‰j                  ‰    D �ci c]  }|||   “Œ
 c}«      }t        j                  j                  ‰j                  ‰   D �ci c]  }|||   “Œ
 c}«      }t        |j                  «       «      t        |j                  «       «      k7  ryt        j                  j                  ‰‰    D �ci c]  }|||   “Œ
 c}«      }t        j                  j                  ‰‰   D �ci c]  }|||   “Œ
 c}«      }t        |j                  «       «      t        |j                  «       «      k7  ry|j                  «       D �]  \  }}||   }‰j                  «       rHt        ˆˆ fd„|D «       «      }t        ˆˆfd„|D «       «      }t        d„ t        ||«      D «       «      r yt        |j                  |«      «      t        |
j                  |«      «      k7  r yt        |	j                  |«      «      t        |j                  |«      «      k7  r y‰j                  «       sŒãt        |j                  |«      «      t        |j                  |«      «      k7  s�Œ y ‰j                  «       sy|j                  «       D �]  \  }}||   }‰j                  «       rHt        ˆˆ fd„|D «       «      }t        ˆˆfd„|D «       «      }t        d„ t        ||«      D «       «      r yt        |j                  |«      «      t        |
j                  |«      «      k7  r yt        |	j                  |«      «      t        |j                  |«      «      k7  r yt        |j                  |«      «      t        |j                  |«      «      k7  s�Œ	 y yc c}w c c}w c c}w c c}w )	aÇ  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   óB   •K  — | ]  }‰j                  ‰|«      –— Œ y ­wrR   ©rƒ   ©rS   rd   r   r„   s     €€r!   rV   z_cut_PT.<locals>.<genexpr>¼  ó   øè ø€ Ò!K¸q "×"4Ñ"4°Q¸×":Ñ!Kùó   ƒc              3   óB   •K  — | ]  }‰j                  ‰|«      –— Œ y ­wrR   r—   ©rS   rd   r   Úvs     €€r!   rV   z_cut_PT.<locals>.<genexpr>½  r™   rš   c              3   ó,   K  — | ]  \  }}||k7  –— Œ y ­wrR   rc   ©rS   Úu_nbr_edgesÚv_nbr_edgess      r!   rV   z_cut_PT.<locals>.<genexpr>¾  ó!   è ø€ ò á,�K ð ˜{Õ*ñùó   ‚Fc              3   óB   •K  — | ]  }‰j                  ‰|«      –— Œ y ­wrR   r—   r˜   s     €€r!   rV   z_cut_PT.<locals>.<genexpr>Õ  ó   øè ø€ Ò!L¸q "×"4Ñ"4°Q¸×":Ñ!Lùrš   c              3   óB   •K  — | ]  }‰j                  ‰|«      –— Œ y ­wrR   r—   rœ   s     €€r!   rV   z_cut_PT.<locals>.<genexpr>Ö  r¥   rš   c              3   ó,   K  — | ]  \  }}||k7  –— Œ y ­wrR   rc   rŸ   s      r!   rV   z_cut_PT.<locals>.<genexpr>×  r¢   r£   )r'   r\   r]   r^   rŠ   r_   ÚkeysrX   r‚   r2   rW   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�y ! Q¨ð 	ñØ	Ø	Ø
ØØØ	Ø
ØØØ	ð 46°rÐ0ÐØ	‡~�~ÔÜ "§¡§¡Ø)+¯©°©Ö4 2ˆR�˜2‘ÑÒ4ó!
Ðô !#§¡§¡Ø)+¯©°©Ö4 2ˆR�˜2‘ÑÒ4ó!
Ðô Ð$×)Ñ)Ó+Ó,´Ð4I×4NÑ4NÓ4PÓ0QÒQØäŸ(™(Ÿ/™/ÀrÈ!ÁuÖ*MÀ¨2¨y¸©}Ñ+<Ò*MÓNÐÜŸ(™(Ÿ/™/ÀrÈ!ÁuÖ*MÀ¨2¨y¸©}Ñ+<Ò*MÓNÐô Ð×#Ñ#Ó%Ó&¬#Ð.A×.FÑ.FÓ.HÓ*IÒIØà,×2Ñ2Ó4ó ‰ˆˆvØ$ UÑ+ˆà×ÑÔä!Ô!KÀFÔ!KÓKˆLÜ!Ô!KÀFÔ!KÓKˆLÜñ ä03°LÀ,Ó0Oôô ñ äˆr�‰˜vÓ&Ó'¬3¨r¯©¸vÓ/FÓ+GÒGÙÜˆx×$Ñ$ VÓ,Ó-´°X×5JÑ5JÈ6Ó5RÓ1SÒSÙØ�>‰>Õ¤ E×$6Ñ$6°vÓ$>Ó ?Ä3Ø×Ñ˜vÓ&óD
ô !
ñ ð)ð, �>‰>ÔØà/×5Ñ5Ó7ó ‰ˆˆwØ'¨Ñ.ˆà×ÑÔä!Ô!LÀGÔ!LÓLˆLÜ!Ô!LÀGÔ!LÓLˆLÜñ ä03°LÀ,Ó0Oôô ñ äˆr�‰˜wÓ'Ó(¬C°·±ÀÓ0HÓ,IÒIÙÜˆx×$Ñ$ WÓ-Ó.´#°h×6KÑ6KÈGÓ6TÓ2UÒUÙÜˆu×!Ñ! 'Ó*Ó+¬s°5×3EÑ3EÀgÓ3NÓ/OÔOÙð%ð( ùò{ 5ùò 5ùò +NùÚ*Ms   ÁOÂOÄ O!Ä4O&c                 óv  — |j                   |j                  }}|j                  |j                  }}||    D ]1  }||v sŒ|j	                  | |«      |j	                  |||   «      k7  sŒ1 y ||   D ]1  }||v sŒ|j	                  | ||   «      |j	                  ||«      k7  sŒ1 y |j                  «       sy|j                  |    D ]1  }	|	|v sŒ|j	                  |	| «      |j	                  ||	   |«      k7  sŒ1 y |j                  |   D ]1  }	|	|v sŒ|j	                  ||	   | «      |j	                  |	|«      k7  sŒ1 y y)aÌ  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’   ç  s}  € ðJ �_‰_˜lŸo™oˆ€BØ+×3Ñ3°\×5QÑ5Qˆ_€Gà�q‘Eò ˆØ�wÒØ×!Ñ! ! XÓ.°"×2DÑ2DØ�7˜8Ñ$ó3ó ñ ðð �q‘Eò ˆØ�Ò&Ø×!Ñ! ! _°XÑ%>Ó?À2×CUÑCUØ�8óDó ñ ðð �>‰>ÔØà—w‘w˜q‘zò ˆØ˜'Ò!Ø×!Ñ! +¨qÓ1°R×5GÑ5GØ˜Ñ$ aó6ó ñ ðð —w‘w˜q‘zò ˆØ˜/Ò)Ø×!Ñ!Ø Ñ,¨aóà×#Ñ# K°Ó3ó4ñ ðð r#   c           
      ó|  — |\  }}}}}}}|\
  }}}	}
}}}}}}||    D �ch c]	  }||vsŒ|’Œ }}||   D �ch c]	  }||vsŒ|’Œ }}|	j                  |«       |j                  |«       |	j                  | «       |j                  |«       |j                  |«       |j                  |«       |j                  | «       |j                  |«       |j                  «       sy|j                  |    D �ch c]	  }||vsŒ|’Œ }}|j                  |   D �ch c]	  }||vsŒ|’Œ }}|
j                  |«       |j                  |«       |
j                  | «       |j                  |«       |j                  |«       |j                  |«       |j                  | «       |j                  |«       yc c}w c c}w c c}w c c}w )aK  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)Úupdaterr   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 )Ñ€BˆˆAˆq�!�Q˜ð 	ñØØØ
ØØØØ
ØØØð 13°9±ÖU¨ÀÈWÒATštÐUÐÐUà˜I™öØ¨$°oÒ*EŠðÐð ð
 ‡I�IÐ%Ô&Ø‡I�IÐ%Ô&Ø‡J�JˆyÔØ‡J�JˆyÔà×ÑÐ6Ô7Ø×ÑÐ6Ô7Ø×Ñ�YÔØ×Ñ�YÔà�>‰>ÔØð Ÿ™ Ñ+ö!Ø¨t¸7Ò/BŠð!Ðð !ð Ÿ™ Ñ+ö!Ø¨t¸?Ò/JŠð!Ðð !ð 
‡L�LÐ*Ô+Ø	‡L�LÐ*Ô+Ø	‡M�M�)ÔØ	‡M�M�)Ôà×ÑÐ8Ô9Ø×ÑÐ8Ô9Ø×Ñ�YÔØ×Ñ�YÕùòE Vùòùò$!ùò!s-   Ÿ	F*©F*¶	F/Á F/Ã0	F4Ã:F4Ä	F9ÄF9c           
      óü  ‡‡— |\  }}}}}}}|\
  ŠŠ}}}	}
}}}}d}||    D ]T  }|‰v rd}|j                  | «       Œt        ˆfd„||   D «       «      rŒ3|j                  |«       |	j                  |«       ŒV |s|	j                  | «       d}||   D ]T  }|‰v rd}|j                  |«       Œt        ˆfd„||   D «       «      rŒ3|j                  |«       |j                  |«       ŒV |s|j                  |«       yy)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   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   )rS   r…   r   s     €r!   rV   z"_restore_Tinout.<locals>.<genexpr>Ä  s   øè ø€ Ò: c�3˜'”>Ñ:ùó   ƒc              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   )rS   r…   r   s     €r!   rV   z"_restore_Tinout.<locals>.<genexpr>Ó  s   øè ø€ ÒB¨c�3˜/Ô)ÑBùrÅ   N)ÚaddrW   rr   )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 )Ñ€BˆˆAˆq�!�Q˜ð 	ñØØØ
ØØØØ
ØØØð €HØ�|Ñ$ò 
#ˆØ�wÑàˆHØ�F‰F�<Õ ô Ó:¨R°©\Ô:Ô:ØØ�J‰J�xÔ Ø�L‰L˜Õ"ð
#ñ Ø�‰�\Ô"à€HØ�|Ñ$ò #ˆØ�Ñ&ØˆHØ�F‰F�<Õ äÓB°R¸±\ÔBÔBØØ�J‰J�xÔ Ø�L‰L˜Õ"ð#ñ Ø�‰�\Õ"ð r#   c           
      ól  ‡‡— |\  }}}}}}}|\
  ŠŠ}}}	}
}}}}d}||    D ]�  }|‰v rd}|j                  | «       Œt        ˆfd„|j                  |   D «       «      s|j                  |«       t        ˆfd„||   D «       «      s|j                  |«       ||vsŒz||vsŒ|	j                  |«       Œ‘ |j                  |    D ]�  }|‰v rd}|j                  | «       Œt        ˆfd„|j                  |   D «       «      s|j                  |«       t        ˆfd„||   D «       «      s|j                  |«       ||v rŒz||v rŒ|	j                  |«       Œ‘ |s|	j                  | «       d}||   D ]�  }|‰v rd}|j                  |«       Œt        ˆfd„|j                  |   D «       «      s|j                  |«       t        ˆfd„||   D «       «      s|j                  |«       ||vsŒz||vsŒ|j                  |«       Œ‘ |j                  |   D ]�  }|‰v rd}|j                  |«       Œt        ˆfd	„|j                  |   D «       «      s|j                  |«       t        ˆfd
„||   D «       «      s|j                  |«       ||v rŒz||v rŒ|j                  |«       Œ‘ |s|j                  |«       y y )NFTc              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   ©rS   rŠ   r   s     €r!   rV   z%_restore_Tinout_Di.<locals>.<genexpr>ô  s   øè ø€ ÒF¨4�t˜w”ÑFùrÅ   c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   ©rS   r‹   r   s     €r!   rV   z%_restore_Tinout_Di.<locals>.<genexpr>÷  s   øè ø€ ÒA¨4�t˜w”ÑAùrÅ   c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   rË   s     €r!   rV   z%_restore_Tinout_Di.<locals>.<genexpr>  s   øè ø€ ÒH¨4�t˜w”ÑHùrÅ   c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   rÍ   s     €r!   rV   z%_restore_Tinout_Di.<locals>.<genexpr>  s   øè ø€ ÒC¨4�t˜w”ÑCùrÅ   c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   ©rS   rŠ   r   s     €r!   rV   z%_restore_Tinout_Di.<locals>.<genexpr>  s   øè ø€ ÒN°4�t˜Ô.ÑNùrÅ   c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   ©rS   r‹   r   s     €r!   rV   z%_restore_Tinout_Di.<locals>.<genexpr>  s   øè ø€ ÒI°4�t˜Ô.ÑIùrÅ   c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   rÑ   s     €r!   rV   z%_restore_Tinout_Di.<locals>.<genexpr>)  s   øè ø€ ÒP°4�t˜Ô.ÑPùrÅ   c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrR   rc   rÓ   s     €r!   rV   z%_restore_Tinout_Di.<locals>.<genexpr>,  s   øè ø€ ÒK°4�t˜Ô.ÑKùrÅ   )rÇ   rW   rŠ   rr   )rM   rN   rD   rE   r   r   r?   r   r   r   r   r   r   r   r   rÈ   Ú	successorrº   r   r   s                     @@r!   r0   r0   Ü  sª  ù€ à(Ñ€BˆˆAˆq�!�Q˜ð 	ñØØØ
ØØØØ
ØØØð €HØ˜Ñ%ò ,ˆ	Ø˜ÑàˆHØ�I‰I�lÕ#ô ÓF°2·7±7¸9Ñ3EÔFÔFØ—
‘
˜9Ô%äÓA°2°i±=ÔAÔAØ—‘˜iÔ(à Ò"Ø EÒ)Ø—L‘L Õ+ð,ð" —w‘w˜|Ñ,ò *ˆØ˜'Ñ!àˆHØ�F‰F�<Õ ô ÓH°2·7±7¸;Ñ3GÔHÔHØ—
‘
˜;Ô'äÓC°2°k±?ÔCÔCØ—‘˜kÔ*à 2Ò%¨¸Ò)=Ø—‘˜[Õ)ð*ñ" Ø�‰�\Ô"à€HØ˜Ñ%ò ,ˆ	Ø˜Ñ'ØˆHØ�I‰I�lÕ#äÓN¸2¿7¹7À9Ñ;MÔNÔNØ—
‘
˜9Ô%äÓI¸2¸i¹=ÔIÔIØ—‘˜iÔ(à Ò"Ø EÒ)Ø—L‘L Õ+ð,ð —w‘w˜|Ñ,ò *ˆØ˜/Ñ)àˆHØ�F‰F�<Õ ô ÓP¸2¿7¹7À;Ñ;OÔPÔPØ—
‘
˜;Ô'äÓK¸2¸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   rc   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#   