U
    ZÊ¹j  ã                   @   s  d Z ddlmZ ddlmZmZmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZ ddlmZmZmZmZmZmZmZm Z  ddl!m"Z" ddddgZ#G dd„ deƒZ$e$Z%G dd„ deƒZ&G dd„ de&ƒZ'G dd„ de&ƒZ(dS )at  An implementation of qubits and gates acting on them.

Todo:

* Update docstrings.
* Update tests.
* Implement apply using decompose.
* Implement represent using decompose or something smarter. For this to
  work we first have to implement represent for SWAP.
* Decide if we want upper index to be inclusive in the constructor.
* Fix the printing of Rk gates in plotting.
é    )ÚExpr)ÚIÚIntegerÚpi©ÚSymbol)Úexp)ÚMatrix©Úsqrt)Úqapply)ÚQuantumErrorÚQExpr)Úeye)Úmatrix_tensor_product)ÚGateÚHadamardGateÚSwapGateÚOneQubitGateÚCGateÚ	PhaseGateÚTGateÚZGate)ÚsignÚQFTÚIQFTÚRkGateÚRkc                   @   sZ   e Zd ZdZdZdZdd„ Zedd„ ƒZe	dd	„ ƒZ
e	d
d„ ƒZe	dd„ ƒZddd„ZdS )r   z This is the R_k gate of the QTF.r   ÚRc                 G   s‚   t |ƒdkrtd| ƒ‚|d }|d }|dkr8t|ƒS |dkrHt|ƒS |dkrXt|ƒS |  |¡}tj| f|žŽ }|  |¡|_	|S )Né   z)Rk gates only take two arguments, got: %rr   é   é   )
Úlenr   r   r   r   Ú
_eval_argsr   Ú__new__Z_eval_hilbert_spaceZhilbert_space)ÚclsÚargsÚtargetÚkÚinst© r*   úX/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/physics/quantum/qft.pyr$   1   s     ÿ
zRkGate.__new__c                 C   s
   t  |¡S ©N)r   r#   )r%   r&   r*   r*   r+   r#   F   s    zRkGate._eval_argsc                 C   s
   | j d S ©Nr    ©Úlabel©Úselfr*   r*   r+   r(   L   s    zRkGate.kc                 C   s   | j d d… S r-   r.   r0   r*   r*   r+   ÚtargetsP   s    zRkGate.targetsc                 C   s   d| j t| jƒf S )Nz$%s_%s$)Úgate_name_latexÚstrr(   r0   r*   r*   r+   Úgate_name_plotT   s    zRkGate.gate_name_plotÚsympyc                 C   sX   |dkrHt ddgdtt| jƒtdƒ t t tdƒt| jƒ  ƒggƒS td| ƒ‚d S )Nr6   r    r   r   z#Invalid format for the R_k gate: %r)	r	   r   r   r(   r   r   r   ÚabsÚNotImplementedError)r1   Úformatr*   r*   r+   Úget_target_matrixX   s
    @ÿzRkGate.get_target_matrixN)r6   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	gate_namer3   r$   Úclassmethodr#   Úpropertyr(   r2   r5   r:   r*   r*   r*   r+   r   ,   s   



c                   @   s\   e Zd ZdZedd„ ƒZdd„ Zdd„ Zedd	„ ƒZ	ed
d„ ƒZ
edd„ ƒZedd„ ƒZdS )ÚFourierz@Superclass of Quantum Fourier and Inverse Quantum Fourier Gates.c                 C   s:   t |ƒdkrtd| ƒ‚|d |d kr0tdƒ‚t |¡S )Nr   z*QFT/IQFT only takes two arguments, got: %rr   r    z!Start must be smaller than finish)r"   r   r   r#   )r1   r&   r*   r*   r+   r#   e   s    ÿzFourier._eval_argsc                 K   s   | j d|ŽS )N)N)Ú_represent_ZGate)r1   Úoptionsr*   r*   r+   Ú_represent_default_basiso   s    z Fourier._represent_default_basisc                    sª   |  dd¡}|dkrtdƒ‚|| jk r2td| ƒ‚| j‰| j‰ ‡ ‡fdd„tˆƒD ƒ}t|ƒ}| jd dkr„tt	d| jd  ƒ|ƒ}| j|k r¦t|t	d|| j  ƒƒ}|S )z:
            Represents the (I)QFT In the Z Basis
        Únqubitsr   z.The number of qubits must be given as nqubits.z2The number of qubits %r is too small for the gate.c                    s&   g | ]‰ ‡ ‡‡fd d„t ˆƒD ƒ‘qS )c                    s$   g | ]}ˆ|ˆ  ˆ  t ˆƒ ‘qS r*   r
   )Ú.0Úi)ÚjÚomegaÚsizer*   r+   Ú
