
    z	iK                        S r SSKJr  SSKrSSKJr  SSKrSSKJ	r	  SSK
JrJrJrJr  SSKJr  SSKJr  S	S
KJrJr   " S S\5      r " S S\5      rg)z=Piecewise polynomial Chebyshev approximation to a given f(x).    )annotationsN)Callable)	Chebyshev)QuantumCircuitQuantumRegisterAncillaRegisterGate)BlueprintCircuit)CircuitError   )!PiecewisePolynomialPauliRotations%PiecewisePolynomialPauliRotationsGatec                    ^  \ rS rSrSr    S           SU 4S jjjrSSS jjr\SS j5       r\R                  SS j5       r\SS j5       r
\
R                  SS j5       r
\SS	 j5       r\R                  SS
 j5       r\SS j5       r\R                  SS j5       r\SS j5       r\R                  SS j5       rSS jrU 4S jrSrU =r$ )PiecewiseChebyshev   a  Piecewise Chebyshev approximation to an input function.

For a given function :math:`f(x)` and degree :math:`d`, this class implements a piecewise
polynomial Chebyshev approximation on :math:`n` qubits to :math:`f(x)` on the given intervals.
All the polynomials in the approximation are of degree :math:`d`.

The values of the parameters are calculated according to [1] and see [2] for a more
detailed explanation of the circuit construction and how it acts on the qubits.

Examples:

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

    import numpy as np
    from qiskit import QuantumCircuit
    from qiskit.circuit.library.arithmetic.piecewise_chebyshev import PiecewiseChebyshev
    f_x, degree, breakpoints, num_state_qubits = lambda x: np.arcsin(1 / x), 2, [2, 4], 2
    pw_approximation = PiecewiseChebyshev(f_x, degree, breakpoints, num_state_qubits)
    pw_approximation._build()
    qc = QuantumCircuit(pw_approximation.num_qubits)
    qc.h(list(range(num_state_qubits)))
    qc.append(pw_approximation.to_instruction(), qc.qubits)
    qc.draw(output='mpl')

References:

[1] Haener, T., Roetteler, M., & Svore, K. M. (2018).
Optimizing Quantum Circuits for Arithmetic.
`arXiv:1805.12445 <http://arxiv.org/abs/1805.12445>`_

[2] Carrera Vazquez, A., Hiptmair, H., & Woerner, S. (2022).
Enhancing the Quantum Linear Systems Algorithm Using Richardson Extrapolation.
`ACM Transactions on Quantum Computing 3, 1, Article 2 <https://doi.org/10.1145/3490631>`_
c                   > [         TU ]  US9  SU l        Xl        Ub  UOSU l        Ub  UOS/U l        SU l        X@l        g)a  
Args:
    f_x: the function to be approximated. Constant functions should be specified
     as f_x = constant.
    degree: the degree of the polynomials.
        Defaults to ``1``.
    breakpoints: the breakpoints to define the piecewise-linear function.
        Defaults to the full interval.
    num_state_qubits: number of qubits representing the state.
    name: The name of the circuit object.
nameNr   r   )super__init___num_state_qubits_f_x_degree_breakpoints_polynomialsnum_state_qubits)selff_xdegreebreakpointsr   r   	__class__s         o/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/circuit/library/arithmetic/piecewise_chebyshev.pyr   PiecewiseChebyshev.__init__E   sS    & 	d# "& 	!'!3v+6+BK6: 0    c                   SnU R                   c  SnU(       a  [        S5      eU R                  c  SnU(       a  [        S5      eU R                  c  SnU(       a  [        S5      e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.TFz1The function to be approximated has not been set.z/The degree of the polynomials has not been set.z"The breakpoints have not been set.z&The number of qubits has not been set.r   z0Not enough qubits in the circuit, need at least .)r   AttributeErrorr   r   r   
num_qubitsr   )r   raise_on_failurevalids      r"   _check_configuration'PiecewiseChebyshev._check_configurationf   s    99E$%XYY<<E$%VWW$E$%IJJ  (E$%MNN??T22Q66E"F,,q014 
 r$   c                    U R                   $ )zPThe function to be approximated.

