§
    º³ÙgÐC  ã                   ó  — d Z ddlZddlmZmZmZmZmZ ddlm	Z	m
Z
 ddlmZmZmZmZ ddlmZmZ ddlmZmZmZmZmZmZ ddlmZ dd	lmZ dd
lmZm Z  ddl!m"Z" ddl#m$Z$  G d„ d¦  «        Z% G d„ de¦  «        Z&d„ Z'dS )z<Search for star connectivity patterns and replace them with.é    N)ÚIterableÚUnionÚOptionalÚListÚTuple)ÚfloorÚlog10)ÚSwitchCaseOpÚClbitÚClassicalRegisterÚBarrier)Úcondition_resourcesÚnode_resources)Ú	DAGOpNodeÚ
DAGDepNodeÚDAGDependencyÚ
DAGCircuitÚ
DAGOutNodeÚ	DAGInNode)ÚTransformationPass)ÚLayout)Ú_build_sabre_dagÚ_apply_sabre_result)Ústar_prerouting)ÚNLayoutc                   ó,   — e Zd ZdZdd„Zd„ Zd„ Zd„ ZdS )	Ú	StarBlockz<Defines blocks representing star-shaped pieces of a circuit.Nr   c                 ó8   — || _         || _        |€g n|| _        d S ©N)ÚcenterÚnum2qÚnodes)Úselfr"   r    r!   s       úf/granary/edev/quantum/lib/python3.11/site-packages/qiskit/transpiler/passes/routing/star_prerouting.pyÚ__init__zStarBlock.__init__'   s#   € ØˆŒØˆŒ
Ø ˜=�R�R¨eˆŒ
ˆ
ˆ
ó    c                 ó   — | j         S )z,Returns the list of nodes used in the block.©r"   ©r#   s    r$   Ú	get_nodeszStarBlock.get_nodes,   s
   € àŒzÐr&   c                 ó  — d}t          |j        ¦  «        dk    r| j                             |¦  «         d}�nG| j        €Ft          |j        ¦  «        | _        | j                             |¦  «         | xj        dz  c_        d}nút          | j        t
          ¦  «        r¦|j        d         | j        v r?|j        d         | _        | j                             |¦  «         | xj        dz  c_        d}n�|j        d         | j        v r>|j        d         | _        | j                             |¦  «         | xj        dz  c_        d}n:| j        |j        v r,| j                             |¦  «         | xj        dz  c_        d}|S )z¦
        If node can be added to block while keeping the block star-shaped, and
        return True. Otherwise, does not add node to block and returns False.
        Fé   TNr   )ÚlenÚqargsr"   Úappendr    Úsetr!   Ú
isinstance)r#   ÚnodeÚaddeds      r$   Úappend_nodezStarBlock.append_node0   se  € ð ˆåˆtŒz‰?Œ?˜aÒÐØŒJ×Ò˜dÑ#Ô#Ð#ØˆE‰EØŒ[Ð Ý˜dœj™/œ/ˆDŒKØŒJ×Ò˜dÑ#Ô#Ð#ØˆJŒJ˜!‰OˆJŒJØˆEˆEÝ˜œ¥SÑ)Ô)ð 	ØŒz˜!Œ} ¤Ð+Ð+Ø"œj¨œm�”Ø”
×!Ò! $Ñ'Ô'Ð'Ø�
”
˜a‘�
”
Ø��Ø”˜A” $¤+Ð-Ð-Ø"œj¨œm�”Ø”
×!Ò! $Ñ'Ô'Ð'Ø�
”
˜a‘�
”
Ø�øàŒ{˜dœjÐ(Ð(Ø”
×!Ò! $Ñ'Ô'Ð'Ø�
”
˜a‘�
”
Ø�àˆr&   c                 ó   — | j         S )zN
        Returns the number of two-qubit quantum gates in this block.
        )r!   r)   s    r$   ÚsizezStarBlock.sizeS   s   € ð ŒzÐr&   )NNr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r%   r*   r4   r6   © r&   r$   r   r   $   s\   € € € € € ØFÐFð4ð 4ð 4ð 4ð
