U
    	-e                     @   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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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)   Z/var/www/html/Darija-Ai-Train/env/lib/python3.8/site-packages/sympy/physics/quantum/qft.pyr#   /   s     
zRkGate.__new__c                 C   s
   t |S N)r   r"   )r$   r%   r)   r)   r*   r"   D   s    zRkGate._eval_argsc                 C   s
   | j d S Nr   labelselfr)   r)   r*   r'   J   s    zRkGate.kc                 C   s   | j d d S r,   r-   r/   r)   r)   r*   targetsN   s    zRkGate.targetsc                 C   s   d| j t| jf S )Nz$%s_%s$)gate_name_latexstrr'   r/   r)   r)   r*   gate_name_plotR   s    zRkGate.gate_name_plotsympyc                 C   sJ   |dkr:t ddgdttdt t td| j  ggS td| d S )Nr5   r   r   r   z#Invalid format for the R_k gate: %r)r	   r   r   r   r   r'   NotImplementedError)r0   formatr)   r)   r*   get_target_matrixV   s
    2zRkGate.get_target_matrixN)r5   )__name__
__module____qualname____doc__	gate_namer2   r#   classmethodr"   propertyr'   r1   r4   r8   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"   )r0   r%   r)   r)   r*   r"   c   s    zFourier._eval_argsc                 K   s   | j d|S )N)N)_represent_ZGate)r0   optionsr)   r)   r*   _represent_default_basism   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rtt	d| jd  |}| j|k rt|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)rE   rH   rI   )rG   r*   rJ      s   z,Fourier._represent_ZGate.<locals>.<listcomp>r   )
getr   
min_qubitsrI   rH   rK   r	   r.   r   r   )r0   ZbasisrB   rD   ZarrayFTZmatrixFTr)   rL   r*   rA   p   s.    

 zFourier._represent_ZGatec                 C   s   t | jd | jd S )Nr   r   )rK   r.   r/   r)   r)   r*   r1      s    zFourier.targetsc                 C   s
   | j d S r,   r-   r/   r)   r)   r*   rN      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-   r/   r)   r)   r*   rI      s    zFourier.sizec                 C   s   t dS )NrH   r   r/   r)   r)   r*   rH      s    zFourier.omegaN)r9   r:   r;   r<   r>   r"   rC   rA   r?   r1   rN   rI   rH   r)   r)   r)   r*   r@   `   s   
	


r@   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.   reversedrK   r   r   r   r   )r0   startfinishcircuitlevelrF   r)   r)   r*   	decompose   s    

$zQFT.decomposec                 K   s   t |  | S r+   )r   rT   )r0   ZqubitsrB   r)   r)   r*   _apply_operator_Qubit   s    zQFT._apply_operator_Qubitc                 C   s
   t | j S r+   )r   r%   r/   r)   r)   r*   _eval_inverse   s    zQFT._eval_inversec                 C   s   t dt t | j S )Nr   r   r   r   rI   r/   r)   r)   r*   rH      s    z	QFT.omegaN)r9   r:   r;   r<   r=   r2   rT   rU   rV   r?   rH   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%   rK   r   rO   r   r   r   )r0   rP   rQ   rR   rF   rS   r)   r)   r*   rT      s    

$zIQFT.decomposec                 C   s
   t | j S r+   )r   r%   r/   r)   r)   r*   rV      s    zIQFT._eval_inversec                 C   s   t dt t | j S )NrW   r/   r)   r)   r*   rH      s    z
IQFT.omegaN)
r9   r:   r;   r<   r=   r2   rT   rV   r?   rH   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   __all__r   r   r@   r   r   r)   r)   r)   r*   <module>   s*   (3?