
    z	i&                        S r SSKJr  SSKrSSKrSSKJ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rS	S
KJrJr  \R,                  (       a  SSKJr   " S S\5      rg)zQDrift Class    )annotationsN)chain)Callable)QuantumCircuit)SparsePauliOp)QiskitError   )ProductFormulareorder_paulis)PauliEvolutionGatec                  v   ^  \ rS rSrSr       SSS.                 S	U 4S jjjjrS
S jrSrU =r$ )QDrift!   a\  The QDrift Trotterization method, which selects each term in the
Trotterization randomly, with a probability proportional to its weight. Based on the work
of Earl Campbell in Ref. [1].

References:
    [1]: E. Campbell, "A random compiler for fast Hamiltonian simulation" (2018).
    `arXiv:quant-ph/1811.08017 <https://arxiv.org/abs/1811.08017>`_
F"atomic_evolution_sparse_observablec                  > [         T	U ]  SUUUUUUUS9  SU l        [        R                  R                  U5      U l        g)a  
Args:
    reps: The number of times to repeat the Trotterization circuit.
    insert_barriers: Whether to insert barriers between the atomic evolutions.
    cx_structure: How to arrange the CX gates for the Pauli evolutions, can be
        ``"chain"``, where next neighbor connections are used, or ``"fountain"``, where all
        qubits are connected to one. This only takes effect when
        ``atomic_evolution is None``.
    atomic_evolution: A function to apply the evolution of a single
        :class:`~.quantum_info.Pauli`, or :class:`.SparsePauliOp` of only commuting terms,
        to a circuit. The function takes in three arguments: the circuit to append the
        evolution to, the Pauli operator to evolve, and the evolution time. By default, a
        single Pauli evolution is decomposed into a chain of ``CX`` gates and a single
        ``RZ`` gate.
    seed: An optional seed for reproducibility of the random sampling process.
    wrap: Whether to wrap the atomic evolutions into custom gate objects. This only takes
        effect when ``atomic_evolution is None``.
    preserve_order: If ``False``, allows reordering the terms of the operator to
        potentially yield a shallower evolution circuit. Not relevant
        when synthesizing operator with a single term.
    atomic_evolution_sparse_observable: If a custom ``atomic_evolution`` is passed,
        which does not yet support :class:`.SparseObservable`\ s as input, set this
        argument to ``False`` to automatically apply a conversion to :class:`.SparsePauliOp`.
        This argument is supported until Qiskit 2.2, at which point all atomic evolutions
        are required to support :class:`.SparseObservable`\ s as input.
r	   r   N)super__init__sampled_opsnprandomdefault_rngrng)
selfrepsinsert_barrierscx_structureatomic_evolutionseedwrappreserve_orderr   	__class__s
            [/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/synthesis/evolution/qdrift.pyr   QDrift.__init__+   sP    R 	/Q 	 		
  99((.    c                   UR                   nUR                  n[        U[        5      (       a>  [        [        R
                  " U Vs/ s H  oDR                  5       PM     sn5      5      nOUR                  5       n U VVs/ s H%  u    pg[        [        R                  " U5      5      PM'     nnn[        R                  " U5      n
[        R                  " U
5      n[        R                  " SUS-  -  US-  -  U R                   -  5      nU R"                  R%                  [        R&                  " U[(        S9U4X-  S9nSU-  U-  U-  nU Vs/ s H;  oS   US   [        R*                  " [        R,                  " US   5      5      U-  4PM=     nnU R.                  (       d  [1        U5      nU$ s  snf s  snnf ! [         a  n	[        S5      U	eS n	A	ff = fs  snf )Nz)QDrift requires bound, real coefficients.   )dtype)sizepr   r	   )operatortime
isinstancelistr   from_iterableto_sparse_listfloatr   real_if_close	TypeErrorr   abssummathceilr   r   choicearrayobjectrealsignr!   r   )r   	evolution	operatorsr,   oppaulis_coeffcoeffsexcweightslambd	num_gatessampledrescaled_timepaulisampled_pauliss                    r#   expandQDrift.expanda   s   &&	~~ i&&%--Y.WYr/@/@/BY.WXYF--/F	THNOAeB,,U34FO
 &&.wIIa5!8na8499DE	 ((//HHV6*) " 
 E	I-4Za
ZaQV1XuQxq):!;m!KLZa 	 
 ""+N;N; /X
 P 	TIJPSS	T 
s7   F2=F= ,F7.F= AG7F= =
GGG)r   r   )r	   Fr   NNFT)r   intr   boolr   strr   zYCallable[[QuantumCircuit, qiskit.quantum_info.Pauli | SparsePauliOp, float], None] | Noner   z
int | Noner    rO   r!   rO   r   rO   returnNone)r=   r   rQ   z#list[tuple[str, tuple[int], float]])	__name__
__module____qualname____firstlineno____doc__r   rL   __static_attributes____classcell__)r"   s   @r#   r   r   !   s      %# #4/ 494/4/ 4/ 	4/4/ 4/ 4/ 4/ -14/ 
4/ 4/l$ $r%   r   )rW   
__future__r   r6   typing	itertoolsr   collections.abcr   numpyr   qiskit.circuit.quantumcircuitr   qiskit.quantum_info.operatorsr   qiskit.exceptionsr   qiskit.quantum_infoqiskitproduct_formular
   r   TYPE_CHECKINGqiskit.circuit.libraryr   r    r%   r#   <module>rh      sE     "    $  8 7 )  ;	9d^ dr%   