ð ð ð!ð !ð !ðFð ð ð ð r&   r   c                   óæ   ‡ — e Zd ZdZˆ fd„Zd„ Zdeeee	f                  fd„Z
d„ Zd„ Zd„ Zd	„ Z	 dd„Zd„ Zdeeef         dedeee         eee         ee	         f         f         fd„Zd„ Zˆ xZS )ÚStarPreRoutinga²  Run star to linear pre-routing

    This pass is a logical optimization pass that rewrites any
    solely 2q gate star connectivity subcircuit as a linear connectivity
    equivalent with swaps.

    For example:

      .. plot::
         :alt: Circuit diagram output by the previous code.
         :include-source:

         from qiskit.circuit import QuantumCircuit
         from qiskit.transpiler.passes import StarPreRouting

         qc = QuantumCircuit(10)
         qc.h(0)
         qc.cx(0, range(1, 5))
         qc.h(9)
         qc.cx(9, range(8, 4, -1))
         qc.measure_all()
         StarPreRouting()(qc).draw("mpl")

    This pass was inspired by a similar pass described in Section IV of:
    C. Campbell et al., "Superstaq: Deep Optimization of Quantum Programs,"
    2023 IEEE International Conference on Quantum Computing and Engineering (QCE),
    Bellevue, WA, USA, 2023, pp. 1020-1032, doi: 10.1109/QCE57702.2023.00116.
    c                 ód   •— d| _         d| _        t          ¦   «                              ¦   «          dS )r=   N)Ú_pending_nodesÚ
_in_degreeÚsuperr%   )r#   Ú	__class__s    €r$   r%   zStarPreRouting.__init__x   s2   ø€ ð MQˆÔØMQˆŒÝ‰Œ×ÒÑÔÐÐÐr&   c                 óì   — g | _         i | _        |                      |¦  «        D ]O}t          |                      ||¦  «        ¦  «        }|| j        |<   |dk    r| j                              |¦  «         ŒPdS )a+  For an efficient implementation, for every node we keep the number of its
        unprocessed immediate predecessors (called ``_in_degree``). This ``_in_degree``
        is set up at the start and updated throughout the algorithm.
        A node is leaf (or input) node iff its ``_in_degree`` is 0.
        When a node is (marked as) collected, the ``_in_degree`` of each of its immediate
        successor is updated by subtracting 1.
        Additionally, ``_pending_nodes`` explicitly keeps the list of nodes whose
        ``_in_degree`` is 0.
        r   N)r?   r@   Ú	_op_nodesr-   Ú_direct_predsr/   )r#   Údagr2   Údegs       r$   Ú_setup_in_degreesz StarPreRouting._setup_in_degrees   s‚   € ð !ˆÔØˆŒØ—N’N 3Ñ'Ô'ð 	1ð 	1ˆDÝ�d×(Ò(¨¨dÑ3Ô3Ñ4Ô4ˆCØ$'ˆDŒO˜DÑ!Ø�aŠxˆxØÔ#×*Ò*¨4Ñ0Ô0Ð0øð		1ð 	1r&   Úreturnc                 ó|   — t          |t          ¦  «        s|                     ¦   «         S |                     ¦   «         S )zReturns DAG nodes.)r1   r   Úop_nodesr*   )r#   rF   s     r$   rD   zStarPreRouting._op_nodes‘   s0   € å˜#�}Ñ-Ô-ð 	#Ø—<’<‘>”>Ð!à—=’=‘?”?Ð"r&   c                 ó¸   ‡— t          ‰t          ¦  «        sd„ ‰                     |¦  «        D ¦   «         S ˆfd„‰                     |j        ¦  «        D ¦   «         S )zêReturns direct predecessors of a node. This function takes into account the
        direction of collecting blocks, that is node's predecessors when collecting
        backwards are the direct successors of a node in the DAG.
        c                 ó<   — g | ]}t          |t          ¦  «        ¯|‘ŒS r;   ©r1   r   )Ú.0Úpreds     r$   ú