Returns:
    The function to be approximated.
)r   r   s    r"   r   PiecewiseChebyshev.f_x   s     yyr$   c                    U R                   b  XR                   :w  a2  U R                  5         Xl         U R                  U R                  5        gg)zSet the function to be approximated.

Note that this may change the underlying quantum register, if the number of state qubits
changes.

Args:
    f_x: The new function to be approximated.
N)r   _invalidate_reset_registersr   )r   r   s     r"   r   r/      sA     99yy 0I!!$"7"78	 !1r$   c                    U R                   $ )zLThe degree of the polynomials.

Returns:
    The degree of the polynomials.
)r   r.   s    r"   r   PiecewiseChebyshev.degree   s     ||r$   c                    U R                   b  XR                   :w  a2  U R                  5         Xl         U R                  U R                  5        gg)zSet the error tolerance.

Note that this may change the underlying quantum register, if the number of state qubits
changes.

Args:
    degree: The new degree.
N)r   r1   r2   r   )r   r   s     r"   r   r4      sA     <<6\\#9!L!!$"7"78	 $:r$   c                    U R                   nU R                  b,  SU R                  -  nUS   U:  a  X/-   nUS   S:  a  S/U-   nU$ )zpThe breakpoints for the piecewise approximation.

Returns:
    The breakpoints for the piecewise approximation.
   r   )r   r   )r   r    
num_statess      r"   r    PiecewiseChebyshev.breakpoints   se     ''   ,D111J 2+)L8 1~! cK/r$   c                    U R                   b  XR                   :w  a9  U R                  5         Ub  UOS/U l         U R                  U R                  5        gg)zSet the breakpoints for the piecewise approximation.

Note that this may change the underlying quantum register, if the number of state qubits
changes.

Args:
    breakpoints: The new breakpoints for the piecewise approximation.
