B
    [2                 @   s<  d Z ddl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mZmZ ddlmZ ddlmZ d	d
dddddgZe	dZe	dddgiefdZeresG dd	 d	eZdd
 Zn.ejZejjZejjZG dd	 d	eZdd
 Zi fddZd"ddZ G dd deZ!G dd deZ"G dd deZ#d#d!dZ$d S )$a  Matplotlib based plotting of quantum circuits.

Todo:

* Optimize printing of large circuits.
* Get this to work with single gates.
* Do a better job checking the form of circuits to make sure it is a Mul of
  Gates.
* Get multi-target gates plotting.
* Get initial and final states to plot.
* Get measurements to plot. Might need to rethink measurement as a gate
  issue.
* Get scale and figsize to be handled in a better way.
* Write some tests/examples!
    )print_functiondivision)Mul)range)import_module)GateOneQubitGateCGateCGateS)	BasicMeta)ManagedPropertiesCircuitPlotcircuit_plotlabellerMzMxCreateOneQubitGateCreateCGateZnumpy
matplotlibfromlistpyplot)Z__import__kwargsZcatchc               @   s   e Zd Zdd ZdS )r   c              O   s   t dd S )Nz"numpy or matplotlib not available.)ImportError)argskwargs r   @lib/python3.7/site-packages/sympy/physics/quantum/circuitplot.py__init__,   s    zCircuitPlot.__init__N)__name__
__module____qualname__r   r   r   r   r   r   +   s   c              O   s   t dd S )Nz"numpy or matplotlib not available.)r   )r   r   r   r   r   r   /   s    c               @   s   e Zd ZdZdZdZdZdZdZdZ	g Z
i ZdZdd Zd	d
 Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'S )(r   z$A class for managing a circuit plot.g      ?g      4@g?g333333?g      ?c             K   sP   || _ t| j j| _|| _| | |   |   |   | 	  | 
  d S )N)circuitlenr   ngatesnqubitsupdate_create_grid_create_figure_plot_wires_plot_gates_finish)selfcr#   r   r   r   r   r   F   s    
zCircuitPlot.__init__c             C   s   | j | dS )z'Load the kwargs into the instance dict.N)__dict__r$   )r*   r   r   r   r   r$   Q   s    zCircuitPlot.updatec             C   sF   | j }tjd| j| |td}tjd| j| |td}|| _|| _dS )zCreate the grid of wires.g        )ZdtypeN)scalenpZaranger#   floatr"   
_wire_grid
_gate_grid)r*   r-   Z	wire_gridZ	gate_gridr   r   r   r%   U   s
    zCircuitPlot._create_gridc             C   s   t j| j| j | j| j fddd| _| jjddddd}|  d| j }|| j	d | | j	d |  |
| jd | | jd |  |d	 || _d
S )z"Create the main matplotlib figure.w)ZfigsizeZ	facecolorZ	edgecolor   T)Zframeong      ?r   ZequalN)r   Zfigurer"   r-   r#   _figureZadd_subplotZset_axis_offZset_xlimr1   Zset_ylimr0   Z
set_aspect_axes)r*   Zaxoffsetr   r   r   r&   ]   s    

  
zCircuitPlot._create_figurec          
   C   s   | j d }| j d }|| j || j f}xt| jD ]}| j| | j| f}t||d| jd}| j| | j	r4d}| j
| j	| rd}| jj|d | j | |d t| j	| | j
| jdddd q4W |   dS )	z&Plot the wires of the circuit diagram.r   r4   k)colorlwg      ?center)sizer9   havaN)r1   r-   r   r#   r0   Line2D	linewidthr6   add_linelabelsinitsgettextlabel_bufferrender_labelfontsize_plot_measured_wires)r*   ZxstartxstopxdataiydatalineZinit_label_bufferr   r   r   r'   o   s(    


 zCircuitPlot._plot_wiresc             C   s,  |   }| jd }d}x^|D ]V}| j||  || j f}| j| | | j| | f}t||d| jd}| j| qW xt| 	 D ]\}}	t
