
    z	i                     j    S 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   " S S	\5      rg
)?Cancel pairs of inverse gates exploiting commutation relations.    )SessionCommutationChecker)CircuitError)
DAGCircuit	DAGOpNode)Operator)matrix_equal)TransformationPassc                   \   ^  \ rS rSrSrSS\S\4U 4S jjjrS rS r	S r
S	\4S
 jrSrU =r$ )CommutativeInverseCancellation   r   matrix_based
max_qubitsc                 P   > Xl         X l        [        U l        [        TU ]  5         g)a  
Args:
    matrix_based: If ``True``, uses matrix representations to check whether two
        operations are inverse of each other. This makes the checks more powerful,
        and, in addition, allows canceling pairs of operations that are inverse up to a
        phase, while updating the global phase of the circuit accordingly.
        Generally this leads to more reductions at the expense of increased runtime.
    max_qubits: Limits the number of qubits in matrix-based commutativity and
        inverse checks.
N)_matrix_based_max_qubitsscccomm_checkersuper__init__)selfr   r   	__class__s      ڀ/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/transpiler/passes/optimization/commutative_inverse_cancellation.pyr   'CommutativeInverseCancellation.__init__   s$     *%    c                 L   [        U[        5      (       d  g[        UR                  SS5      (       d  UR                  S;   a  g[        USS5      (       a  gUR                  5       (       a  g[        UR                  SS5      b   UR                  R                  5       (       a  gg)z:Returns True if we should skip this node for the analysis.T
_directiveF>   delayresetmeasure	conditionNis_parameterized)
isinstancer   getattropnameis_control_flowr"   )r   nodes     r   
_skip_node)CommutativeInverseCancellation._skip_node*   s    $	** 477L%00DIIA^4^4d++!!477.5AdggF^F^F`F`r   c                 Z     UR                  5       nU$ ! [        [        4 a    Sn U$ f = f)zo
Returns an inverse of the given op, or ``None`` if the inverse
does not exist or is too expensive to compute.
N)inverser   AttributeError)r   r%   r,   s      r   _get_inverse+CommutativeInverseCancellation._get_inverse=   s9    	jjlG  n- 	G	s    **c                     SnX:H  nU(       dJ  U(       aC  [        U5      R                  n[        U5      R                  n0 n[        XgSUS9nU(       a  US   nXT4$ )a5  
Checks whether op1 and op2 are equal up to a phase, that is whether
``op2 = e^{i * d} op1`` for some phase difference ``d``.

If this is the case, we can replace ``op2 * op1^{-1}`` by ``e^{i * d} I``.

The output is a tuple representing whether the two ops
are equal up to a phase and that phase difference.
r   T)ignore_phasepropsphase_difference)r   datar	   )	r   op1op2r   r3   	are_equalmat1mat2r2   s	            r   _check_equal_upto_phase6CommutativeInverseCancellation._check_equal_upto_phaseI   s_     J	\C=%%DC=%%DE$Td%PI#();#< **r   dagc                    [        UR                  5       5      n[        U5      n[        U5       Vs/ s H  nSPM     nnSn[        SU5       GHW  nU R	                  X'   5      (       a  M  U R                  X'   R                  5      =nc  M@  U R                  =(       a    X'   R                  U R                  :*  n	Sn
[        US-
  SS5       H  nX[   (       a  M  U R	                  X+   5      (       dl  X+   R                  X'   R                  :X  aN  X+   R                  X'   R                  :X  a0  U R                  UX+   R                  U	5      u  pU(       a  Xm-  nUn
  O4U R                  R                  X'   X+   U R                  S9(       a  M    O   U
S:w  d  GMO  SXW'   SXZ'   GMZ     [        U5       H!  nX^   (       d  M  UR                  X.   5        M#     US:w  a  U=R                   U-  sl        U$ s  snf )z
Run the CommutativeInverseCancellation pass on `dag`.

Args:
    dag: the directed acyclic graph to run on.

Returns:
    DAGCircuit: Transformed DAG.
Fr      )max_num_qubitsT)listtopological_op_nodeslenranger)   r.   r%   r   
num_qubitsr   qargscargsr:   r   commute_nodesremove_op_nodeglobal_phase)r   r<   topo_sorted_nodes	circ_size_removedphase_updateidx1op1_inverser   matched_idx2idx2
is_inversephaseidxs                  r   run"CommutativeInverseCancellation.run_   s    !!9!9!;<)*	"'	"23"2Q5"23!Y'D0677#001B1H1K1KLLU ""]'8'>'I'ITM]M]']  LdQhB/= (9(?@@)/559J9P9V9VV)/559J9P9V9VV(,(D(D#)/22$)%J
 "$-'+((66%+%+#'#3#3 7  
 1 04 r! $(,%S (V #C||""#4#9: $ 1,
m 4s   G7)r   r   r   )F   )__name__
__module____qualname____firstlineno____doc__boolintr   r)   r.   r:   r   rW   __static_attributes____classcell__)r   s   @r   r   r      sA    IT s   &
+,Dz D Dr   r   N)r^   "qiskit.circuit.commutation_libraryr   r   qiskit.circuitr   qiskit.dagcircuitr   r   qiskit.quantum_infor   (qiskit.quantum_info.operators.predicatesr	   qiskit.transpiler.basepassesr
   r    r   r   <module>rj      s,    F O ' 3 ( A ;L%7 Lr   