<listcomp>z0StarPreRouting._direct_preds.<locals>.<listcomp>ž   s(   € Ð[Ð[Ð[˜T½zÈ$ÕPYÑ?ZÔ?ZÐ[�DÐ[Ð[Ð[r&   c                 ó:   •— g | ]}‰                      |¦  «        ‘ŒS r;   ©Úget_node)rO   Úpred_idrF   s     €r$   rQ   z0StarPreRouting._direct_preds.<locals>.<listcomp>    s%   ø€ Ð_Ð_Ð_¨g�C—L’L Ñ)Ô)Ð_Ð_Ð_r&   )r1   r   ÚpredecessorsÚdirect_predecessorsÚnode_id©r#   rF   r2   s    ` r$   rE   zStarPreRouting._direct_preds˜   sf   ø€ õ
 ˜#�}Ñ-Ô-ð 	`Ø[Ð[ S×%5Ò%5°dÑ%;Ô%;Ð[Ñ[Ô[Ð[à_Ð_Ð_Ð_¸×9PÒ9PÐQUÔQ]Ñ9^Ô9^Ð_Ñ_Ô_Ð_r&   c                 ó¸   ‡— t          ‰t          ¦  «        sd„ ‰                     |¦  «        D ¦   «         S ˆfd„‰                     |j        ¦  «        D ¦   «         S )zèReturns direct successors of a node. This function takes into account the
        direction of collecting blocks, that is node's successors when collecting
        backwards are the direct predecessors of a node in the DAG.
        c                 ó<   — g | ]}t          |t          ¦  «        ¯|‘ŒS r;   rN   )rO   Úsuccs     r$   rQ   z0StarPreRouting._direct_succs.<locals>.<listcomp>¨   s'   € ÐYÐYÐY˜T½ZÈÍiÑ=XÔ=XÐY�DÐYÐYÐYr&   c                 ó:   •— g | ]}‰                      |¦  «        ‘ŒS r;   rS   )rO   Úsucc_idrF   s     €r$   rQ   z0StarPreRouting._direct_succs.<locals>.<listcomp>ª   s%   ø€ Ð]Ð]Ð]¨g�C—L’L Ñ)Ô)Ð]Ð]Ð]r&   )r1   r   Ú