<listcomp>‚   s   ÿ
ÿÿz7Fourier._represent_ZGate.<locals>.<listcomp>.<listcomp>)Úrange)rG   ©rJ   rK   )rI   r+   rL   ‚   s   ÿÿz,Fourier._represent_ZGate.<locals>.<listcomp>r   )
Úgetr   Ú
min_qubitsrK   rJ   rM   r	   r/   r   r   )r1   ZbasisrD   rF   ZarrayFTZmatrixFTr*   rN   r+   rC   r   s.    ÿ
ÿÿ
 ÿzFourier._represent_ZGatec                 C   s   t | jd | jd ƒS )Nr   r    )rM   r/   r0   r*   r*   r+   r2   �   s    zFourier.targetsc                 C   s
   | j d S r-   r.   r0   r*   r*   r+   rP   “   s    zFourier.min_qubitsc                 C   s   d| j d | j d   S )z"Size is the size of the QFT matrixr   r    r   r.   r0   r*   r*   r+   rK   —   s    zFourier.sizec                 C   s   t dƒS )NrJ   r   r0   r*   r*   r+   rJ   œ   s    zFourier.omegaN)r;   r<   r=   r>   r@   r#   rE   rC   rA   r2   rP   rK   rJ   r*   r*   r*   r+   rB   b   s   
	


rB   c                   @   s<   e Zd ZdZd Zd Zdd„ Zdd„ Zdd„ Ze	dd	„ ƒZ
d
S )r   z&The forward quantum Fourier transform.c                 C   sž   | j d }| j d }d}tt||ƒƒD ]B}t|ƒ| }t|| ƒD ]$}t|| d t||d ƒƒ| }qBq&t|| d ƒD ]}t|| || d ƒ| }qz|S )z%Decomposes QFT into elementary gates.r   r    r   )r/   ÚreversedrM   r   r   r   r   )r1   ÚstartÚfinishÚcircuitÚlevelrH   r*   r*   r+   Ú	decompose§   s    

$zQFT.decomposec                 K   s   t |  ¡ | ƒS r,   )r   rV   )r1   ZqubitsrD   r*   r*   r+   Ú_apply_operator_Qubit´   s    zQFT._apply_operator_Qubitc                 C   s
   t | jŽ S r,   )r   r&   r0   r*   r*   r+   Ú_eval_inverse·   s    zQFT._eval_inversec                 C   s   t dt t | j ƒS )Nr   ©r   r   r   rK   r0   r*   r*   r+   rJ   º   s    z	QFT.omegaN)r;   r<   r=   r>   r?   r3   rV   rW   rX   rA   rJ   r*   r*   r*   r+   r   ¡   s   c                   @   s4   e Zd ZdZd ZdZdd„ Zdd„ Zedd„ ƒZ	d	S )
r   z&The inverse quantum Fourier transform.z
{QFT^{-1}}c                 C   s    | j d }| j d }d}t|| d ƒD ]}t|| || d ƒ| }q(t||ƒD ]H}tt|| ƒƒD ]&}t|| d t|| d ƒƒ| }qft|ƒ| }qR|S )z&Decomposes IQFT into elementary gates.r   r    r   )r&   rM   r   rQ   r   r   r   )r1   rR   rS   rT   rH   rU   r*   r*   r+   rV   Å   s    

$zIQFT.decomposec                 C   s
   t | jŽ S r,   )r   r&   r0   r*   r*   r+   rX   Ò   s    zIQFT._eval_inversec                 C   s   t dt t | j ƒS )NéþÿÿÿrY   r0   r*   r*   r+   rJ   Õ   s    z
IQFT.omegaN)
r;   r<   r=   r>   r?   r3   rV   rX   rA   rJ   r*   r*   r*   r+   r   ¿   s   N))r>   Zsympy.core.exprr   Zsympy.core.numbersr   r   r   Zsympy.core.symbolr   Z&sympy.functions.elementary.exponentialr   Zsympy.matrices.denser	   Zsympy.functionsr   Zsympy.physics.quantum.qapplyr   Zsympy.physics.quantum.qexprr   r   Zsympy.matricesr   Z#sympy.physics.quantum.tensorproductr   Zsympy.physics.quantum.gater   r   r   r   r   r   r   r   Z$sympy.functions.elementary.complexesr   Ú__all__r   r   rB   r   r   r*   r*   r*   r+   Ú<module>   s,   (ü3?