
    z	i6(                         S r SSKJr  SSKrSSKJr  SSKJr  SSKJr  SSK	J
r
Jr  SSKJr  SS	KJr  SS
KJr  \R"                  " \5      r\SS// SQ4\
SS// SQ40r  " S S\5      rS rg)zKReduce 1Q gate complexity by commuting through 2Q gates and resynthesizing.    )copyN)deque)
DAGCircuit)QuantumRegister)CXGateRZXGate)	DAGOpNode)TransformationPass)Optimize1qGatesDecompositionrzp)xsxrxc                   z   ^  \ rS rSrSrSU 4S jjr\SS j5       r\SS j5       rS r	\S 5       r
S rS	 rS
rU =r$ ) Optimize1qGatesSimpleCommutation/   a  
Optimizes 1Q gate strings interrupted by 2Q gates by commuting the components and
resynthesizing the results.  The commutation rules are stored in ``commutation_table``.

NOTE: In addition to those mentioned in ``commutation_table``, this pass has some limitations:
      + Does not handle multiple commutations in a row without intermediate progress.
      + Can only commute into positions where there are pre-existing runs.
      + Does not exhaustively test all the different ways commuting gates can be assigned to
        either side of a barrier to try to find low-depth configurations.  (This is particularly
        evident if all the gates in a run commute with both the predecessor and the successor
        barriers.)
c                 J   > [         TU ]  5         [        XS9U l        X l        g)a  
Args:
    basis (List[str]): See also `Optimize1qGatesDecomposition`.
    run_to_completion (bool): If `True`, this pass retries until it is unable to do any more
        work.  If `False`, it finds and performs one optimization, and for full optimization
        the user is obligated to re-call the pass until the output stabilizes.
    target (Target): The :class:`~.Target` representing the target backend, if both
        ``basis`` and this are specified then this argument will take
        precedence and ``basis`` will be ignored.
)basistargetN)super__init__r   _optimize1q_run_to_completion)selfr   run_to_completionr   	__class__s       w/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/transpiler/passes/optimization/optimize_1q_commutation.pyr   )Optimize1qGatesSimpleCommutation.__init__@   s#     	7eS"3    c                    U(       a  US   OUS   n[        U(       a  U R                  U5      OU R                  U5      5      nU(       a  U R                  U5      OU R                  U5      n/ nU H|  n[        U[        5      (       d  M  UR
                  UR
                  :X  d  M6  / nU H<  n	[        U	5      S:w  d  M  U	S   R
                  UR
                  :X  d  M3  X;   d  M:  U	n  O     XW4$    XW4$ )a  
Finds the run which abuts `run` from the front (or the rear if `front == False`), separated
by a blocking node.