successorsÚdirect_successorsrX   rY   s    ` r$   Ú_direct_succszStarPreRouting._direct_succs¢   sb   ø€ õ
 ˜#�}Ñ-Ô-ð 	^ØYÐY S§^¢^°DÑ%9Ô%9ÐYÑYÔYÐYà]Ð]Ð]Ð]¸×9NÒ9NÈtÌ|Ñ9\Ô9\Ð]Ñ]Ô]Ð]r&   c                 ó2   — t          | j        ¦  «        dk    S )z5Returns whether there are uncollected (pending) nodesr   )r-   r?   r)   s    r$   Ú_have_uncollected_nodesz&StarPreRouting._have_uncollected_nodes¬   s   € å�4Ô&Ñ'Ô'¨!Ò+Ð+r&   c                 óz  — | j         }g | _         t          ¦   «         }|rœg }|D ]“} ||¦  «        o|                     |¦  «        }|rU|                      ||¦  «        D ]=}| j        |xx         dz  cc<   | j        |         dk    r|                     |¦  «         Œ>Œy| j                              |¦  «         Œ”|}|°œ|S )a�  Iteratively collects the largest block of input nodes (that is, nodes with
        ``_in_degree`` equal to 0) that match a given filtering function.
        Examples of this include collecting blocks of swap gates,
        blocks of linear gates (CXs and SWAPs), blocks of Clifford gates, blocks of single-qubit gates,
        blocks of two-qubit gates, etc.  Here 'iteratively' means that once a node is collected,
        the ``_in_degree`` of each of its immediate successor is decreased by 1, allowing more nodes
        to become input and to be eligible for collecting into the current block.
        Returns the block of collected nodes.
        r,   r   )r?   r   r4   ra   r@   r/   )	r#   rF   Ú	filter_fnÚunprocessed_pending_nodesÚcurrent_blockÚnew_pending_nodesr2   r3   Úsucs	            r$   Úcollect_matching_blockz%StarPreRouting.collect_matching_block°   s  € ð %)Ô$7Ð!Ø ˆÔå!™œˆð (ð 	:Ø "ÐØ1ð 	5ð 	5�Ø!˜	 $™œÐK¨M×,EÒ,EÀdÑ,KÔ,K�Øð 5à#×1Ò1°#°tÑ<Ô<ð :ð :˜Øœ¨Ð,Ð,Ô,°Ñ1Ð,Ð,Ñ,Øœ?¨3Ô/°1Ò4Ð4Ø-×4Ò4°SÑ9Ô9Ð9øð:ð
 Ô'×.Ò.¨tÑ4Ô4Ð4Ð4Ø(9Ð%ð (ð 	:ð Ðr&   é   c                 ó–  ‡— d„ Šˆfd„}|                       |¦  «         g }g }|                      ¦   «         r„|                      ||¬¦  «         |                      |‰¬¦  «        }|                     ¦   «         |k    r|                     |¦  «         |                     |¦  «         |                      ¦   «         °„d„ |D ¦   «         }||fS )a?  Collects all blocks that match a given filtering function filter_fn.
        This iteratively finds the largest block that does not match filter_fn,
        then the largest block that matches filter_fn, and so on, until no more uncollected
        nodes remain. Intuitively, finding larger blocks of non-matching nodes helps to
        find larger blocks of matching nodes later on. The option ``min_block_size``
        specifies the minimum number of gates in the block for the block to be collected.

        By default, blocks are collected in the direction from the inputs towards the outputs
        of the circuit. The option ``collect_from_back`` allows to change this direction,
        that is collect blocks from the outputs towards the inputs of the circuit.

        Returns the list of matching blocks only.
        c                 ó¾   — t          | j        ¦  «        dk    oEt          | j        ¦  «        dk    o-t          | dd¦  «        du ot	          | j        t          ¦  «         S )z8Specifies which nodes can be collected into star blocks.rk   r   Ú	conditionN)r-   r.   ÚcargsÚgetattrr1   Úopr   )r2   s    r$   re   z=StarPreRouting.collect_all_matching_blocks.<locals>.filter_fnæ   s`   € õ �D”J‘” 1Ò$ð 5Ý˜œ