Nr   )r   r1   r2   r   )r   r    s     r"   r    r:      sR     $7H7H(H/:/FQCD!!$"7"78	 )Ir$   c           	        U R                   c  / /$ U R                  nUS/:X  a  SSU R                   -  /n[        U5      n/ n[        SUS-
  5       H  n [	        U R
                  [        [        45      (       a  UR                  U R
                  /5        MG  [        R                  " U R
                  U R                  X   XS-      /S9nSUR                  [        R                  R                  S9R                   -  nUR                  UR#                  5       5        M     US
   SU R                   -  :  a  US[        R,                  " S5      -  //-   nUS   S:  a  S[        R,                  " S5      -  //U-   nU$ ! [$         a;  n['        SU R
                  R(                  R*                  S   -   S-   S	-   5      UeSnAff = f)The polynomials for the piecewise approximation.

Returns:
    The polynomials for the piecewise approximation.

Raises:
    TypeError: If the input function is not in the correct format.
Nr   r7   r   domainkind5 <lambda>() missing 1 required positional argument: ''.< Constant functions should be specified as 'f_x = constant'.r8   )r   r   lenrange
isinstancer   floatintappendr   interpolater   convertnp
polynomial
Polynomialcoeftolist
ValueError	TypeError__code__co_varnamesarcsin)r   r    num_intervalspolynomialsipolyerrs          r"   rX   PiecewiseChebyshev.polynomials   s      (4K
 ''1#a!6!667KK( q-!+,Adhh55&&z2$00$++{~{WXSXGY6ZD t||1I1I|JOOOD&&t{{}5 -0 r?Q 5 555%!biil*:);(<<K q>A		!,-.<K!  Khh''33A67 UU
 s    AE?BE??
G	6F??Gc                    U R                   b  XR                   :w  a2  U R                  5         Xl         U R                  U R                  5        gg)zSet the polynomials for the piecewise approximation.

Note that this may change the underlying quantum register, if the number of state qubits
changes.

Args:
    polynomials: The new breakpoints for the piecewise approximation.
N)r   r1   r2   r   )r   rX   s     r"   rX   r\     sG     $7H7H(H +!!$"7"78	 )Ir$   c                    U R                   $ )zoThe number of state qubits representing the state :math:`|x\rangle`.

Returns:
    The number of state qubits.
)r   r.   s    r"   r   #PiecewiseChebyshev.num_state_qubits+  s     %%%r$   c                    U R                   b  XR                   :w  aD  U R                  5         Xl         Ub  U R                  c  SSU-  /U l        U R	                  U5        gg)zSet the number of state qubits.

Note that this may change the underlying quantum register, if the number of state qubits
changes.

Args:
    num_state_qubits: The new number of qubits.
Nr   r7   )r   r1   r   r    r2   )r   r   s     r"   r   r_   4  si     !!)-=AWAW-W%5"  +0A0A0I$%q*:':#; !!"23 .Xr$   c                    / U l         UbF  [        US5      n[        SS5      nX#/U l         UnUS:  a  [        U5      nU R                  U5        ggg)zReset the registers.Nstater   targetr   )qregsr   r   add_register)r   r   qr_state	qr_targetnum_ancillas
qr_ancillas         r"   r2   #PiecewiseChebyshev._reset_registersH  sa    
'&'7AH'84I".DJ+La,\:
!!*-   (r$   c                  > U R                   (       a  g[        TU ]	  5         [        R                  " 5          [        R
                  " S[        SS9  [        U R                  U R                  U R                  U R                  S9nSSS5        U R                  WR                  5       U R                  5        g! , (       d  f       N9= f)znBuild the circuit if not already build. The operation is considered successful
when q_objective is :math:`|1>`Nignoreqiskit)categorymoduler   )	_is_builtr   _buildwarningscatch_warningsfilterwarningsDeprecationWarningr   r   r    rX   r   rJ   to_gatequbits)r   poly_rr!   s     r"   rq   PiecewiseChebyshev._buildV  s     >> $$&##H7IRZ[6%%t'7'79I9IPTPYPYF ' 	FNN$dkk2 '&s   AB99
C)r   r   r   r   r   r    r   rd   )NNNpw_cheb)r   float | Callable[[int], float]r   
int | Noner    list[int] | Noner   r|   r   strreturnNone)T)r)   boolr   r   )r   r{   )r   z%float | Callable[[int], float] | Noner   r   )r   rI   )r   r|   r   r   )r   z	list[int])r    r}   r   r   )r   zlist[list[float]])rX   zlist[list[float]] | Noner   r   )r   r|   r   r   )__name__
__module____qualname____firstlineno____doc__r   r+   propertyr   setterr   r    rX   r   r2   rq   __static_attributes____classcell__r!   s   @r"   r   r      sT   #P "(,'+1+1 1 &	1
 %1 1 
1 1B D   	ZZ9 9   ]]9 9  , 9 9 7 7r 9 9 & & 4 4&.3 3r$   r   c                  \   ^  \ rS rSrSr   S           SU 4S jjjrS rS rSrU =r	$ )	PiecewiseChebyshevGateii  a  Piecewise Chebyshev approximation to an input function.

For a given function :math:`f(x)` and degree :math:`d`, this class implements a piecewise
polynomial Chebyshev approximation on :math:`n` qubits to :math:`f(x)` on the given intervals.
All the polynomials in the approximation are of degree :math:`d`.

The values of the parameters are calculated according to [1] and see [2] for a more
detailed explanation of the circuit construction and how it acts on the qubits.

Examples:

    .. plot::
       :alt: Example of generating a circuit with the piecewise Chebyshev gate.
       :include-source:

        import numpy as np
        from qiskit import QuantumCircuit
        from qiskit.circuit.library.arithmetic import PiecewiseChebyshevGate

        f_x, num_state_qubits, degree, breakpoints = lambda x: np.arcsin(1 / x), 2, 2, [2, 4]
        pw_approximation = PiecewiseChebyshevGate(f_x, num_state_qubits, degree, breakpoints)

        qc = QuantumCircuit(pw_approximation.num_qubits)
        qc.h(list(range(num_state_qubits)))
        qc.append(pw_approximation, qc.qubits)
        qc.draw(output="mpl")

