U
    0e.                     @  s   d 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dd	d
ddgZedZedddgiefdZererejZejjZejjZG dd d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!
    )annotations)Mul)import_module)GateOneQubitGateCGateCGateSCircuitPlotcircuit_plotlabellerMzMxCreateOneQubitGateCreateCGateZnumpy
matplotlibfromlistpyplot)Zimport_kwargsZcatchc                   @  s   e Zd ZU dZdZdZdZdZdZdZ	g Z
ded< i Zde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)d* Zd+S ),r	   z$A class for managing a circuit plot.g      ?g      4@g?g333333?z	list[str]labelszdict[str, str]inits      ?c                 K  s`   t rtstd|| _t| jj| _|| _| | | 	  | 
  |   |   |   d S )Nz"numpy or matplotlib not available.)npr   ImportErrorcircuitlenargsngatesnqubitsupdate_create_grid_create_figure_plot_wires_plot_gates_finish)selfcr   kwargs r&   E/tmp/pip-unpacked-wheel-_6tpq7m6/sympy/physics/quantum/circuitplot.py__init__<   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   I   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)scaler   Zaranger   floatr   
_wire_grid
_gate_grid)r#   r*   Z	wire_gridZ	gate_gridr&   r&   r'   r   M   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frameonr   r   equalN)r   figurer   r*   r   _figureZadd_subplotZset_axis_offZset_xlimr-   Zset_ylimr,   Z
set_aspect_axes)r#   Zaxoffsetr&   r&   r'   r   U   s"      
  
zCircuitPlot._create_figurec              
   C  s   | j d }| j d }|| j || j f}t| jD ]}| j| | j| f}t||d| jd}| j| | j	r2d}| j
| j	| rd}| jj|d | j | |d t| j	| | j
| jdddd q2|   dS )	z&Plot the wires of the circuit diagram.r   r0   kcolorlwg      ?center)sizer8   havaN)r-   r*   ranger   r,   Line2D	linewidthr4   add_liner   r   gettextlabel_bufferrender_labelfontsize_plot_measured_wires)r#   ZxstartxstopxdataiydatalineZinit_label_bufferr&   r&   r'   r    g   s4    

     zCircuitPlot._plot_wiresc                 C  s  |   }| jd }d}|D ]V}| j||  || j f}| j| | | j| | f}t||d| jd}| j| qt| 	 D ]\}}	t
|	ttfr~|	j|	j }
|
D ]n}||kr| j| | j||  krt|
t|
f}| j| | | j| | f}t||d| jd}| j| qq~d S )Nr0   g{Gz?r6   r7   )_measurementsr-   r*   r,   r?   r@   r4   rA   	enumerate_gates
isinstancer   r   controlstargetsminmax)r#   
ismeasuredrH   ZdyZimrI   rK   rL   rJ   gZwiresZwirer&   r&   r'   rG   ~   s:    
  z CircuitPlot._plot_measured_wiresc                 C  sT   g }t | jtr8t| jjD ]}t |tr|| qnt | jtrP|| j |S )z/Create a list of all gates in the circuit plot.)rP   r   r   reversedr   r   append)r#   ZgatesrV   r&   r&   r'   rO      s    
zCircuitPlot._gatesc                 C  s&   t |  D ]\}}|| | qdS )z0Iterate through the gates and plot each of them.N)rN   rO   Z	plot_gate)r#   rJ   Zgater&   r&   r'   r!      s    zCircuitPlot._plot_gatesc                 C  s\   i }t |  D ]F\}}t|ddr|jD ]*}||krL|| |krT|||< q*|||< q*q|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)rN   rO   getattrrR   )r#   rU   rJ   rV   targetr&   r&   r'   rM      s    

zCircuitPlot._measurementsc                 C  s   | j  D ]}|d q
d S )NF)r3   ZfindobjZset_clip_on)r#   or&   r&   r'   r"      s    zCircuitPlot._finishc                 C  sB   | j | }| j| }| jj|||dddddd| jd| jd dS )z#Draw a box for a single qubit gate.r6   r:   r.   TZecZfcfillr9   )r8   r<   r=   Zbboxr;   N)r-   r,   r4   rC   r@   rF   )r#   tgate_idxwire_idxxyr&   r&   r'   one_qubit_box   s    

  zCircuitPlot.one_qubit_boxc                 C  s   t | j t | j dS )z<Draw a box for a two qubit gate. Does not work yet.
        N)printr-   r,   )r#   r_   r`   ra   r&   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.r6   r7   N)r-   r,   r?   r@   r4   rA   )r#   r`   Zmin_wireZmax_wirerI   rK   rL   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.r6   Tr]   N)r-   r,   control_radiusCircler*   r@   r4   	add_patch)r#   r`   ra   rb   rc   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.r6   r.   Fr]   r7   N)	r-   r,   
not_radiusri   r@   r4   rj   r?   rA   )r#   r`   ra   rb   rc   rk   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.r6   r7   N)r-   r,   
swap_deltar?   r@   r4   rA   )r#   r`   ra   rb   rc   dl1l2r&   r&   r'   
swap_point  s"    

zCircuitPlot.swap_pointN)__name__
__module____qualname____doc__r*   rF   r@   rh   rm   rp   r   __annotations__r   rD   r(   r   r   r   r    rG   rO   r!   rM   r"   rd   rf   rg   rl   ro   rt   r&   r&   r&   r'   r	   /   s4   
c                 K  s   t | |f|S )aE  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 )a  Slightly more flexible way to render labels.

    >>> from sympy.physics.quantum.circuitplot import render_label
    >>> render_label('q0')
    '$\\left|q0\\right\\rangle$'
    >>> render_label('q0', {'q0':'0'})
    '$\\left|q0\\right\\rangle=\\left|0\\right\\rangle$'
    z-$\left|%s\right\rangle=\left|%s\right\rangle$z$\left|%s\right\rangle$)rB   )labelr   initr&   r&   r'   rE   .  s    	
rE   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_%dr/   r&   ).0rJ   nsymbolr&   r'   
<listcomp>M  s     zlabeller.<locals>.<listcomp>)r>   r~   r&   r~   r'   r   <  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ru   rv   rw   rx   rY   	gate_namegate_name_latexr&   r&   r&   r'   r   O  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_xNr   r&   r&   r&   r'   r   Y  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   )typer   )Zmclname	latexnamer&   r&   r'   __new__d  s
    zCreateOneQubitGate.__new__)N)ru   rv   rw   r   r&   r&   r&   r'   r   c  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[   Zonequbitgater&   r'   ControlledGatep  s    z#CreateCGate.<locals>.ControlledGate)r   )r   r   r   r&   r   r'   r   j  s
    
)r|   )N)rx   
__future__r   Zsympy.core.mulr   Zsympy.externalr   Zsympy.physics.quantum.gater   r   r   r   __all__r   RuntimeErrorr   r   linesr?   Zpatchesri   r	   r
   rE   r   r   r   r   r   r   r&   r&   r&   r'   <module>   s>   
  r