‘O”O qÒ(ð5å˜D +¨tÑ4Ô4¸Ð<ð5õ # 4¤7­GÑ4Ô4Ð4ð	r&   c                 ó   •—  ‰| ¦  «         S )z"Returns the opposite of filter_fn.r;   )r2   re   s    €r$   Únot_filter_fnzAStarPreRouting.collect_all_matching_blocks.<locals>.not_filter_fnï   s   ø€ à �y ‘”Ð&Ð&r&   )re   c                 ó&   — g | ]}|j         D ]}|‘ŒŒS r;   r(   )rO   ÚpÚns      r$   rQ   z>StarPreRouting.collect_all_matching_blocks.<locals>.<listcomp>   s'   € ÐIÐIÐI !ÀÄÐIÐI¸A˜AÐIÐIÐIÐIr&   )rH   rc   rj   r6   r/   )r#   rF   Úmin_block_sizers   Úmatching_blocksÚprocessing_orderÚmatching_blockre   s          @r$   Úcollect_all_matching_blocksz*StarPreRouting.collect_all_matching_blocksÓ   s  ø€ ð&	ð 	ð 	ð	'ð 	'ð 	'ð 	'ð 	'ð
 	×Ò˜sÑ#Ô#Ð#ð ,.ˆØÐØ×*Ò*Ñ,Ô,ð 	4Ø×'Ò'¨°}Ð'ÑEÔEÐEØ!×8Ò8¸È	Ð8ÑRÔRˆNØ×"Ò"Ñ$Ô$¨Ò6Ð6Ø×&Ò& ~Ñ6Ô6Ð6Ø×#Ò# NÑ3Ô3Ð3ð ×*Ò*Ñ,Ô,ð 	4ð JÐIÐ'7ÐIÑIÔIÐàÐ 0Ð0Ð0r&   c                 óL  ‡— |                       ‰d¬¦  «        \  }}|s‰S t          d„ |D ¦   «         ¦  «        r‰S |                      ‰||¦  «        \  }}d„ t          ‰j        ¦  «        D ¦   «         }t          |¦  «        | j        d<   | j        d         €
|| j        d<   t          ˆfd„t          |¦  «        D ¦   «         ¦  «        }| j        d         x}rB|                     |                     ‰j        ‰j        ¦  «        ‰j        ¦  «        | j        d<   n
|| j        d<   |S )	Nrk   ©rw   c              3   óF   K  — | ]}|                      ¦   «         d k     V — ŒdS )é   N)r6   )rO   Úbs     r$   ú	<genexpr>z%StarPreRouting.run.<locals>.<genexpr>  s.   è è € Ð1Ð1 ˆq�vŠv‰xŒx˜!Š|Ð1Ð1Ð1Ð1Ð1Ð1r&   c                 ó   — i | ]\  }}||“Œ	S r;   r;   )rO   ÚindexÚqubits      r$   ú
<dictcomp>z&StarPreRouting.run.<locals>.<dictcomp>  s   € ÐVÐVÐV±°°u˜u eÐVÐVÐVr&   Úoriginal_layoutÚoriginal_qubit_indicesc                 ó2   •— i | ]\  }}‰j         |         |“ŒS r;   )Úqubits)rO   ÚidxÚoutrF   s      €r$   r…   z&StarPreRouting.run.<locals>.<dictcomp>  s%   ø€ Ð[Ð[Ð[±h°c¸3˜SœZ¨œ_¨cÐ[Ð[Ð[r&   Úvirtual_permutation_layout)	Ú determine_star_blocks_processingÚallÚstar_prerouteÚ	enumerater‰   r   Úproperty_setÚcomposeÚinverse)	r#   rF   Ústar_blocksry   Únew_dagÚqubit_mappingÚinput_qubit_mappingÚ
new_layoutÚcurrent_layouts	    `       r$   ÚrunzStarPreRouting.run  s\  ø€ à(,×(MÒ(MÈcÐbcÐ(MÑ(dÔ(dÑ%ˆÐ%àð 	ØˆJåÐ1Ð1 [Ð1Ñ1Ô1Ñ1Ô1ð 	ð ˆJð "&×!3Ò!3°C¸ÐFVÑ!WÔ!WÑˆ�ð WÐVÅ	È#Ì*Ñ@UÔ@UÐVÑVÔVÐÝ/5Ð6IÑ/JÔ/JˆÔÐ+Ñ,ØÔÐ5Ô6Ð>Ø:MˆDÔÐ6Ñ7åÐ[Ð[Ð[Ð[Å)ÈMÑBZÔBZÐ[Ñ[Ô[Ñ\Ô\ˆ
Ø!Ô.Ð/KÔLÐLˆ>ð 	IØ>H×>PÒ>PØ×&Ò& s¤z°3´:Ñ>Ô>ÀÄ
ñ?ô ?ˆDÔÐ:Ñ;Ð;ð ?IˆDÔÐ:Ñ;àˆr&   rF   rw   c                 ó>   — |                       ||¬¦  «        \  }}||fS )aÞ  Returns star blocks in dag and the processing order of nodes within these star blocks
        Args:
            dag (DAGCircuit or DAGDependency): a dag on which star blocks should be determined.
            min_block_size (int): minimum number of two-qubit gates in a star block.

        Returns:
            List[StarBlock]: a list of star blocks in the given dag
            Union[List[DAGOpNode], List[DAGDepNode]]: a list of operations specifying processing order
        r}   )r{   )r#   rF   rw   Úblocksry   s        r$   r�   z/StarPreRouting.determine_star_blocks_processing$  s8   € ð $(×#CÒ#CØ ð $Dñ $
ô $
Ñ ˆÐ ð Ð'Ð'Ð'r&   c                 óâ  ‡‡‡‡— t          ‰j        ¦  «        }‰j        d         }t          j        |¦  «        }d„ t          |¦  «        D ¦   «         Šˆfd„|                     ¦   «                              ¦   «         D ¦   «         }t          |||¦  «        }t          ‰|‰¦  «        \  }	}
ˆfd„|D ¦   «         }t          t          t          |¦  «        ¦  «        ¦  «        dz   Šˆfd„t          |¦  «        D ¦   «         Šˆˆfd„}t          ‰                     |¬¦  «        ‰¦  «        }t          j        |	||¦  «        �^ }}t!          ‰                     ¦   «         ‰||‰j        |
¦  «        }||fS )	a7  Returns star blocks in dag and the processing order of nodes within these star blocks
        Args:
            dag (DAGCircuit or DAGDependency): a dag on which star prerouting should be performed.
            blocks (List[StarBlock]): a list of star blocks in the given dag.
            processing_order (Union[List[DAGOpNode], List[DAGDepNode]]): a list of operations specifying
            processing order

        Returns:
            new_dag: a dag specifying the pre-routed circuit
            qubit_mapping: the final qubit mapping after pre-routing
        Úqc                 ó   — i | ]\  }}||“Œ	S r;   r;   )rO   rŠ   Úbits      r$   r…   z0StarPreRouting.star_preroute.<locals>.<dictcomp>E  s   € ÐPÐPÐP¡h c¨3˜˜cÐPÐPÐPr&   c                 ó(   •— i | ]\  }}‰|         |“ŒS r;   r;   )rO   ÚkÚvÚqubit_indicess      €r$   r…   z0StarPreRouting.star_preroute.<locals>.<dictcomp>F  s$   ø€ ÐdÐdÐd±$°!°Q˜-¨Ô*¨AÐdÐdÐdr&   c                 óf   •— g | ]-}|j         d ut          |                     ¦   «         ‰¦  «        f‘Œ.S r   )r    Ú_extract_nodesr*   )rO   ÚblockrF   s     €r$   rQ   z0StarPreRouting.star_preroute.<locals>.<listcomp>K  sF   ø€ ð 
ð 
ð 
ØSXˆUŒ\ Ð%¥~°e·o²oÑ6GÔ6GÈÑ'MÔ'MÐNð
ð 
ð 
r&   r,   c                 ó*   •— i | ]\  }}|d |d‰› �›�“ŒS )ÚaÚ0r;   )rO   rƒ   r2   Ú
int_digitss      €r$   r…   z0StarPreRouting.star_preroute.<locals>.<dictcomp>Q  s@   ø€ ð &
ð &
ð &
Ù0;°°tˆDÐ+�eÐ+˜jÐ+Ð+Ð+Ð+ð&
ð &
ð &
r&   c                 ó  •— ‰                      | d ¦  «        }|�|S t          | t          t          f¦  «        rt	          | j        ¦  «        S d                     ˆfd„t          j        | j	        | j
        ¦  «        D ¦   «         ¦  «        S )Nú,c              3   óP   •K  — | ] }‰                      |¦  «        j        d ›V — Œ!dS )Ú04dN©Úfind_bitrƒ   )rO   rž   rF   s     €r$   r�   zHStarPreRouting.star_preroute.<locals>.tie_breaker_key.<locals>.<genexpr>[  sG   øè è € ð ð Ø34�3—<’< ‘?”?Ô(Ð.Ð.ðð ð ð ð ð r&   )Úgetr1   r   r   ÚstrÚwireÚjoinÚ	itertoolsÚchainr.   ro   )r2   ry   rF   Úprocessing_order_index_maps     €€r$   Útie_breaker_keyz5StarPreRouting.star_preroute.<locals>.tie_breaker_keyU  s˜   ø€ Ø9×=Ò=¸dÀDÑIÔIÐØÐ+Ø'Ð'Ý˜$¥­JÐ 7Ñ8Ô8ð &Ý˜4œ9‘~”~Ð%Ø—8’8ð ð ð ð Ý8A¼ÈÌ
ÐTXÔT^Ñ8_Ô8_ðñ ô ñ ô ð r&   )Úkey)r-   r‰   Úqregsr   Úgenerate_trivial_layoutr�   Úget_virtual_bitsÚitemsr   r   r   r	   r¦   Útopological_op_nodesr   r�   r   Úcopy_empty_like)r#   rF   rœ   ry   Ú
num_qubitsÚcanonical_registerr™   Úlayout_mappingÚinitial_layoutÚ	sabre_dagÚcircuit_to_dag_dictÚrust_blocksr¹   Úrust_processing_orderÚsabre_resultr–   Úres_dagr«   r¸   r¤   s    `               @@@r$   r�   zStarPreRouting.star_preroute5  sÇ  øøøø€ õ ˜œ‘_”_ˆ
Ø œY sœ^ÐÝÔ7Ð8JÑKÔKˆØPÐPµ)Ð<NÑ2OÔ2OÐPÑPÔPˆØdÐdÐdÐd¸.×:YÒ:YÑ:[Ô:[×:aÒ:aÑ:cÔ:cÐdÑdÔdˆÝ  °¸ZÑHÔHˆÝ)9¸#¸zÈ=Ñ)YÔ)YÑ&ˆ	Ð&ð
ð 
ð 
ð 
Ø\bð
ñ 
ô 
ˆõ
 �5¥Ð%5Ñ!6Ô!6Ñ7Ô7Ñ8Ô8¸1Ñ<ˆ
ð&
ð &
ð &
ð &
Ý?HÐIYÑ?ZÔ?Zð&
ñ &
ô &
Ð"ð	ð 	ð 	ð 	ð 	ð 	õ !/¨s×/GÒ/GÈOÐ/GÑ/\Ô/\Ð^aÑ bÔ bÐõ (7Ô'DØ�{Ð$9ñ(
ô (
Ñ$ˆ�}õ &Ø×ÒÑ!Ô!ØØØØŒJØñ
ô 
ˆð ˜Ð%Ð%r&   )rk   )r7   r8   r9   r:   r%   rH   r   r   r   r   rD   rE   ra   rc   rj   r{   rš   r   r   Úintr   r   r   r�   r�   Ú__classcell__)rB   s   @r$   r=   r=   Z   sN  ø€ € € € € ðð ð:ð ð ð ð ð1ð 1ð 1ð$# ¨¨y¸*Ð/DÔ)EÔ Fð #ð #ð #ð #ð`ð `ð `ð^ð ^ð ^ð,ð ,ð ,ð!ð !ð !ðL ð/1ð /1ð /1ð /1ðbð ð ð@(Ø˜ ]Ð2Ô3ð(ØEHð(à	ˆt�IŒ  d¨9¤o°t¸JÔ7GÐ&GÔ HÐHÔ	Ið(ð (ð (ð (ð":&ð :&ð :&ð :&ð :&ð :&ð :&r&   r=   c                 óz  ‡— g }| D �]3}ˆfd„|j         D ¦   «         }t          ¦   «         }|j        �1|                     t	          |j        j        ¦  «        j        ¦  «         t          |j        t          ¦  «        r‰|j        j	        }t          |t          ¦  «        r|                     |¦  «         nRt          |t          ¦  «        r|                     |¦  «         n'|                     t          |¦  «        j        ¦  «         t          |j        dd¦  «        }|                     |j        |||f¦  «         �Œ5|S )a  Extract and format node information for Rust representation used in SabreDAG.

    Each node is represented as a tuple containing:
    - Node ID (int): The unique identifier of the node in the DAG.
    - Qubit indices (list of int): Indices of qubits involved in the node's operation.
    - Classical bit indices (set of int): Indices of classical bits involved in the node's operation.
    - Directive flag (bool): Indicates whether the operation is a directive (True) or not (False).

    Args:
        nodes (list[DAGOpNode]): List of DAGOpNode objects to extract information from.
        dag (DAGCircuit): DAGCircuit object containing the circuit structure.

    Returns:
        list of tuples: Each tuple contains information about a node in the format described above.
    c                 óD   •— g | ]}‰                      |¦  «        j        ‘ŒS r;   r°   )rO   r„   rF   s     €r$   rQ   z"_extract_nodes.<locals>.<listcomp>„  s(   ø€ ÐKÐKÐK°u˜Ÿš eÑ,Ô,Ô2ÐKÐKÐKr&   NÚ