|	tst
|	tr|	j|	j }
xv|
D ]n}||kr| j| | j||  krt|
t|
f}| j| | | j| | f}t||d| jd}| j| qW qW d S )Nr4   g{Gz?r8   )r9   r:   )_measurementsr1   r-   r0   r?   r@   r6   rA   	enumerate_gates
isinstancer	   r
   Zcontrolstargetsminmax)r*   
ismeasuredrJ   ZdyZimrK   rM   rN   rL   gZwiresZwirer   r   r   rI      s0    




z CircuitPlot._plot_measured_wiresc             C   sX   g }t | jtr<xBt| jjD ]}t |tr|| qW nt | jtrT|| j |S )z/Create a list of all gates in the circuit plot.)rR   r    r   reversedr   r   append)r*   ZgatesrW   r   r   r   rQ      s    
zCircuitPlot._gatesc             C   s*   x$t |  D ]\}}|| | qW dS )z0Iterate through the gates and plot each of them.N)rP   rQ   Z	plot_gate)r*   rL   Zgater   r   r   r(      s    zCircuitPlot._plot_gatesc             C   sd   i }xZt |  D ]J\}}t|ddrx4|jD ]*}||krP|| |krX|||< q.|||< q.W qW |S )zReturn a dict {i:j} where i is the index of the wire that has
            been measured, and j is the gate where the wire is measured.
            measurementF)rP   rQ   getattrrS   )r*   rV   rL   rW   targetr   r   r   rO      s    
zCircuitPlot._measurementsc             C   s"   x| j  D ]}|d qW d S )NF)r5   ZfindobjZset_clip_on)r*   or   r   r   r)      s    zCircuitPlot._finishc             C   sD   | j | }| j| }| jj|||dddtddd| jd| jd dS )z#Draw a box for a single qubit gate.r8   r;   r2   T)ecfcfillr:   )r9   r=   r>   bboxr<   N)r1   r0   r6   rE   dictr@   rH   )r*   tgate_idxwire_idxxyr   r   r   one_qubit_box   s    

zCircuitPlot.one_qubit_boxc             C   s\   | j | }| j| d }t| j  t| j | jj|||dddtddd| jd| jd}dS )	z?Draw a box for a two qubit gate. Doesn't work yet.
            g      ?r8   r;   r2   T)r^   r_   r`   r:   )r9   r=   r>   ra   r<   N)r1   r0   printr6   rE   rb   r@   rH   )r*   rc   rd   re   rf   rg   objr   r   r   two_qubit_box   s    


zCircuitPlot.two_qubit_boxc             C   sJ   | j | | j | f}| j| | j| f}t||d| jd}| j| dS )zDraw a vertical control line.r8   )r9   r:   N)r1   r0   r?   r@   r6   rA   )r*   rd   Zmin_wireZmax_wirerK   rM   rN   r   r   r   control_line   s    
zCircuitPlot.control_linec             C   sJ   | j | }| j| }| j}t||f|| j ddd| jd}| j| dS )zDraw a control point.r8   T)r^   r_   r`   r:   N)r1   r0   control_radiusCircler-   r@   r6   	add_patch)r*   rd   re   rf   rg   radiusr+   r   r   r   control_point   s    


