B
    [                 @   s   d Z ddlmZmZ ddlmZmZmZmZ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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.
    )print_functiondivision)ExprMatrixexpIpiIntegerSymbol)range)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kZinst r)   8lib/python3.7/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#   C   s    zRkGate._eval_argsc             C   s
   | j d S )Nr    )label)selfr)   r)   r*   r(   I   s    zRkGate.kc             C   s   | j d d S )Nr    )r+   )r,   r)   r)   r*   targetsM   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_plotQ   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 )Nr1   r    r   r   z#Invalid format for the R_k gate: %r)r   r   r	   r   r   r(   NotImplementedError)r,   formatr)   r)   r*   get_target_matrixU   s    2zRkGate.get_target_matrixN)r1   )__name__
__module____qualname____doc__	gate_namer.   r$   classmethodr#   propertyr(   r-   r0   r4   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#   )r,   r&   r)   r)   r*   r#   b   s    
zFourier._eval_argsc             K   s   | j d|S )N)N)_represent_ZGate)r,   optionsr)   r)   r*   _represent_default_basisl   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>)r   )rA   )rD   rE   )rC   r*   rF      s   z,Fourier._represent_ZGate.<locals>.<listcomp>r   )
getr   
min_qubitsrE   rD   r   r   r+   r   r   )r,   Zbasisr>   r@   ZarrayFTZmatrixFTr)   )rD   rE   r*   r=   o   s$    


zFourier._represent_ZGatec             C   s   t | jd | jd S )Nr   r    )r   r+   )r,   r)   r)   r*   r-      s    zFourier.targetsc             C   s
   | j d S )Nr    )r+   )r,   r)   r)   r*   rH      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*   rE      s    zFourier.sizec             C   s   t dS )NrD   )r
   )r,   r)   r)   r*   rD      s    zFourier.omegaN)r5   r6   r7   r8   r:   r#   r?   r=   r;   r-   rH   rE   rD   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}xXtt||D ]F}t|| }x4t|| D ]$}t|| d t||d | }qFW q(W x2t|| d D ]}t|| || d | }qW |S )z%Decomposes QFT into elementary gates.r   r    r   )r+   reversedr   r   r   r   r   )r,   startfinishcircuitlevelrB   r)   r)   r*   	decompose   s    

(zQFT.decomposec             K   s   t |  | S )N)r   rN   )r,   Zqubitsr>   r)   r)   r*   _apply_operator_Qubit   s    zQFT._apply_operator_Qubitc             C   s
   t | j S )N)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   rE   )r,   r)   r)   r*   rD      s    z	QFT.omegaN)r5   r6   r7   r8   r9   r.   rN   rO   rP   r;   rD   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}x2t|| d D ]}t|| || d | }q*W xZt||D ]L}x:tt|| D ]&}t|| d t|| d | }qnW t|| }qXW |S )z&Decomposes IQFT into elementary gates.r   r    r   )r&   r   r   rI   r   r   r   )r,   rJ   rK   rL   rB   rM   r)   r)   r*   rN      s    

&zIQFT.decomposec             C   s
   t | j S )N)r   r&   )r,   r)   r)   r*   rP      s    zIQFT._eval_inversec             C   s   t dt t | j S )N)r   r   r   rE   )r,   r)   r)   r*   rD      s    z
IQFT.omegaN)
r5   r6   r7   r8   r9   r.   rN   rP   r;   rD   r)   r)   r)   r*   r      s   N)(r8   Z
__future__r   r   r1   r   r   r   r   r   r	   r
   Zsympy.core.compatibilityr   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?