References:

[1] Haener, T., Roetteler, M., & Svore, K. M. (2018).
Optimizing Quantum Circuits for Arithmetic.
`arXiv:1805.12445 <http://arxiv.org/abs/1805.12445>`_

[2] Carrera Vazquez, A., Hiptmair, H., & Woerner, S. (2022).
Enhancing the Quantum Linear Systems Algorithm Using Richardson Extrapolation.
`ACM Transactions on Quantum Computing 3, 1, Article 2 <https://doi.org/10.1145/3490631>`_
c                  > Xl         Ub  UOSU l        X l        Uc  S/nSU-  nUS   U:  a  XF/-   nUS   S:  a  S/U-   nX@l        [	        [        U5      S:  5      n[        TU ]  SX'-   S-   / U5        U R                  5       U l	        g)a  
Args:
    f_x: the function to be approximated. Constant functions should be specified
     as f_x = constant.
    num_state_qubits: number of qubits representing the state.
    degree: the degree of the polynomials.
        Defaults to ``1``.
    breakpoints: the breakpoints to define the piecewise-linear function.
        Defaults to the full interval.
    label: A label for the gate.
Nr   r   r7   r8   r   )
r   r   r   r    rI   rE   r   r   _build_polynomialsrX   )	r   r   r   r   r    labelr9   num_comparer!   s	           r"   r   PiecewiseChebyshevGate.__init__  s    (  & 2f 0 #K ((
r?Z'%4K q>A#+K&#k*Q./-/?/MPQ/QSUW\]  224r$   c           	     d   U R                   nU R                  S-
  nUS/:X  a  SSU-  /n[        U5      n/ n[        SUS-
  5       H  n [	        U R
                  [        [        45      (       a  UR                  U R
                  /5        MG  [        R                  " U R
                  U R                  X   XS-      /S9nSUR                  [        R                  R                  S9R                   -  nUR                  UR#                  5       5        M     US
   SU-  :  a  US[        R,                  " S5      -  //-   nUS   S:  a  S[        R,                  " S5      -  //U-   nU$ ! [$         a;  n['        SU R
                  R(                  R*                  S   -   S-   S-   5      UeS	nAff = f)r=   r   r   r7   r>   r@   rB   rC   rD   Nr8   )r    r(   rE   rF   rG   r   rH   rI   rJ   r   rK   r   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   )r   r    r   rW   rX   rY   rZ   r[   s           r"   r   )PiecewiseChebyshevGate._build_polynomials  s    &&  ??Q.1#a!112KK( q-!+,Adhh55&&z2$00$++{~{WXSXGY6ZD t||1I1I|JOOOD&&t{{}5 -0 r?Q 000%!biil*:);(<<K q>A		!,-.<K!  Khh''33A67 UU
 s    
AE*BE**
F/46F**F/c                    [        U R                  U R                  U R                  5      n[	        UR
                  5      U l        U R                  R                  XR                  R                  5        g )N)	r   r   r    rX   r   r(   
definitionrJ   rw   )r   rx   s     r"   _definePiecewiseChebyshevGate._define  sU    6!!4#3#3T5E5E
 )):):;v'='=>r$   )r    r   r   r   r   rX   )NNN)r   r{   r   rI   r   r|   r    r}   r   z
str | Noner   r   )
r   r   r   r   r   r   r   r   r   r   r   s   @r"   r   r   i  si    $T "(, +5++5 +5 	+5
 &+5 +5 
+5 +5Z7r? ?r$   r   )r   
__future__r   rr   typingr   numpyrM   numpy.polynomial.chebyshevr   qiskit.circuitr   r   r   r	   'qiskit.circuit.library.blueprintcircuitr
   qiskit.circuit.exceptionsr   $piecewise_polynomial_pauli_rotationsr   r   r   r    r$   r"   <module>r      sI    D "    0 Q Q D 2G3) G3T
S?T S?r$   