_directiveF)r.   r0   rn   Úupdater   rq   Úclbitsr1   r
   Útargetr   Úaddr   r   rp   r/   Ú_node_id)r"   rF   Úextracted_node_infor2   r¤   Úclassical_bit_indicesÚswitch_case_targetÚis_directives    `      r$   r¦   r¦   r  sK  ø€ ð  ÐØð 
ñ 
ˆØKÐKÐKÐKÀÄ
ÐKÑKÔKˆÝ #¡¤ÐàŒ>Ð%Ø!×(Ò(Õ)<¸T¼WÔ=NÑ)OÔ)OÔ)VÑWÔWÐWå�d”g�|Ñ,Ô,ð 	XØ!%¤¤ÐÝÐ,­eÑ4Ô4ð XØ%×)Ò)Ð*<Ñ=Ô=Ð=Ð=ÝÐ.Õ0AÑBÔBð XØ%×,Ò,Ð-?Ñ@Ô@Ð@Ð@à%×,Ò,­^Ð<NÑ-OÔ-OÔ-VÑWÔWÐWå˜tœw¨°eÑ<Ô<ˆØ×"Ò"ØŒ]˜MÐ+@À,ÐOñ	
ô 	
ð 	
ñ 	
ð Ðr&   )(r:   r¶   Útypingr   r   r   r   r   Úmathr   r	   Úqiskit.circuitr
   r   r   r   Úqiskit.circuit.controlflowr   r   Úqiskit.dagcircuitr   r   r   r   r   r   Úqiskit.transpiler.basepassesr   Úqiskit.transpiler.layoutr   Ú+qiskit.transpiler.passes.routing.sabre_swapr   r   Úqiskit._accelerater   Úqiskit._accelerate.nlayoutr   r   r=   r¦   r;   r&   r$   ú<module>rã      sÀ  ðð CÐ BØ Ð Ð Ð Ø 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ø Ð Ð Ð Ð Ð Ð Ð à JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JØ JÐ JÐ JÐ JÐ JÐ JÐ JÐ Jðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð <Ð ;Ð ;Ð ;Ð ;Ð ;Ø +Ð +Ð +Ð +Ð +Ð +Ø ]Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]à .Ð .Ð .Ð .Ð .Ð .Ø .Ð .Ð .Ð .Ð .Ð .ð3ð 3ð 3ð 3ð 3ñ 3ô 3ð 3ðlU&ð U&ð U&ð U&ð U&Ð'ñ U&ô U&ð U&ðp&ð &ð &ð &ð &r&   