zCircuitPlot.control_pointc             C   sr   | j | }| j| }| j}t||f|ddd| jd}| j| t||f|| || fd| jd}| j| dS )z7Draw a NOT gates as the circle with plus in the middle.r8   r2   F)r^   r_   r`   r:   )r9   r:   N)	r1   r0   
not_radiusrn   r@   r6   ro   r?   rA   )r*   rd   re   rf   rg   rp   r+   lr   r   r   	not_point   s     



zCircuitPlot.not_pointc             C   s   | j | }| j| }| j}t|| || f|| || fd| jd}t|| || f|| || fd| jd}| j| | j| dS )zDraw a swap point as a cross.r8   )r9   r:   N)r1   r0   
swap_deltar?   r@   r6   rA   )r*   rd   re   rf   rg   dl1l2r   r   r   
swap_point  s    



zCircuitPlot.swap_pointN)r   r   r   __doc__r-   rH   r@   rm   rr   ru   rB   rC   rF   r   r$   r%   r&   r'   rI   rQ   r(   rO   r)   rh   rk   rl   rq   rt   ry   r   r   r   r   r   9   s4   c             K   s   t | |f|S )ad  Draw the circuit diagram for the circuit with nqubits.

        Parameters
        ==========

        c : circuit
            The circuit to plot. Should be a product of Gate instances.
        nqubits : int
            The number of qubits to include in the circuit. Must be at least
            as big as the largest `min_qubits`` of the gates.
        )r   )r+   r#   r   r   r   r   r   '  s    c             C   s"   | | }|rd| |f S d|  S )zSlightly more flexible way to render labels.

    >>> from sympy.physics.quantum.circuitplot import render_label
    >>> render_label('q0')
    '$|q0\\rangle$'
    >>> render_label('q0', {'q0':'0'})
    '$|q0\\rangle=|0\\rangle$'
    z$|%s\rangle=|%s\rangle$z$|%s\rangle$)rD   )ZlabelrC   Zinitr   r   r   rG   5  s    	
rG   qc                s    fddt  D S )a  Autogenerate labels for wires of quantum circuits.

    Parameters
    ==========
    n : int
      number of qubits in the circuit
    symbol : string
      A character string to precede all gate labels. E.g. 'q_0', 'q_1', etc.

    >>> from sympy.physics.quantum.circuitplot import labeller
    >>> labeller(2)
    ['q_1', 'q_0']
    >>> labeller(3,'j')
    ['j_2', 'j_1', 'j_0']
    c                s    g | ]}d  | d f qS )z%s_%dr3   r   ).0rL   )nsymbolr   r   
<listcomp>S  s    zlabeller.<locals>.<listcomp>)r   )r}   r~   r   )r}   r~   r   r   C  s    c               @   s   e Zd ZdZdZd ZdZdS )r   zMock-up of a z measurement gate.

    This is in circuitplot rather than gate.py because it's not a real
    gate, it just draws one.
    TZM_zN)r   r   r   rz   rZ   	gate_namegate_name_latexr   r   r   r   r   U  s   c               @   s   e Zd ZdZdZd ZdZdS )r   zMock-up of an x measurement gate.

    This is in circuitplot rather than gate.py because it's not a real
    gate, it just draws one.
    TZM_xN)r   r   r   rz   rZ   r   r   r   r   r   r   r   _  s   c               @   s   e Zd ZdddZdS )r   Nc             C   s$   |s|}t | |d tf||dS )Nr   )r   r   )r   __new__r   )Zmclname	latexnamer   r   r   r   j  s    zCreateOneQubitGate.__new__)N)r   r   r   r   r   r   r   r   r   i  s   Nc                s"   |s| }t | |  fdd}|S )z5Use a lexical closure to make a controlled gate.
    c                s   t t|  |S )N)r	   tuple)Zctrlsr\   )onequbitgater   r   ControlledGatev  s    z#CreateCGate.<locals>.ControlledGate)r   )r   r   r   r   )r   r   r   p  s
    
)r{   )N)%rz   Z
__future__r   r   Zsympyr   Zsympy.core.compatibilityr   Zsympy.externalr   Zsympy.physics.quantum.gater   r   r	   r
   Zsympy.core.corer   Zsympy.core.assumptionsr   __all__r.   RuntimeErrorr   objectr   r   r   linesr?   Zpatchesrn   rG   r   r   r   r   r   r   r   r   r   <module>   sB   


 o