Returns a pair of the abutting multiqubit gate and the run which it separates from this
one. The next run can be the empty list `[]` if it is absent.
r   )nextpredecessors
successors
isinstancer	   qargslen)
dagrunsrunfront	edge_nodeblockerpossibilitiesadjoining_runpossibility
single_runs
             r   _find_adjoining_run4Optimize1qGatesSimpleCommutation._find_adjoining_runP   s     $CFR	es''	2PYAZ[5:((1w@W(K+y11k6G6G9??6Z ""&JJ1,A1D1DHYHY1Y&4,6M! #' '' ) ''r    c                    U/ :X  a  / / 4$ [        U5      n[        / 5      nSu  pV[        U [        5      (       a  Sn[        U R                  5       H  u  pxXS   R                  S   :X  d  M  UnM      SnUbS  [        U [        5      (       a>  U R
                  R                  [        ;   a   [        U R
                  R                     U   nUb|  U(       au  U(       a  US   OUS   n	U	R                  U;  a  OSU(       a"  UR                  5         UR                  U	5        O!UR                  5         UR                  U	5        U(       a  Mu  U(       a  [        U5      [        U5      4$ [        U5      [        U5      4$ )z
Pulls `DAGOpNode`s from the front of `run` (or the back, if `front == False`) until it
encounters a gate which does not commute with `blocker`.

Returns a pair of lists whose concatenation is `run`.
)NNNr   r"   )r   r&   r	   	enumerater'   op
base_classcommutation_tablenamepopleftappendpop
appendleftlist)
r.   r+   r,   	run_clonecommutedpreindexcommutation_ruleiq	next_gates
             r   _commute_through1Optimize1qGatesSimpleCommutation._commute_throughk   sD    "9r6M #J	9%/"gy))H!'--0AQ' H 1  $$w	22JJ))->>#4WZZ5J5J#KH#U ',1IaLy}	>>)99%%'OOI.MMO''	2 ) >4	?22	?DN22r    c                 x   [        U5      S:X  a&  [        5       nUR                  [        S5      5        U$ US   R                  R                  5       nUSS  H,  nUR                  R                  5       R                  U5      nM.     U R                  R                  U R                  R                  XB5      5      $ )z
Synthesizes an efficient circuit from a sequence `run` of `DAGOpNode`s.

NOTE: Returns None when resynthesis is not possible.
r      N)
r(   r   add_qregr   r7   	to_matrixdotr   _gate_sequence_to_dag_resynthesize_run)r   r+   qubitr)   operatorgates         r   _resynthesize.Optimize1qGatesSimpleCommutation._resynthesize   s     s8q=,CLL+,Jq699&&(GDww((*..x8H 55..x?
 	
r    c                     U R                  US   U5      nUSS  H  nU R                  U5        M     UR                  5        Vs/ s H  oCUR                     PM     nn[	        X5        gs  snf )z}
Replaces a nonempty sequence `old_run` of `DAGNode`s, assumed to be a complete chain in
`dag`, with the circuit `new_circ`.
r   rJ   N)substitute_node_with_dagremove_op_nodetopological_op_nodes_node_idmov_list)r)   old_runnew_dagnode_mapnodespliced_runs         r   _replace_subdag0Optimize1qGatesSimpleCommutation._replace_subdag   so     //
GDABKDt$   <C;W;W;YZ;Y4.;YZ& [s   A+c           
         UR                  5       nSnU GH  n[        U5      nU/ :X  a  M  U R                  XU5      u  pg/ nU/ :w  a  U R                  Xe5      u  pU R                  XUSS9u  p/ nU
/ :w  a  U R                  XSS9u  p[UR	                  US   R
                  S   5      R                  nU R                  Xx-   U5      nU R                  X-   U5      nU R                  X\5      nU R                  R                  U=(       d    / U-   U
=(       d    / -   UR                  5       UR                  5       -   UR                  5       -   U R                  R                  UR	                  US   R
                  S   5      R                  5      (       d  GM  U(       a  Ub  U R                  XU5        U
(       a  Ub  U R                  XU5        Ub  U R                  XU5        SnGM     U$ )zv
Performs one full pass of optimization work.

Returns True if `dag` changed, False if no work on `dag` was possible.
F)r,   r   T)collect_1q_runsr   r3   rG   find_bitr'   indexrS   r   _substitution_checksop_nodes_basis_gatesr`   )r   r)   r*   did_workr+   r@   preceding_blockerpreceding_runcommuted_precedingsucceeding_blockersucceeding_runcommuted_succeedingrP   new_preceding_runnew_succeeding_runnew_runs                   r   _step&Optimize1qGatesSimpleCommutation._step   s    ""$CS	Iby 04/G/GSV/W,!#"040E0EFW0c-" 261I1I3e 2J 2. #%#151F1F& 2G 2.	
 LLQa177E $ 2 2=3UW\ ]!%!3!34G4XZ_!`((:G 44$"+~/CD!**,w/?/?/AADVD_D_Daa  --SV\\!_-33	  !%6%B((=NO!&8&D((>PQ&((7;S V r    c                 `     U R                  U5      nU R                  (       a  U(       d   U$ M.  )zc
Args:
    dag (DAGCircuit): the DAG to be optimized.

Returns:
    DAGCircuit: the optimized DAG.
)rs   r   )r   r)   ri   s      r   r+   $Optimize1qGatesSimpleCommutation.run   s,     zz#H**(
 r    )r   r   )NFN)T)__name__
__module____qualname____firstlineno____doc__r   staticmethodr3   rG   rS   r`   rs   r+   __static_attributes____classcell__)r   s   @r   r   r   /   s_     4  ( (4 -3 -3^
" ' '5n r    r   c                 2    U (       a  U S	 U (       a  M  X-  n g)z/
Replace `destination` in-place with `source`.
r   N )destinationsources     r   rZ   rZ     s    
 N +Kr    )r{   r   loggingcollectionsr   qiskit.dagcircuitr   qiskit.circuitr   %qiskit.circuit.library.standard_gatesr   r   r	   qiskit.transpiler.basepassesr
   ?qiskit.transpiler.passes.optimization.optimize_1q_decompositionr   	getLoggerrw   loggerr9   r   rZ   r   r    r   <module>r      s|    R    ( * A ' ; 
		8	$ tSk,-
dC[+, 	R'9 Rjr    