
    z	i1                        S r SSKJr  SSKJr  SSKJrJrJr  SSK	J
r
  SSKJr  S rS	 rS
 r " S S\5      r " S S\5      rg)z(Polynomially controlled Pauli-rotations.    )annotations)product)QuantumRegisterQuantumCircuitGate)CircuitError   )FunctionalPauliRotationsc                    SU 4SU S4S0nSn[        SU S-  S-   5       H!  nX U-
  S-   -  U-  nU=XX-
  4'   XU-
  U4'   M#     U$ )zReturn a dictionary of binomial coefficients

Based-on/forked from sympy's binomial_coefficients() function [#]

.. [#] https://github.com/sympy/sympy/blob/sympy-1.5.1/sympy/ntheory/multinomial.py
r   r	      )range)ndatatempks       v/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py_binomial_coefficientsr      sp     FA1vq!DD1a1fqj!A	"q(*..X!eQh " K    c           	   #    #    U SU-  :  d  US:X  a*  [        X5      nUR                  5        H
  u  p4X44v   M     g[        X5      n0 nUR                  5        H  u  p4XE[        [        SU5      5      '   M     UnU/S/U S-
  -  -   n[        U5      n[        [        SU5      5      nXrU   4v   U(       a  Sn	OU n	XS-
  :  a|  Xi   n
U	(       a  SXi'   XS'   U
S:  a  XiS-   ==   S-  ss'   Sn	OU	S-  n	Xi==   S-  ss'   US==   S-  ss'   [        U5      n[        [        SU5      5      nXrU   4v   XS-
  :  a  M{  gg7f)zReturn an iterator of multinomial coefficients

Based-on/forked from sympy's multinomial_coefficients_iterator() function [#]

.. [#] https://github.com/sympy/sympy/blob/sympy-1.5.1/sympy/ntheory/multinomial.py
r   r	   Nr   )_multinomial_coefficientsitemstuplefilter)mr   coefficientskeyvaluecoefficients_dictr   temp_abjtemp_js              r   _large_coefficients_iterr#   *   sY     	1q5yAF06&,,.JC, / 16&,,.JC:?eF4$567 /(saSAE]"t&v&'A''AAa%iWF QzUq Q1GqLG4[FfT6*+A?++! a%is   D;E?Ec                   U (       d  U(       a  0 $ SS0$ U S:X  a  [        U5      $ U SU-  :  a  US:  a  [        [        X5      5      $ U(       a  SnOU nU/S/U S-
  -  -   n[        U5      S0nX S-
  :  a  X2   nU(       a  SX2'   XSS'   US:  a  X2S-   ==   S-  ss'   SnSnSnO$US-  nUS-   nU[        U5         nX2==   S-  ss'   [	        X`5       H6  nX8   (       d  M  X8==   S-  ss'   Xt[        U5         -  nX8==   S-  ss'   M8     US==   S-  ss'   Xu-  XS   -
  -  U[        U5      '   X S-
  :  a  M  U$ )zReturn an iterator of multinomial coefficients

Based-on/forked from sympy's multinomial_coefficients() function [#]

.. [#] https://github.com/sympy/sympy/blob/sympy-1.5.1/sympy/ntheory/multinomial.py
 r	   r   r   )r   dictr#   r   r   )	r   r   r!   r   resr"   startvr   s	            r   r   r   X   sg    IAwAv%a((AEza!e,Q2333!AD;
C
!e)DGGA:QK1KAEAFAEEE$K AGqLGuAww1t%%1	 !
 	Q1JAQK8E$K+ !e), Jr   c                     ^  \ rS rSrSr    S         SU 4S jjjr\SS j5       r\R                  SS j5       r\SS j5       r	S r
SSS jjrU 4S	 jrS
rU =r$ )PolynomialPauliRotations   a  A circuit implementing polynomial Pauli rotations.

For a polynomial :math:`p(x)`, a basis state :math:`|i\rangle` and a target qubit
:math:`|0\rangle` this operator acts as:

.. math::

    |i\rangle |0\rangle \mapsto \cos\left(\frac{p(i)}{2}\right) |i\rangle |0\rangle
    + \sin\left(\frac{p(i)}{2}\right) |i\rangle |1\rangle

Let n be the number of qubits representing the state, d the degree of p(x) and q_i the qubits,
where q_0 is the least significant qubit. Then for

.. math::

    x = \sum_{i=0}^{n-1} 2^i q_i,

we can write

.. math::

    p(x) = \sum_{j=0}^{j=d} c_j x^j

where :math:`c` are the input coefficients, ``coeffs``.
c                F   > U=(       d    SS/U l         [        TU ]	  XUS9  g)a1  
Args:
    num_state_qubits: The number of qubits representing the state.
    coeffs: The coefficients of the polynomial. ``coeffs[i]`` is the coefficient of the
        i-th power of x. Defaults to linear: [0, 1].
    basis: The type of Pauli rotation ('X', 'Y', 'Z').
    name: The name of the circuit.
r   r	   )num_state_qubitsbasisnameN)_coeffssuper__init__)selfr.   coeffsr/   r0   	__class__s        r   r3   !PolynomialPauliRotations.__init__   s*      '!Q 	*:dSr   c                    U R                   $ )a  The coefficients of the polynomial.

``coeffs[i]`` is the coefficient of the i-th power of the function input :math:`x`,
that means that the rotation angles are based on the coefficients value,
following the formula

.. math::

    c_j x^j ,  j=0, ..., d

where :math:`d` is the degree of the polynomial :math:`p(x)` and :math:`c` are the coefficients
``coeffs``.

Returns:
    The coefficients of the polynomial.
)r1   r4   s    r   r5   PolynomialPauliRotations.coeffs   s    $ ||r   c                0    U R                  5         Xl        g)zSet the coefficients of the polynomial.

``coeffs[i]`` is the coefficient of the i-th power of x.

Args:
    The coefficients of the polynomial.
N)_invalidater1   )r4   r5   s     r   r5   r:      s     	r   c                V    U R                   (       a  [        U R                   5      S-
  $ g)zReturn the degree of the polynomial, equals to the number of coefficients minus 1.

Returns:
    The degree of the polynomial. If the coefficients have not been set, return 0.
r	   r   )r5   lenr9   s    r   degreePolynomialPauliRotations.degree   s"     ;;t{{#a''r   c                R    Ub  [        USS9n[        SSS9nX#/U l        g/ U l        g)zReset the registers.Nstate)r0   r	   target)r   qregs)r4   r.   qr_state	qr_targets       r   _reset_registers)PolynomialPauliRotations._reset_registers   s2    '&'7gFH'9I".DJDJr   c                    SnU R                   c  SnU(       a  [        S5      eU R                  U R                   S-   :  a%  SnU(       a  [        SU R                   S-    S35      eU$ )z,Check if the current configuration is valid.TFz&The number of qubits has not been set.r	   z0Not enough qubits in the circuit, need at least .)r.   AttributeError
num_qubitsr   )r4   raise_on_failurevalids      r   _check_configuration-PolynomialPauliRotations._check_configuration   su      (E$%MNN??T22Q66E"F,,q014 
 r   c                   > U R                   (       a  g[        TU ]	  5         [        U R                  U R
                  U R                  5      nU R                  XR                  5        g)z(If not already built, build the circuit.N)		_is_builtr2   _buildPolynomialPauliRotationsGater.   r5   r/   appendqubits)r4   gater6   s     r   rS   PolynomialPauliRotations._build   sF    >>+D,A,A4;;PTPZPZ[D++&r   )r1   rD   )NNYpoly)
r.   z
int | Noner5   list[float] | Noner/   strr0   r\   returnNone)r]   list[float])r5   r_   r]   r^   )r]   int)T)rM   boolr]   ra   )__name__
__module____qualname____firstlineno____doc__r3   propertyr5   setterr?   rG   rO   rS   __static_attributes____classcell__r6   s   @r   r+   r+      s    8 (,%)T$T #T 	T
 T 
T T*  & ]]	 	  	&' 'r   r+   c                  \   ^  \ rS rSrSr   S         SU 4S jjjrS rS	S jrSrU =r	$ )
rT   i
  a~  A gate implementing polynomial Pauli rotations.

For a polynomial :math:`p(x)`, a basis state :math:`|i\rangle` and a target qubit
:math:`|0\rangle` this operator acts as:

.. math::

    |i\rangle |0\rangle \mapsto \cos\left(\frac{p(i)}{2}\right) |i\rangle |0\rangle
    + \sin\left(\frac{p(i)}{2}\right) |i\rangle |1\rangle

Let n be the number of qubits representing the state, d the degree of p(x) and q_i the qubits,
where q_0 is the least significant qubit. Then for

.. math::

    x = \sum_{i=0}^{n-1} 2^i q_i,

we can write

.. math::

    p(x) = \sum_{j=0}^{j=d} c_j x^j

where :math:`c` are the input coefficients, ``coeffs``.
c                z   > U=(       d    SS/U l         UR                  5       U l        [        TU ]  SUS-   / US9  g)a~  Prepare an approximation to a state with amplitudes specified by a polynomial.

Args:
    num_state_qubits: The number of qubits representing the state.
    coeffs: The coefficients of the polynomial. ``coeffs[i]`` is the coefficient of the
        i-th power of x. Defaults to linear: [0, 1].
    basis: The type of Pauli rotation ('X', 'Y', 'Z').
    label: A label for the gate.
r   r	   	PolyPauli)labelN)r5   lowerr/   r2   r3   )r4   r.   r5   r/   ro   r6   s        r   r3   %PolynomialPauliRotationsGate.__init__%  s>      &A[[]
&6&:BeLr   c                   [        U R                  5      nUR                  S U R                  S-
   nUR                  S   nU R                  5       nU R                  S:X  a   UR                  U R                  S   U5        OOU R                  S:X  a   UR                  U R                  S   U5        OUR                  U R                  S   U5        U GH&  n/ n[        U5       H"  u  pxXW   S:  d  M  UR                  X'   5        M$     [        U5      S:  ab  U R                  S:X  a  UR                  XE   Xc5        Ml  U R                  S:X  a  UR                  XE   Xc5        M  UR                  XE   Xc5        M  [        U5      S:X  d  M  U R                  S:X  a  UR                  XE   US   U5        M  U R                  S:X  a  UR!                  XE   US   U5        GM  UR#                  XE   US   U5        GM)     Xl        g )Nr	   xr   y)r   rL   rV   _get_rotation_coefficientsr/   rxr5   ryrz	enumeraterU   r>   mcrxmcrymcrzcrxcrycrz
definition)	r4   circuitrE   rF   rotation_coeffsc
qr_controli_s	            r   _define$PolynomialPauliRotationsGate._define9  s    1>>"7DOOa$78NN2&	99;::JJt{{1~y1ZZ3JJt{{1~y1JJt{{1~y1 AJ!!4!8%%hk2 %
 :"::$LL!3ZKZZ3&LL!3ZKLL!3ZKZA%::$KK 2JqM9MZZ3&KK 2JqM9MKK 2JqM9M+ !. "r   c                   U R                   S-
  n[        U R                  5      S-
  n[        [	        SS/US95      n/ nU H$  nS[        U5      s=:  a  U::  d  M  O  M  XE/-  nM&     U Vs0 s H  ofS_M     nn[        U R                  SS 5       Hq  u  pUS-  n[        X5      R                  5        HJ  u  pSnSn[        U
5       H!  u  pUS:  a  US-  nUSX-  -  -  nM  US	-  nM#     Xv==   X-  U-  -  ss'   ML     Ms     U$ s  snf )
zCompute the coefficient of each monomial.

Returns:
    A dictionary with pairs ``{control_state: rotation angle}`` where ``control_state``
    is a tuple of ``0`` or ``1`` bits.
r	   r   )repeatg        Nr%   )r	   r   )r   )	rL   r>   r5   listr   sumrz   r   r   )r4   r.   r?   all_combinationsvalid_combinationscombinationcontrol_stater   r   coeffcomb	num_combspowerr!   qubits                  r   rv   7PolynomialPauliRotationsGate._get_rotation_coefficients`  s:     ??Q.T[[!A%A7G HI+K3{#-v--"m3" , DVVCU-#-CUV "$++ab/2HAFA $==M#Q#W#W#Y13 )$HAqy%-qy!11%- !0  .%2Ce2KK. $Z	 3" ) Ws   -D
)r/   r5   r   )NrY   N)
r.   r`   r5   r[   r/   r\   ro   z
str | Noner]   r^   )r]   zdict[tuple[int, ...], float])
rb   rc   rd   re   rf   r3   r   rv   ri   rj   rk   s   @r   rT   rT   
  sd    : &* MM #M 	M
 M 
M M(%"N$ $r   rT   N)rf   
__future__r   	itertoolsr   qiskit.circuitr   r   r   qiskit.circuit.exceptionsr   functional_pauli_rotationsr
   r   r#   r   r+   rT   r%   r   r   <module>r      sK    / "  @ @ 2 @ +,\+\A'7 A'Hz4 zr   